-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
File dialogs and drag-and-drop of files #270
Comments
I would like to contribute on this one. Going with something based on On the other hand if we go with platform specific dialogs then that would show a familiar open dialog to the user.
Maybe we should just go with this native-dialog crate? |
If opening a file dialog on web is easy then maybe it can just be added to |
I should mention: I tried using |
For note, this is caused by the windows COM, it has to be initialized in either, essentially, single-threaded or multi-threaded mode, however some COM objects only work properly in one mode or the other (usually sound annoyingly, needs multithreaded), and dragging and dropping with 'extended' clipboard attributes is one such annoyance (needs single-threaded). To see details about the issue and how winit deals with it then see: rust-windowing/winit#1255 But in short, if you don't need extended clipboard attributes (OLE Clipboard rather than standard clipboard) then drop the OLE stuff and it would work regardless, otherwise you have to discard drag/drop when CoInitializeEx is in the wrong mode. |
If you want to use native windows, perhaps using this crate is the way to go. Then you don't need to add anything here, or perhaps at most, a very thin wrapper. |
Using |
Here was my first stab at it in a crate: https://crates.io/crates/im-native-dialog |
I'd like to use the rfd crate to open a file dialog. This crate offers a pure Rust solution and an async mode, which is required to work in macOS. It is shown in an example here: Im my application, the dialog should open after pressing a button. Where I'm struggling is how to integrate this into egui. I guess there has to be some executor and other stuff. My knowledge of Rust and async is still not sufficient to get this running, so any help would appreciated. |
I couldn't get |
Some good news: I was able to get rfd working with async at least in macOS and Linux. Can't do any Windows testing at the moment though. I used the demo code with minimal changes. The trickiest part was to get the selected file back to the application because |
@sourcebox could you share what you did? |
Sure. My project is not published yet, so I tried to extract the relevant parts. By doing this, it's possible that I introduced some errors or forgot something. pub enum Message {
FileOpen(std::path::PathBuf),
// Other messages
}
pub struct App {
message_channel: (
std::sync::mpsc::Sender<Message>,
std::sync::mpsc::Receiver<Message>,
)
}
impl Default for App {
fn default() -> Self {
Self {
message_channel: std::sync::mpsc::channel(),
}
}
}
impl epi::App for App {
fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) {
// This is important, otherwise file dialog can hang
// and messages are not processed
ctx.request_repaint();
loop {
match self.message_channel.1.try_recv() {
Ok(message) => {
// Process FileOpen and other messages
}
Err(_) => {
break;
}
}
}
egui::CentralPanel::default().show(ctx, |ui| {
let open_button = ui.add(egui::widgets::Button::new("Open...");
if open_button.clicked() {
let task = rfd::AsyncFileDialog::new()
.add_filter("Text files", &["txt"])
.set_directory("/")
.pick_file();
let message_sender = self.message_channel.0.clone();
execute(async move {
let file = task.await;
if let Some(file) = file {
let file_path = std::path::PathBuf::from(file.path());
message_sender.send(Message::FileOpen(file_path)).ok();
}
});
}
});
}
}
fn execute<F: std::future::Future<Output = ()> + Send + 'static>(f: F) {
std::thread::spawn(move || {
futures::executor::block_on(f);
});
} |
@sourcebox I had a chance to use your code today, some minor tweaks but overall snippet worked great!
|
Fine. There's one thing I want to point out for the discussion, the IMO, it would be nice, to have some function that is called periodically even when no ui updates are necessary. This is where the message processing and other things could be done without any cost of repainting. |
Wouldn't cloning |
For load/save on native we should probably use https://github.com/EmbarkStudios/nfd2 since |
@sourcebox Oh wow, I missed I just made a PR that fixes hanging native file dialogs on mac, and I have tested that it works with both |
Drag-and-drop of files is working, and the Opening a file dialog on web is still unimplemented, but I think we can start here and add that later if someone really wants it. |
I know that I'm kinda late, but I think that there is a little bit of misunderstanding about main thread of macos dialogs in my RFD crate. RFD uses macos eventloop to automatically redirect dialogs to main thread (as long as eventloop is running for example internaly in winit), if you find that this is not the case you should report it as a bug. Other crates are mostly focusing on CLI use so they can't just expect the EventLoop to be started, but RFD supports it as long as all the requirements are met. TLDR: as long as you are in winit or sdl app you can spawn dialogs whenever and RFD should do everything for you. EDIT: @OfficialURL Also the Windows COM issue was lately adresed in cpal so you should no longer come across it (as cpal was one of the only crates that used COM in multithreaded mode) |
@PolyMeilex before #631 got merged |
Yep that's a know issue that I was struggling with for quite some time, and thank you for your workaround it's a lot easier that using my fork of winit, I should probably mention it in RFD repo so future users know that it is possible to avoid winit deadlock |
Is there an example how the dialogs now should be used? I'm on macOS 10.13 and had a working solution with an async dialog before. After the latest update I got the message about unsupported environment. So I changed the dialog to the sync version. Now the dialog windows just flashes up and closes immediately again returning |
Oh, that's an unexpected side effect of this change, so when using winit's But rfd checks if NSApp is running whenever it is starts async dialog to make sure that it is running in supported env: Maybe I could add a flag to force RFD to try to start a dialog even in this case, but I kinda feel like we are stacking workaround on top of workarounds just to make winit happy.
Could you check if this is also the case for |
https://github.com/PolyMeilex/winit is your best bet, I'm using it for for all releases of Neothesia and I never heard any complaints since I switched to it, if you need it for any specific version of winit just backport it, it is a single commit change |
I had a look into your Neothesia project, |
@sourcebox try adding this to your [patch.crates-io]
winit = { git = "https://github.com/PolyMeilex/winit ", branch = "master" } |
@emilk Thanks, that will probably do it ;-) |
I backported PolyMeilex's fix to the 0.25 release version: https://github.com/OfficialURL/winit |
I had a little bit of time today and tried both forks from vihdzp and PolyMeilex. I still get an immediately disappearing dialog with those. Do I have to switch back to the async version when using these fixes? |
Oh, it's probably because I and vihdzp are not using Once again, I'm sorry that I can't dedicate any time to this. |
I just request to reopen this issue, so it does not get lost. |
Related: #756 |
I have submitted @PolyMeilex winit fix as a PR now: rust-windowing/winit#2027 Once that is merged and |
Actually, I'll consider this closed - the feature is there, but there are some bugs and problems left. Let's open separate issues for those as needed. |
Thanks. macOS file dialogs now work when using PolyMeilex fork. |
yep, the run_return commit in egui was reverted, so my fork should work as expected now |
just wanna say that we are in 2022 |
I have a project that requires loading a file on web and native Here's my attempt: https://github.com/kirjavascript/trueLMAO/blob/master/frontend/src/widgets/file.rs usage:
The advantage over the rfd wasm version is that this version doesn't rely on having the user click a file element and handles the creation and clicking for you, making the dialogs presented to the user match on web and native. Is this an idiomatic approach to egui file dialogs, and could it be improved? The example usage relies on request_repaint still to "wait" for the file, but there is probably a better approach, and certainly the
Added a web/native way of saving;
|
Does anyone know where we can find example code using a file drag and drop? |
Hi, I'm interested in knowing if we have some improvements on the item: If it's not the case, I would also like to know if someone could give me a few pointers so I can see if I can implement this. |
It is presently possible to select and upload files using rfd and egui. |
is it also possible to drag files from the app outside to other apps? |
Hello, does the file picker work on the web now? If yes can someone share an example please? Thanks |
Hey @anilbey I made one for you - does this help? |
Wow! many many thanks @woelper! I am trying it |
Fantastic thanks a lot @woelper |
Thank you @woelper! Google brought me here and this is exactly what I was after. |
Tracking issue for
rfd
now works since egui_glium: run app code outside event loop to fix file dialogs #631)egui_web
("Select a file to upload")egui_web and
egui_glium` (Drag and drop files into egui_glium and egui_web #637)The text was updated successfully, but these errors were encountered: