Skip to content

Commit bc0d1fb

Browse files
authored
Merge pull request #1 from emoon/refactor
Big refactor Added proper Result type No unwrapping inside the open dialog functions. It now returns a correct restult type instead Added the nfd sources that is built using the gcc crate instead of having the user compile the code manually Added DialogBuilder to make it nicer to construct dialogs with filters and paths Added builder_open_jpg example which uses the builder code and only allows for opening of jpg files Fixed issue focus issue for Mac dialogs: Outlined here mlabbe/nativefiledialog#7 Support for multi open + example
2 parents 0f903f9 + 83edcb2 commit bc0d1fb

File tree

18 files changed

+1926
-87
lines changed

18 files changed

+1926
-87
lines changed

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "nfd"
3-
version = "0.0.1"
4-
authors = ["Saurav Sachidanand <[email protected]>"]
3+
version = "0.0.2"
4+
authors = ["Saurav Sachidanand <[email protected]>", "Daniel Collin <daniel@collin>"]
55

66
license = "MIT"
77
repository = "https://www.github.com/saurvs/nfd-rs"
@@ -11,5 +11,6 @@ keywords = ["file", "dialog", "ui"]
1111

1212
build = "build.rs"
1313

14-
[dependencies]
15-
libc = "0.2.7"
14+
[build-dependencies]
15+
gcc = "0.3"
16+

README.md

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22

33
`nfd-rs` is a Rust binding to the library [nativefiledialog](https://github.com/mlabbe/nativefiledialog), that provides a convenient cross-platform interface to opening file dialogs on Linux, OS X and Windows.
44

5-
Currently, only single file and save dialogs are supported, and the crate has been tested only on OS X. And yes, APIs may break with newer versions.
5+
This crate has been tested on Mac, Window and Linux (Ubuntu 14.04) and supports single/mutliple and save dialogs, notice APIs may break with newer versions.
66

77
## Usage
88

9-
* Follow the instructions [here](https://github.com/mlabbe/nativefiledialog/blob/master/README.md) to build the libraries in C and an OS-specific language. Then, set the `NFD_LIB_DIR` environment variable to the path of the directory in which the libraries are stored.
10-
119
* Add the dependency `nfd` in your ```Cargo.toml```
1210
```toml
1311
[dependencies]
@@ -18,18 +16,37 @@ Currently, only single file and save dialogs are supported, and the crate has be
1816
```rust
1917
extern crate nfd;
2018

21-
use nfd::*;
19+
use nfd::Response
2220

2321
fn main() {
2422

25-
let result = open_file_dialog(None, None);
23+
let result = nfd::open_file_dialog(None, None).unwrap_or_else(|e| {
24+
panic!(e);
25+
});
2626

2727
match result {
28-
NFDResult::Okay(file_path) => println!("File path = {:?}", file_path),
29-
NFDResult::Cancel => println!("User canceled"),
30-
NFDResult::Error(error) => println!("Error: {}", error),
28+
Response::Okay(file_path) => println!("File path = {:?}", file_path),
29+
Response::Cancel => println!("User canceled"),
3130
}
31+
}
32+
```
33+
34+
* Open a multi file dialog using builder with jpg files as filter
35+
```rust
36+
extern crate nfd;
3237

38+
use nfd::Response
39+
40+
fn main() {
41+
42+
let result = nfd::dialog_multiple().filter("jpg").open().unwrap_or_else(|e| {
43+
panic!(e);
44+
});
45+
46+
match result {
47+
Response::OkayMultiple(files) => println!("Files {:?}", files),
48+
Response::Cancel => println!("User canceled"),
49+
}
3350
}
3451
```
3552

build.rs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,51 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2020
THE SOFTWARE.
2121
*/
2222

23+
extern crate gcc;
2324
use std::env;
25+
use std::process::Command;
2426

2527
fn main() {
26-
let ndf_lib_dir = env::var("NFD_LIB_DIR").unwrap();
27-
println!("cargo:rustc-link-search=native={}",ndf_lib_dir);
28-
println!("cargo:rustc-link-lib=static=nfd");
29-
println!("cargo:rustc-link-lib=framework=AppKit");
28+
let mut cfg = gcc::Config::new();
29+
let env = env::var("TARGET").unwrap();
30+
31+
cfg.file("nfd/src/nfd_common.c");
32+
33+
if env.contains("darwin") {
34+
cfg.file("nfd/src/nfd_cocoa.m");
35+
cfg.compile("libnfd.a");
36+
println!("cargo:rustc-link-lib=framework=AppKit");
37+
} else if env.contains("windows") {
38+
cfg.file("nfd/src/nfd_win.cpp");
39+
cfg.compile("libnfd.a");
40+
println!("cargo:rustc-link-lib=ole32");
41+
// MinGW doesn't link it by default
42+
println!("cargo:rustc-link-lib=uuid");
43+
} else {
44+
let pkg_output = Command::new("pkg-config")
45+
.arg("--cflags")
46+
.arg("gtk+-3.0")
47+
.arg("glib-2.0")
48+
.arg("--libs")
49+
.arg("glib-2.0")
50+
.output();
51+
match pkg_output {
52+
Ok(output) => {
53+
let t = String::from_utf8(output.stdout).unwrap();
54+
let flags = t.split(" ");
55+
for flag in flags {
56+
if flag != "\n" && flag != "" {
57+
cfg.flag(flag);
58+
}
59+
}
60+
}
61+
_ => (),
62+
}
63+
cfg.file("nfd/src/nfd_gtk.c");
64+
cfg.compile("libnfd.a");
65+
println!("cargo:rustc-link-lib=gdk-3");
66+
println!("cargo:rustc-link-lib=gtk-3");
67+
println!("cargo:rustc-link-lib=glib-2.0");
68+
println!("cargo:rustc-link-lib=gobject-2.0");
69+
}
3070
}

examples/builder_open_jpg.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
extern crate nfd;
2+
3+
use nfd::Response;
4+
5+
fn main() {
6+
let result = nfd::dialog().filter("jpg").open().unwrap_or_else(|e| {
7+
panic!(e);
8+
});
9+
10+
match result {
11+
Response::Okay(file_path) => println!("File path = {:?}", file_path),
12+
Response::Cancel => println!("User canceled"),
13+
_ => (),
14+
}
15+
}

examples/example.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ THE SOFTWARE.
2222

2323
extern crate nfd;
2424

25-
use nfd::*;
25+
use nfd::Response;
2626

2727
fn main() {
28-
let result = open_file_dialog(None, None);
28+
let result = nfd::open_file_dialog(None, None).unwrap_or_else(|e| {
29+
panic!(e);
30+
});
2931

3032
match result {
31-
NFDResult::Okay(file_path) => println!("File path = {:?}", file_path),
32-
NFDResult::Cancel => println!("User canceled"),
33-
NFDResult::Error(error) => println!("Error: {}", error),
33+
Response::Okay(file_path) => println!("File path = {:?}", file_path),
34+
Response::Cancel => println!("User canceled"),
35+
_ => (),
3436
}
3537
}

examples/open_multiple.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
extern crate nfd;
2+
3+
use nfd::Response;
4+
5+
fn main() {
6+
let result = nfd::dialog_multiple().open().unwrap_or_else(|e| {
7+
panic!(e);
8+
});
9+
10+
match result {
11+
Response::OkayMultiple(files) => println!("File path = {:?}", files),
12+
Response::Cancel => println!("User canceled"),
13+
_ => (),
14+
}
15+
}

nfd/LICENSE

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
This software is provided 'as-is', without any express or implied
2+
warranty. In no event will the authors be held liable for any damages
3+
arising from the use of this software.
4+
5+
Permission is granted to anyone to use this software for any purpose,
6+
including commercial applications, and to alter it and redistribute it
7+
freely, subject to the following restrictions:
8+
9+
1. The origin of this software must not be misrepresented; you must not
10+
claim that you wrote the original software. If you use this software
11+
in a product, an acknowledgment in the product documentation would be
12+
appreciated but is not required.
13+
2. Altered source versions must be plainly marked as such, and must not be
14+
misrepresented as being the original software.
15+
3. This notice may not be removed or altered from any source distribution.
16+

nfd/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Native File Dialog #
2+
3+
A tiny, neat C library that portably invokes native file open and save dialogs. Write dialog code once and have it pop up native dialogs on all supported platforms. Avoid linking large dependencies like wxWidgets and qt.
4+
5+
Features:
6+
7+
- Lean C API, static library -- no ObjC, no C++, no STL.
8+
- Zlib licensed.
9+
- Consistent UTF-8 support on all platforms.
10+
- Simple universal file filter syntax.
11+
- Paid support available.
12+
- Multiple file selection support.
13+
- 64-bit and 32-bit friendly.
14+
- GCC, Clang and Visual Studio supported.
15+
- No third party dependencies.
16+
- Support for Vista's modern `IFileDialog` on Windows.
17+
- Support for non-deprecated Cocoa APIs on OS X.
18+
- GTK+3 dialog on Linux.
19+
- Tested, works alongside [http://www.libsdl.org](SDL2) on all platforms, for the game developers out there.
20+
21+
# Example Usage #
22+
23+
```C
24+
#include <nfd.h>
25+
#include <stdio.h>
26+
#include <stdlib.h>
27+
28+
int main( void )
29+
{
30+
nfdchar_t *outPath = NULL;
31+
nfdresult_t result = NFD_OpenDialog( NULL, NULL, &outPath );
32+
33+
if ( result == NFD_OKAY ) {
34+
puts("Success!");
35+
puts(outPath);
36+
free(outPath);
37+
}
38+
else if ( result == NFD_CANCEL ) {
39+
puts("User pressed cancel.");
40+
}
41+
else {
42+
printf("Error: %s\n", NFD_GetError() );
43+
}
44+
45+
return 0;
46+
}
47+
```
48+
49+
See [NFD.h](src/include/nfd.h) for more options.
50+
51+
# Screenshots #
52+
53+
![Windows 8 rendering an IFileOpenDialog](screens/open_win8.png?raw=true)
54+
![GTK3 on Linux](screens/open_gtk3.png?raw=true)
55+
![Cocoa on Yosemite](screens/open_cocoa.png?raw=true)
56+
57+
58+
## Building ##
59+
60+
NFD uses [SCons](http://www.scons.org) for cross-platform builds. After installing SCons, build it with:
61+
62+
cd src
63+
scons debug=[0,1]
64+
65+
Alternatively, you can avoid Scons by just including NFD files to your existing project:
66+
67+
1. Add all header files in `src/` and `src/include` to your project.
68+
2. Add `src/include` to your include search path or copy it into your existing search path.
69+
3. Add `src/nfd_common.c` to your project.
70+
4. Add `src/nfd_<platform>` to your project, where `<platform>` is the NFD backend for the platform you are fixing to build.
71+
5. On Visual Studio, define `_CRT_SECURE_NO_WARNINGS` to avoid warnings.
72+
73+
### Compiling Your Programs ###
74+
75+
1. Add `src/include` to your include search path.
76+
2. Add `nfd.lib` to the list of list of static libraries to link against.
77+
3. Add `src/` to the library search path.
78+
79+
On Linux, you must compile and link against GTK+. Recommend use of `pkg-config --cflags --libs gtk+-3.0`.
80+
81+
On Mac OS X, add `AppKit` to the list of frameworks.
82+
83+
On Windows, ensure you are building against `comctl32.lib`.
84+
85+
## Usage ##
86+
87+
See `NFD.h` for API calls. See `tests/*.c` for example code.
88+
89+
See `tests/SConstruct` for a working build script that compiles on all platforms.
90+
91+
## File Filter Syntax ##
92+
93+
There is a form of file filtering in every file dialog, but no consistent means of supporting it. NFD provides support for filtering files by groups of extensions, providing its own descriptions (where applicable) for the extensions.
94+
95+
A wildcard filter is always added to every dialog.
96+
97+
### Separators ###
98+
99+
- `;` Begin a new filter.
100+
- `,` Add a separate type to the filter.
101+
102+
#### Examples ####
103+
104+
`txt` The default filter is for text files. There is a wildcard option in a dropdown.
105+
106+
`png,jpg;psd` The default filter is for png and jpg files. A second filter is available for psd files. There is a wildcard option in a dropdown.
107+
108+
`NULL` Wildcard only.
109+
110+
## Iterating Over PathSets ##
111+
112+
See [test_opendialogmultiple.c](test/test_opendialogmultiple.c).
113+
114+
# Known Limitations #
115+
116+
I accept quality code patches, or will resolve these and other matters through support.
117+
118+
- No support for Windows XP's legacy dialogs such as `GetOpenFileName`.
119+
- No support for file filter names -- ex: "Image Files" (*.png, *.jpg). Nameless filters are supported, though.
120+
- No support for selecting folders instead of files.
121+
- On Linux, GTK+ cannot be uninitialized to save memory. Launching a file dialog costs memory. I am open to accepting an alternative `nfd_zenity.c` implementation which uses Zenity and pipes.
122+
123+
# Copyright and Credit #
124+
125+
Copyright &copy; 2014 [Frogtoss Games](http://www.frogtoss.com), Inc.
126+
File [LICENSE](LICENSE) covers all files in this repo.
127+
128+
Native File Dialog by Michael Labbe
129+
130+
131+
Tomasz Konojacki for [microutf8](http://puszcza.gnu.org.ua/software/microutf8/)
132+
133+
## Support ##
134+
135+
Directed support for this work is available from the original author under a paid agreement.
136+
137+
[Contact Frogtoss Games](http://www.frogtoss.com/pages/contact.html).

nfd/src/common.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Native File Dialog
3+
4+
Internal, common across platforms
5+
6+
http://www.frogtoss.com/labs
7+
*/
8+
9+
10+
#ifndef _NFD_COMMON_H
11+
#define _NFD_COMMON_H
12+
13+
#define NFD_MAX_STRLEN 256
14+
#define _NFD_UNUSED(x) ((void)x)
15+
16+
void *NFDi_Malloc( size_t bytes );
17+
void NFDi_Free( void *ptr );
18+
void NFDi_SetError( const char *msg );
19+
void NFDi_SafeStrncpy( char *dst, const char *src, size_t maxCopy );
20+
21+
#endif

0 commit comments

Comments
 (0)