Adding in new functionality to scroll the file window when dragging outside the viewport of the scrollable
This commit is contained in:
parent
a092aa2383
commit
7c6df15f08
3 changed files with 58 additions and 5 deletions
|
|
@ -54,6 +54,7 @@ use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::{self, Instant},
|
time::{self, Instant},
|
||||||
};
|
};
|
||||||
|
use cosmic::iced::mouse::Event::CursorMoved;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use trash::TrashItem;
|
use trash::TrashItem;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
|
|
@ -277,6 +278,7 @@ pub enum Message {
|
||||||
Config(Config),
|
Config(Config),
|
||||||
Copy(Option<Entity>),
|
Copy(Option<Entity>),
|
||||||
CosmicSettings(&'static str),
|
CosmicSettings(&'static str),
|
||||||
|
CursorMoved(Point),
|
||||||
Cut(Option<Entity>),
|
Cut(Option<Entity>),
|
||||||
DesktopConfig(DesktopConfig),
|
DesktopConfig(DesktopConfig),
|
||||||
DesktopViewOptions,
|
DesktopViewOptions,
|
||||||
|
|
@ -1926,6 +1928,10 @@ impl Application for App {
|
||||||
let contents = ClipboardCopy::new(ClipboardKind::Copy, &paths);
|
let contents = ClipboardCopy::new(ClipboardKind::Copy, &paths);
|
||||||
return clipboard::write_data(contents);
|
return clipboard::write_data(contents);
|
||||||
}
|
}
|
||||||
|
Message::CursorMoved(pos) => {
|
||||||
|
let entity = self.tab_model.active();
|
||||||
|
return self.update(Message::TabMessage(Some(entity), tab::Message::CursorMoved(pos)));
|
||||||
|
}
|
||||||
Message::Cut(entity_opt) => {
|
Message::Cut(entity_opt) => {
|
||||||
let paths = self.selected_paths(entity_opt);
|
let paths = self.selected_paths(entity_opt);
|
||||||
let contents = ClipboardCopy::new(ClipboardKind::Cut, &paths);
|
let contents = ClipboardCopy::new(ClipboardKind::Cut, &paths);
|
||||||
|
|
@ -4536,7 +4542,8 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
Event::Mouse(CursorMoved { position: pos }) => Some(Message::CursorMoved(pos)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}),
|
}),
|
||||||
Config::subscription().map(|update| {
|
Config::subscription().map(|update| {
|
||||||
|
|
|
||||||
|
|
@ -199,8 +199,8 @@ impl<'a, Message, F> OnMouseButton<'a, Message> for F where F: Fn(Option<Point>)
|
||||||
pub trait OnDrag<'a, Message>: Fn(Option<Rectangle>) -> Message + 'a {}
|
pub trait OnDrag<'a, Message>: Fn(Option<Rectangle>) -> Message + 'a {}
|
||||||
impl<'a, Message, F> OnDrag<'a, Message> for F where F: Fn(Option<Rectangle>) -> Message + 'a {}
|
impl<'a, Message, F> OnDrag<'a, Message> for F where F: Fn(Option<Rectangle>) -> Message + 'a {}
|
||||||
|
|
||||||
pub trait OnResize<'a, Message>: Fn(Size) -> Message + 'a {}
|
pub trait OnResize<'a, Message>: Fn(Size, Rectangle) -> Message + 'a {}
|
||||||
impl<'a, Message, F> OnResize<'a, Message> for F where F: Fn(Size) -> Message + 'a {}
|
impl<'a, Message, F> OnResize<'a, Message> for F where F: Fn(Size, Rectangle) -> Message + 'a {}
|
||||||
|
|
||||||
pub trait OnScroll<'a, Message>: Fn(mouse::ScrollDelta, Modifiers) -> Option<Message> + 'a {}
|
pub trait OnScroll<'a, Message>: Fn(mouse::ScrollDelta, Modifiers) -> Option<Message> + 'a {}
|
||||||
impl<'a, Message, F> OnScroll<'a, Message> for F where
|
impl<'a, Message, F> OnScroll<'a, Message> for F where
|
||||||
|
|
@ -374,6 +374,7 @@ where
|
||||||
cursor,
|
cursor,
|
||||||
shell,
|
shell,
|
||||||
tree.state.downcast_mut::<State>(),
|
tree.state.downcast_mut::<State>(),
|
||||||
|
viewport,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -493,6 +494,7 @@ fn update<Message: Clone>(
|
||||||
cursor: mouse::Cursor,
|
cursor: mouse::Cursor,
|
||||||
shell: &mut Shell<'_, Message>,
|
shell: &mut Shell<'_, Message>,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
|
viewport: &Rectangle
|
||||||
) -> event::Status {
|
) -> event::Status {
|
||||||
let layout_bounds = layout.bounds();
|
let layout_bounds = layout.bounds();
|
||||||
|
|
||||||
|
|
@ -500,7 +502,7 @@ fn update<Message: Clone>(
|
||||||
let size = layout_bounds.size();
|
let size = layout_bounds.size();
|
||||||
if state.size != Some(size) {
|
if state.size != Some(size) {
|
||||||
state.size = Some(size);
|
state.size = Some(size);
|
||||||
shell.publish(message(size));
|
shell.publish(message(size, *viewport));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
46
src/tab.rs
46
src/tab.rs
|
|
@ -83,6 +83,8 @@ const MAX_SEARCH_RESULTS: usize = 200;
|
||||||
//TODO: configurable thumbnail size?
|
//TODO: configurable thumbnail size?
|
||||||
const THUMBNAIL_SIZE: u32 = (ICON_SIZE_GRID as u32) * (ICON_SCALE_MAX as u32);
|
const THUMBNAIL_SIZE: u32 = (ICON_SIZE_GRID as u32) * (ICON_SCALE_MAX as u32);
|
||||||
|
|
||||||
|
const DRAG_SCROLL_DISTANCE: u8 = 5;
|
||||||
|
|
||||||
//TODO: adjust for locales?
|
//TODO: adjust for locales?
|
||||||
const DATE_TIME_FORMAT: &str = "%b %-d, %-Y, %-I:%M %p";
|
const DATE_TIME_FORMAT: &str = "%b %-d, %-Y, %-I:%M %p";
|
||||||
const TIME_FORMAT: &str = "%-I:%M %p";
|
const TIME_FORMAT: &str = "%-I:%M %p";
|
||||||
|
|
@ -1121,6 +1123,8 @@ pub enum Message {
|
||||||
Click(Option<usize>),
|
Click(Option<usize>),
|
||||||
DoubleClick(Option<usize>),
|
DoubleClick(Option<usize>),
|
||||||
ClickRelease(Option<usize>),
|
ClickRelease(Option<usize>),
|
||||||
|
CursorMoved(Point),
|
||||||
|
MouseAreaResized(Size, Rectangle),
|
||||||
DragEnd(Option<usize>),
|
DragEnd(Option<usize>),
|
||||||
Config(TabConfig),
|
Config(TabConfig),
|
||||||
ContextAction(Action),
|
ContextAction(Action),
|
||||||
|
|
@ -1772,6 +1776,9 @@ pub struct Tab {
|
||||||
selected_clicked: bool,
|
selected_clicked: bool,
|
||||||
last_right_click: Option<usize>,
|
last_right_click: Option<usize>,
|
||||||
search_context: Option<SearchContext>,
|
search_context: Option<SearchContext>,
|
||||||
|
global_cursor_position: Option<Point>,
|
||||||
|
current_drag_rect: Option<Rectangle>,
|
||||||
|
viewport_rect: Option<Rectangle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
||||||
|
|
@ -1856,6 +1863,9 @@ impl Tab {
|
||||||
selected_clicked: false,
|
selected_clicked: false,
|
||||||
last_right_click: None,
|
last_right_click: None,
|
||||||
search_context: None,
|
search_context: None,
|
||||||
|
global_cursor_position: None,
|
||||||
|
current_drag_rect: None,
|
||||||
|
viewport_rect: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2199,8 +2209,40 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Message::CursorMoved(pos) => {
|
||||||
|
self.global_cursor_position = Some(pos);
|
||||||
|
|
||||||
|
// we're currently dragging
|
||||||
|
if self.current_drag_rect.is_some() {
|
||||||
|
if let Some(viewport) = self.viewport_rect {
|
||||||
|
if !viewport.contains(pos) {
|
||||||
|
// diff_y should be NEGATIVE here when close to y=0 (above the MouseArea)
|
||||||
|
// and positive when below the viewport
|
||||||
|
let diff_y = pos.y - viewport.y;
|
||||||
|
let scroll_y: i8 = if diff_y > 0.0 {
|
||||||
|
DRAG_SCROLL_DISTANCE as i8
|
||||||
|
} else if diff_y < 0.0 {
|
||||||
|
DRAG_SCROLL_DISTANCE as i8 * -1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
commands.push(Command::Iced(
|
||||||
|
scrollable::scroll_by(self.scrollable_id.clone(), AbsoluteOffset {
|
||||||
|
x: 0.0,
|
||||||
|
y: scroll_y as f32
|
||||||
|
}).into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::MouseAreaResized(_size, viewport) => {
|
||||||
|
self.viewport_rect = Some(viewport);
|
||||||
|
}
|
||||||
Message::DragEnd(_) => {
|
Message::DragEnd(_) => {
|
||||||
self.clicked = None;
|
self.clicked = None;
|
||||||
|
self.current_drag_rect = None;
|
||||||
if let Some(ref mut items) = self.items_opt {
|
if let Some(ref mut items) = self.items_opt {
|
||||||
for item in items.iter_mut() {
|
for item in items.iter_mut() {
|
||||||
item.overlaps_drag_rect = false;
|
item.overlaps_drag_rect = false;
|
||||||
|
|
@ -2433,6 +2475,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Drag(rect_opt) => {
|
Message::Drag(rect_opt) => {
|
||||||
|
self.current_drag_rect = rect_opt;
|
||||||
if let Some(rect) = rect_opt {
|
if let Some(rect) = rect_opt {
|
||||||
self.context_menu = None;
|
self.context_menu = None;
|
||||||
self.location_context_menu_index = None;
|
self.location_context_menu_index = None;
|
||||||
|
|
@ -4434,6 +4477,7 @@ impl Tab {
|
||||||
.on_drag_end(|_| Message::DragEnd(None))
|
.on_drag_end(|_| Message::DragEnd(None))
|
||||||
.show_drag_rect(true)
|
.show_drag_rect(true)
|
||||||
.on_release(|_| Message::ClickRelease(None))
|
.on_release(|_| Message::ClickRelease(None))
|
||||||
|
.on_resize(Message::MouseAreaResized)
|
||||||
.into(),
|
.into(),
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
|
@ -4497,7 +4541,7 @@ impl Tab {
|
||||||
.on_press(move |_point_opt| Message::Click(None))
|
.on_press(move |_point_opt| Message::Click(None))
|
||||||
.on_release(|_| Message::ClickRelease(None))
|
.on_release(|_| Message::ClickRelease(None))
|
||||||
//TODO: better way to keep focused item in view
|
//TODO: better way to keep focused item in view
|
||||||
.on_resize(|_| Message::ScrollToFocus)
|
.on_resize(|_, _| Message::ScrollToFocus)
|
||||||
.on_back_press(move |_point_opt| Message::GoPrevious)
|
.on_back_press(move |_point_opt| Message::GoPrevious)
|
||||||
.on_forward_press(move |_point_opt| Message::GoNext)
|
.on_forward_press(move |_point_opt| Message::GoNext)
|
||||||
.on_scroll(respond_to_scroll_direction);
|
.on_scroll(respond_to_scroll_direction);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue