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

documentation rewrite #43

Merged
merged 1 commit into from
Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 7 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,12 @@
[![Documentation](https://docs.rs/rfd/badge.svg)](https://docs.rs/rfd)
[![dependency status](https://deps.rs/crate/rfd/0.6.4/status.svg)](https://deps.rs/crate/rfd/0.6.4)

Rusty file dialogs for Windows, Linux (GTK), MacOS And WASM32.
Rusty File Dialogs is a cross platform Rust library for using native file open/save dialogs.
It provides both asynchronous and synchronous APIs. Supported platforms:

# Why RFD?
* Windows
* macOS
* Linux & BSDs (GTK3 or XDG Desktop Portal)
* WASM32 (async only)

- It uses 100% native API on all platforms, it does not spawn any processes in the background.
- It supports async/await syntax
- And if one day you decide to port your program to browser, WASM support is there for you!

# Dependencies
#### On Linux:
###### For GTK version:
- GTK3 development libraries (on debian `libgtk-3-dev` on arch `gtk3`)
###### For XFG Portal version (in case you out-out of GTK version):
- XDG Portal provider of you choice has to be present on the system. (Most distros have one by default)

# Features
- `parent` Adds a dialog parenting support via `raw-window-handle`
- `gtk3` Uses GTK for dialogs, if you know for sure that your users have XDG Portal around you can safely disable this, and drop C dependency

# Example

```rust
// Sync Dialog
let files = FileDialog::new()
.add_filter("text", &["txt", "rs"])
.add_filter("rust", &["rs", "toml"])
.set_directory("/")
.pick_file();

// Async Dialog
let file = AsyncFileDialog::new()
.add_filter("text", &["txt", "rs"])
.add_filter("rust", &["rs", "toml"])
.set_directory("/")
.pick_file()
.await;

let data = file.read().await;
```

# State

![GitHub Workflow Status](https://img.shields.io/github/workflow/status/PolyMeilex/rfd/Rust/master?style=flat-square)

| API Stability |
| ------------- |
| 🚧 |

| Feature | Linux | Windows | MacOS | Wasm32 |
| ------------ | ----- | ------- | --------- | ------ |
| SingleFile |||||
| MultipleFile |||||
| PickFolder |||||
| SaveFile |||||
| | | | | |
| Filters |||||
| StartingPath |||||
| Async |||||

### Difference between `MacOS Windowed App` and `MacOS NonWindowed App`

- Macos async dialog requires a started `NSApplication` instance, so dialog is truly async only when opened in windowed env like `winit`,`SDL2`, etc. otherwise it will fallback to sync dialog.
- It is also recommended to spawn dialogs on main thread, RFD can run dialogs from any thread but it is only possible in windowed app and it adds a little bit of overhead. So it is recommended to: [spawn on main and await in other thread](https://github.com/PolyMeilex/rfd/blob/master/examples/async.rs)
- NonWindowed apps will never be able to spawn dialogs from threads diferent than main
- NonWindowed apps will never be able to spawn async dialogs

# rfd-extras

AKA features that are not file related

| Feature | Linux | Windows | MacOS | Wasm32 |
| ------------- | ----- | ------- | ----- | ------ |
| MessageDialog |||||
| PromptDialog | | | | |
| ColorPicker | | | | |
Refer to the [documentation](https://docs.rs/rfd) for more details.
88 changes: 40 additions & 48 deletions src/file_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ pub(crate) struct Filter {
pub extensions: Vec<String>,
}

/// ## Synchronous File Dialog
/// #### Supported Platforms:
/// - Linux
/// - Windows
/// - Mac
/// Synchronous File Dialog. Supported platforms:
/// * Linux
/// * Windows
/// * Mac
#[derive(Default, Debug, Clone)]
pub struct FileDialog {
pub(crate) filters: Vec<Filter>,
Expand All @@ -41,9 +40,9 @@ impl FileDialog {
///
/// Takes in the name of the filter, and list of extensions
///
/// #### Name of the filter will be displayed on supported platforms
/// - Windows
/// - Linux
/// The name of the filter will be displayed on supported platforms:
/// * Windows
/// * Linux
///
/// On platforms that don't support filter names, all filters will be merged into one filter
pub fn add_filter(mut self, name: &str, extensions: &[&str]) -> Self {
Expand All @@ -54,31 +53,28 @@ impl FileDialog {
self
}

/// Set starting directory of the dialog.
/// #### Supported Platforms:
/// - Linux
/// - Windows
/// - Mac
/// Set starting directory of the dialog. Supported platforms:
/// * Linux ([GTK only](https://github.com/PolyMeilex/rfd/issues/42))
/// * Windows
/// * Mac
pub fn set_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
self.starting_directory = Some(path.as_ref().into());
self
}

/// Set starting file name of the dialog.
/// #### Supported Platforms:
/// - Windows
/// - Linux
/// - Mac
/// Set starting file name of the dialog. Supported platforms:
/// * Windows
/// * Linux
/// * Mac
pub fn set_file_name(mut self, file_name: &str) -> Self {
self.file_name = Some(file_name.into());
self
}

/// Set the title of the dialog.
/// #### Supported Platforms:
/// - Windows
/// - Linux
/// - Mac (Only below version 10.11)
/// Set the title of the dialog. Supported platforms:
/// * Windows
/// * Linux
/// * Mac (Only below version 10.11)
pub fn set_title(mut self, title: &str) -> Self {
self.title = Some(title.into());
self
Expand Down Expand Up @@ -115,7 +111,7 @@ impl FileDialog {
/// Opens save file dialog
///
/// #### Platform specific notes regarding save dialog filters:
/// - On MacOs
/// - On macOS
/// - If filter is set, all files will be grayed out (no matter the extension sadly)
/// - If user does not type an extension MacOs will append first available extension from filters list
/// - If user types in filename with extension MacOs will check if it exists in filters list, if not it will display appropriate message
Expand All @@ -132,12 +128,11 @@ impl FileDialog {
}
}

/// ## Asynchronous File Dialog
/// #### Supported Platforms:
/// - Linux
/// - Windows
/// - Mac
/// - WASM32
/// Asynchronous File Dialog. Supported platforms:
/// * Linux
/// * Windows
/// * Mac
/// * WASM32
#[derive(Default, Debug, Clone)]
pub struct AsyncFileDialog {
file_dialog: FileDialog,
Expand All @@ -153,41 +148,38 @@ impl AsyncFileDialog {
///
/// Takes in the name of the filter, and list of extensions
///
/// #### Name of the filter will be displayed on supported platforms
/// - Windows
/// - Linux
/// The name of the filter will be displayed on supported platforms:
/// * Windows
/// * Linux
///
/// On platforms that don't support filter names, all filters will be merged into one filter
pub fn add_filter(mut self, name: &str, extensions: &[&str]) -> Self {
self.file_dialog = self.file_dialog.add_filter(name, extensions);
self
}

/// Set starting directory of the dialog.
/// #### Supported Platforms:
/// - Linux
/// - Windows
/// - Mac
/// Set starting directory of the dialog. Supported platforms:
/// * Linux ([GTK only](https://github.com/PolyMeilex/rfd/issues/42))
/// * Windows
/// * Mac
pub fn set_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
self.file_dialog = self.file_dialog.set_directory(path);
self
}

/// Set starting file name of the dialog.
/// #### Supported Platforms:
/// - Windows
/// - Linux
/// - Mac
/// Set starting file name of the dialog. Supported platforms:
/// * Windows
/// * Linux
/// * Mac
pub fn set_file_name(mut self, file_name: &str) -> Self {
self.file_dialog = self.file_dialog.set_file_name(file_name);
self
}

/// Set the title of the dialog.
/// #### Supported Platforms:
/// - Windows
/// - Linux
/// - Mac (Only below version 10.11)
/// Set the title of the dialog. Supported platforms:
/// * Windows
/// * Linux
/// * Mac (Only below version 10.11)
pub fn set_title(mut self, title: &str) -> Self {
self.file_dialog = self.file_dialog.set_title(title);
self
Expand Down
115 changes: 115 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,118 @@
//! Rusty File Dialogs is a cross platform library for using native file open/save dialogs.
//! It provides both asynchronous and synchronous APIs. Supported platforms:
//!
//! * Windows
//! * macOS
//! * Linux & BSDs (GTK3 or XDG Desktop Portal)
//! * WASM32 (async only)
//!
//! # Examples
//!
//! ## Synchronous
//! ```no_run
//! use rfd::FileDialog;
//!
//! let files = FileDialog::new()
//! .add_filter("text", &["txt", "rs"])
//! .add_filter("rust", &["rs", "toml"])
//! .set_directory("/")
//! .pick_file();
//! ```
//!
//! ## Asynchronous
//! ```no_run
//! use rfd::AsyncFileDialog;
//!
//! let future = async {
//! let file = AsyncFileDialog::new()
//! .add_filter("text", &["txt", "rs"])
//! .add_filter("rust", &["rs", "toml"])
//! .set_directory("/")
//! .pick_file()
//! .await;
//!
//! let data = file.unwrap().read().await;
//! };
//! ```
//!
//! # Linux & BSD backends
//!
//! On Linux & BSDs, two backends are available, one using the [GTK3 Rust bindings](https://gtk-rs.org/)
//! and the other using the [XDG Desktop Portal](https://github.com/flatpak/xdg-desktop-portal)
//! D-Bus API through [ashpd](https://github.com/bilelmoussaoui/ashpd) &
//! [zbus](https://gitlab.freedesktop.org/dbus/zbus/).
//!
//! ## GTK backend
//! The GTK backend is used with the `gtk3` Cargo feature which is enabled by default. The GTK3
//! backend requires the C library and development headers to be installed to build RFD. The package
//! names on various distributions are:
//!
//! | Distribution | Package name |
//! | --------------- | ------------ |
//! | Fedora | gtk3-devel |
//! | Arch | gtk3 |
//! | Debian & Ubuntu | libgtk-3-dev |
//!
//! ## XDG Desktop Portal backend
//! The XDG Desktop Portal backend is used when the `gtk3` feature is disabled with
//! [`default-features = false`](https://doc.rust-lang.org/cargo/reference/features.html#dependency-features). This backend will use either the GTK or KDE file dialog depending on the desktop environment
//! in use at runtime. It does not have any non-Rust
//! build dependencies, however it requires the user to have either the
//! [GTK](https://github.com/flatpak/xdg-desktop-portal-gtk),
//! [GNOME](https://gitlab.gnome.org/GNOME/xdg-desktop-portal-gnome), or
//! [KDE](https://invent.kde.org/plasma/xdg-desktop-portal-kde/) XDG Desktop Portal backend installed
//! at runtime. These are typically installed by the distribution together with the desktop environment.
//! If you are packaging an application that uses RFD, ensure either one of these is installed
//! with the package. The
//! [wlroots portal backend](https://github.com/emersion/xdg-desktop-portal-wlr) does not implement the
//! D-Bus API that RFD requires (it does not interfere with the other portal implementations;
//! they can all be installed simultaneously).
//!
//! The XDG Desktop Portal has no API for message dialogs, so the [MessageDialog] and
//! [AsyncMessageDialog] structs will not build with this backend.
//!
//! # macOS non-windowed applications, async, and threading
//!
//! macOS async dialogs require an `NSApplication` instance, so the dialog is only truly async when
//! opened in windowed environment like `winit` or `SDL2`. Otherwise, it will fallback to sync dialog.
//! It is also recommended to spawn dialogs on your main thread. RFD can run dialogs from any thread
//! but it is only possible in a windowed app and it adds a little bit of overhead. So it is recommended
//! to [spawn on main and await in other thread](https://github.com/PolyMeilex/rfd/blob/master/examples/async.rs).
//! Non-windowed apps will never be able to spawn async dialogs or from threads other than the main thread.
//!
//! # Cargo features
//! * `parent`: Adds a dialog parenting support via [raw-window-handle](https://github.com/rust-windowing/raw-window-handle).
//! [Not yet implemented](https://github.com/bilelmoussaoui/ashpd/issues/40) for XDG Desktop Portal
//! backend.
//! * `gtk3`: Uses GTK for dialogs on Linux & BSDs; has no effect on Windows and macOS
//!
//! # State
//!
//! | API Stability |
//! | ------------- |
//! | 🚧 |
//!
//! | Feature | Linux | Windows | MacOS | Wasm32 |
//! | ------------ | ----- | ------- | --------- | ------ |
//! | SingleFile | ✔ | ✔ | ✔ | ✔ |
//! | MultipleFile | ✔ | ✔ | ✔ | ✔ |
//! | PickFolder | ✔ | ✔ | ✔ | ✖ |
//! | SaveFile | ✔ | ✔ | ✔ | ✖ |
//! | | | | | |
//! | Filters | ✔ ([GTK only](https://github.com/PolyMeilex/rfd/issues/42)) | ✔ | ✔ | ✔ |
//! | StartingPath | ✔ | ✔ | ✔ | ✖ |
//! | Async | ✔ | ✔ | ✔ | ✔ |
//!
//! # rfd-extras
//!
//! AKA features that are not file related
//!
//! | Feature | Linux | Windows | MacOS | Wasm32 |
//! | ------------- | ----- | ------- | ----- | ------ |
//! | MessageDialog | ✔ (GTK only) | ✔ | ✔ | ✔ |
//! | PromptDialog | | | | |
//! | ColorPicker | | | | |

mod backend;

mod file_handle;
Expand Down
12 changes: 10 additions & 2 deletions src/message_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ use std::future::Future;
#[cfg(feature = "parent")]
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};

/// ## Synchronous Message Dialog
/// Synchronous Message Dialog. Supported platforms:
/// * Windows
/// * macOS
/// * Linux (GTK only)
/// * WASM
#[derive(Default, Debug, Clone)]
pub struct MessageDialog {
pub(crate) title: String,
Expand Down Expand Up @@ -77,7 +81,11 @@ impl MessageDialog {
}
}

/// ## Asynchronous Message Dialog
/// Asynchronous Message Dialog. Supported platforms:
/// * Windows
/// * macOS
/// * Linux (GTK only)
/// * WASM
#[derive(Default, Debug, Clone)]
pub struct AsyncMessageDialog(MessageDialog);

Expand Down