Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: Support choosing file formats in the file dialog. #998

Closed
xStrom opened this issue May 30, 2020 · 5 comments · Fixed by #1847
Closed

macOS: Support choosing file formats in the file dialog. #998

xStrom opened this issue May 30, 2020 · 5 comments · Fixed by #1847
Labels
D-Medium requires some research and thinking help wanted has no one working on it yet missing a feature is missing on a specific platform shell/mac concerns the macOS backend

Comments

@xStrom
Copy link
Member

xStrom commented May 30, 2020

When a user is saving a file they should be able to choose from among the supported file formats.
The Windows and GTK implementations already support this and other apps on macOS support this.

file-formats

According to Apple's Human Interface Guidelines this should be possible even without a custom extension.

Let the user choose an output format if your app can save in multiple file formats. Output formats, when present, are displayed via a pop-up button beneath the output location.

It's unclear how these output formats can be specified. NSSavePanel only seems to have allowedFileTypes which we are using already. However the way we are using them is just an array of strings, so we couldn't even specify the format name like Rich Text Document.

The allowedFileTypes also seems to support UTIs. Would we get the format selection if we defined UTIs? Are there other ways to get the format selection?

@xStrom xStrom added help wanted has no one working on it yet shell/mac concerns the macOS backend D-Medium requires some research and thinking missing a feature is missing on a specific platform labels May 30, 2020
@malleusinferni
Copy link

Some light research suggests that the popup menu must be created manually, supplied to the save panel as an accessoryView, and equipped with callbacks that modify allowedFileTypes with the selected extension. I tried creating a simple counterexample from system-defined UTIs, but the format selection menu did not appear.

@xStrom
Copy link
Member Author

xStrom commented Jun 16, 2020

It's definitely possible via an accessory view, but the reason I'm thinking it might be possible in another way is the wording of the Human Interface Guidelines. At the end of that page the accessory view extending and the format pop-up are described separately.

Of course this might also be a another Catalina thing, where previously the pop-up showed up without an accessory view but that's no longer the case in Catalina. Would need someone with an older macOS to comment on that.

@terhechte
Copy link
Contributor

I started working on this and have a implementation that fulfills the requirement:

Screen Shot 2021-07-02 at 11 41 21

There is a way to get this behaviour for free, but only if the application uses NSDocument. Otherwise, one has to build this using custom UI (e.g. a NSView, a NSTextField, and a NSPopupButton).

While I have the UI working, I have trouble returning the proper result. On macOS, such a dialog results in two pieces of data:

  • The selected file path
  • The selected file format

However, the FileInfo struct only has one piece of data:

/// Information about the path to be opened or saved.
///
/// This path might point to a file or a directory.
#[derive(Debug, Clone)]
pub struct FileInfo {
    pub(crate) path: PathBuf,
}

So how do I coalesce these two data into one. My initial approach was to take the path and replace the extension with the chosen extension from the file format. However, this omits crucial data. There might be situations where the file ending is the same, but the file data is different depending on the output format. E.g. I'm generating HTML and the output formats are "HTML with Javascript" and "HTML without Javascript". Or Blender files they're always .blend but can be blender 2, blender 2.4, blender 2.6, etc. Now, I can't think of a great example of similar file extensions with different data, but you get the gist.

So the other option would be to expand FileInfo:

pub struct FileInfo {
    pub(crate) path: PathBuf,
    pub(crate) format: FileSpec
}

But this would be breaking and surely affect the other platforms. I didn't look into it yet but I'd just imagine that the file choosers on other platforms don't let you access the chosen format after the fact. So I'd just go with the rewritten output path instead of opting for the additional format complexity, but I still wanted to raise the point.

I'll post a link to the interim branch once I'm done cleaning it up.

@cmyr
Copy link
Member

cmyr commented Jul 2, 2021

I'm okay with modifying FileInfo to include additional information, even if this isn't used consistently on all platforms. I would maybe consider making the field, Option<FileSpec>, or similar? It would be an opportunity for the platform to provide additional information about how the file should be saved, and I think this is totally reasonable.

What would be most important is documenting this. I think that we should try to provide as much information as possible in PathBuf (e.g. give it a useful extension) and then have FileSpec be purely additive; if you ignore it you should still be likely to do something reasonable.

@terhechte
Copy link
Contributor

I've updated the branch accordingly and tried to add documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
D-Medium requires some research and thinking help wanted has no one working on it yet missing a feature is missing on a specific platform shell/mac concerns the macOS backend
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants