Skip to content

Commit

Permalink
File drop events
Browse files Browse the repository at this point in the history
  • Loading branch information
ecton committed Sep 16, 2024
1 parent e7ccbac commit 01b764d
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
initialized.
- `Window::on_init` is a new callback that is invoked before the winit window is
initialized.
- `Window::on_file_drop` is a new callback that is invoked when file drop events
occur for the window.


[139]: https://github.com/khonsulabs/cushy/issues/139
Expand Down
97 changes: 86 additions & 11 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::io;
use std::marker::PhantomData;
use std::num::{NonZeroU32, TryFromIntError};
use std::ops::{Deref, DerefMut, Not};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::string::ToString;
use std::sync::{mpsc, Arc, OnceLock};
use std::time::{Duration, Instant};
Expand Down Expand Up @@ -61,8 +61,8 @@ use crate::value::{
Destination, Dynamic, DynamicReader, IntoDynamic, IntoValue, Source, Tracked, Value,
};
use crate::widget::{
EventHandling, MakeWidget, MountedWidget, OnceCallback, RootBehavior, SharedCallback, WidgetId,
WidgetInstance, HANDLED, IGNORED,
Callback, EventHandling, MakeWidget, MountedWidget, OnceCallback, RootBehavior, SharedCallback,
WidgetId, WidgetInstance, HANDLED, IGNORED,
};
use crate::widgets::shortcuts::{ShortcutKey, ShortcutMap};
use crate::window::sealed::WindowCommand;
Expand Down Expand Up @@ -565,6 +565,7 @@ where
enabled_buttons: Option<Value<WindowButtons>>,
fullscreen: Option<Value<Option<Fullscreen>>>,
shortcuts: Value<ShortcutMap>,
on_file_drop: Option<Callback<FileDrop>>,
}

impl<Behavior> Default for Window<Behavior>
Expand Down Expand Up @@ -662,6 +663,7 @@ where
fullscreen: None,
shortcuts: Value::default(),
on_init: None,
on_file_drop: None,
}
}

Expand Down Expand Up @@ -1015,6 +1017,15 @@ where
self
}

/// Invokes `on_file_drop` when a file is hovered or dropped on this window.
pub fn on_file_drop<Function>(mut self, on_file_drop: Function) -> Self
where
Function: FnMut(FileDrop) + Send + 'static,
{
self.on_file_drop = Some(Callback::new(on_file_drop));
self
}

/// Sets the window's title.
pub fn titled(mut self, title: impl IntoValue<String>) -> Self {
self.title = title.into_value();
Expand Down Expand Up @@ -1159,6 +1170,7 @@ where
.unwrap_or(Value::Constant(WindowButtons::all())),
fullscreen: this.fullscreen.unwrap_or_default(),
shortcuts: this.shortcuts,
on_file_drop: this.on_file_drop,
}),
pending: this.pending,
},
Expand Down Expand Up @@ -1233,6 +1245,35 @@ where
}
}

/// A file drop event for a window.
pub struct FileDrop {
/// The handle to the window the file drop event is for.
pub window: WindowHandle,
/// The file drop event.
pub drop: DropEvent<PathBuf>,
}

/// A drop event.
pub enum DropEvent<T> {
/// The payload is being hovered over the container.
Hover(T),
/// The payload has been dropped on the container.
Dropped(T),
/// The payload previously hovered has been cancelled.
Cancelled,
}

impl<T> DropEvent<T> {
/// Returns the payload of this event.
#[must_use]
pub fn payload(&self) -> Option<&T> {
match self {
Self::Hover(t) | Self::Dropped(t) => Some(t),
Self::Cancelled => None,
}
}
}

/// The behavior of a Cushy window.
pub trait WindowBehavior: Sized + 'static {
/// The type that is provided when initializing this window.
Expand Down Expand Up @@ -1328,6 +1369,7 @@ struct OpenWindow<T> {
fullscreen: Tracked<Value<Option<Fullscreen>>>,
modifiers: Dynamic<Modifiers>,
shortcuts: Value<ShortcutMap>,
on_file_drop: Option<Callback<FileDrop>>,
}

impl<T> OpenWindow<T>
Expand Down Expand Up @@ -1768,6 +1810,7 @@ where
enabled_buttons: Tracked::from(settings.enabled_buttons).ignoring_first(),
fullscreen: Tracked::from(settings.fullscreen).ignoring_first(),
shortcuts: settings.shortcuts,
on_file_drop: settings.on_file_drop,
};

this.synchronize_platform_window(&mut window);
Expand Down Expand Up @@ -2416,6 +2459,19 @@ where
}
}
}

fn handle_drop(
&mut self,
drop: DropEvent<PathBuf>,
window: &kludgine::app::Window<'_, WindowCommand>,
) {
if let Some(on_file_drop) = &mut self.on_file_drop {
on_file_drop.invoke(FileDrop {
window: WindowHandle::new(window.handle(), self.redraw_status.clone()),
drop,
});
}
}
}

#[derive(Clone, Copy, Eq, PartialEq, Debug)]
Expand Down Expand Up @@ -2634,13 +2690,31 @@ where
self.moved(window.inner_position(), window.outer_position());
}

// fn theme_changed(&mut self, window: kludgine::app::Window<'_, ()>) {}

// fn dropped_file(&mut self, window: kludgine::app::Window<'_, ()>, path: std::path::PathBuf) {}
fn dropped_file(
&mut self,
window: kludgine::app::Window<'_, WindowCommand>,
_kludgine: &mut Kludgine,
path: PathBuf,
) {
self.handle_drop(DropEvent::Dropped(path), &window);
}

// fn hovered_file(&mut self, window: kludgine::app::Window<'_, ()>, path: std::path::PathBuf) {}
fn hovered_file(
&mut self,
window: kludgine::app::Window<'_, WindowCommand>,
_kludgine: &mut Kludgine,
path: PathBuf,
) {
self.handle_drop(DropEvent::Hover(path), &window);
}

// fn hovered_file_cancelled(&mut self, window: kludgine::app::Window<'_, ()>) {}
fn hovered_file_cancelled(
&mut self,
window: kludgine::app::Window<'_, WindowCommand>,
_kludgine: &mut Kludgine,
) {
self.handle_drop(DropEvent::Cancelled, &window);
}

// fn received_character(&mut self, window: kludgine::app::Window<'_, ()>, char: char) {}

Expand Down Expand Up @@ -2886,16 +2960,15 @@ pub(crate) mod sealed {
use kludgine::app::winit::window::{Fullscreen, UserAttentionType, WindowButtons, WindowLevel};
use kludgine::Color;

use super::{PendingWindow, WindowHandle};
use crate::app::Cushy;
use crate::context::sealed::InvalidationStatus;
use crate::context::EventContext;
use crate::fonts::FontCollection;
use crate::styles::{FontFamilyList, ThemePair};
use crate::value::{Dynamic, Value};
use crate::widget::{OnceCallback, SharedCallback};
use crate::widget::{Callback, OnceCallback, SharedCallback};
use crate::widgets::shortcuts::ShortcutMap;
use crate::window::{ThemeMode, WindowAttributes};
use crate::window::{FileDrop, PendingWindow, ThemeMode, WindowAttributes, WindowHandle};

pub struct Context<C> {
pub user: C,
Expand Down Expand Up @@ -2947,6 +3020,7 @@ pub(crate) mod sealed {
pub enabled_buttons: Value<WindowButtons>,
pub fullscreen: Value<Option<Fullscreen>>,
pub shortcuts: Value<ShortcutMap>,
pub on_file_drop: Option<Callback<FileDrop>>,
}

pub struct WindowExecute(Box<dyn ExecuteFunc>);
Expand Down Expand Up @@ -3629,6 +3703,7 @@ impl StandaloneWindowBuilder {
fullscreen: Value::default(),
shortcuts: Value::default(),
on_init: None,
on_file_drop: None,
},
);

Expand Down

0 comments on commit 01b764d

Please sign in to comment.