diff --git a/src/app.rs b/src/app.rs index b7a198c..081a855 100644 --- a/src/app.rs +++ b/src/app.rs @@ -305,7 +305,6 @@ pub enum Message { Config(Config), Copy(Option), CosmicSettings(&'static str), - CursorMoved(Point), Cut(Option), Delete(Option), DesktopConfig(DesktopConfig), @@ -2329,13 +2328,6 @@ impl Application for App { let contents = ClipboardCopy::new(ClipboardKind::Copy, &paths); 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) => { self.set_cut(entity_opt); let paths = self.selected_paths(entity_opt); @@ -5374,7 +5366,7 @@ impl Application for App { struct TimeSubscription; let mut subscriptions = vec![ - event::listen_with(|event, status, window_id| match event { + event::listen_with(|event, status, _window_id| match event { Event::Keyboard(KeyEvent::KeyPressed { key, modifiers, @@ -5408,7 +5400,6 @@ impl Application for App { _ => None, } } - Event::Mouse(CursorMoved { position: pos }) => Some(Message::CursorMoved(pos)), _ => None, }), Config::subscription().map(|update| { diff --git a/src/dialog.rs b/src/dialog.rs index c6ac63d..92098e4 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -411,7 +411,6 @@ enum Message { Cancel, Choice(usize, usize), Config(Config), - CursorMoved(Point), DialogCancel, DialogComplete, DialogUpdate(DialogPage), @@ -1262,9 +1261,6 @@ impl Application for App { return self.update_config(); } } - Message::CursorMoved(pos) => { - return self.update(Message::TabMessage(tab::Message::CursorMoved(pos))); - } Message::DialogCancel => { self.dialog_pages.pop_front(); } @@ -1801,9 +1797,6 @@ impl Application for App { Event::Keyboard(KeyEvent::ModifiersChanged(modifiers)) => { Some(Message::ModifiersChanged(modifiers)) } - Event::Mouse(mouse::Event::CursorMoved { position: pos }) => { - Some(Message::CursorMoved(pos)) - } _ => None, }), Config::subscription().map(|update| { diff --git a/src/mouse_area.rs b/src/mouse_area.rs index 4b176fa..9aa38e9 100644 --- a/src/mouse_area.rs +++ b/src/mouse_area.rs @@ -24,6 +24,7 @@ use cosmic::{ pub struct MouseArea<'a, Message> { id: Id, content: Element<'a, Message>, + on_auto_scroll: Option>>, on_drag: Option>>, on_double_click: Option>>, on_press: Option>>, @@ -46,6 +47,13 @@ pub struct MouseArea<'a, Message> { } impl<'a, Message> MouseArea<'a, Message> { + /// The message to emit when auto scroll changes. + #[must_use] + pub fn on_auto_scroll(mut self, message: impl OnAutoScroll<'a, Message>) -> Self { + self.on_auto_scroll = Some(Box::new(message)); + self + } + /// The message to emit when a drag is initiated. #[must_use] pub fn on_drag(mut self, message: impl OnDrag<'a, Message>) -> Self { @@ -186,6 +194,9 @@ impl<'a, Message> MouseArea<'a, Message> { } } +pub trait OnAutoScroll<'a, Message>: Fn(Option) -> Message + 'a {} +impl<'a, Message, F> OnAutoScroll<'a, Message> for F where F: Fn(Option) -> Message + 'a {} + pub trait OnMouseButton<'a, Message>: Fn(Option) -> Message + 'a {} impl<'a, Message, F> OnMouseButton<'a, Message> for F where F: Fn(Option) -> Message + 'a {} @@ -207,6 +218,7 @@ impl<'a, Message, F> OnEnterExit<'a, Message> for F where F: Fn() -> Message + ' /// Local state of the [`MouseArea`]. #[derive(Default)] struct State { + last_auto_scroll: Option, last_position: Option, last_virtual_position: Option, drag_initiated: Option, @@ -266,6 +278,7 @@ impl<'a, Message> MouseArea<'a, Message> { MouseArea { id: Id::unique(), content: content.into(), + on_auto_scroll: None, on_drag: None, on_drag_end: None, on_double_click: None, @@ -518,10 +531,31 @@ fn update( } state.last_position = position_in; - state.last_virtual_position = Some(Point::new( + let virtual_position = Point::new( viewport.x - layout_bounds.x + position.x, viewport.y - layout_bounds.y + position.y, - )); + ); + state.last_virtual_position = Some(virtual_position); + + if let Some(message) = widget.on_auto_scroll.as_ref() { + let auto_scroll = if state.drag_initiated.is_some() { + let bottom = viewport.y; + let top = viewport.y + viewport.height; + if virtual_position.y < bottom { + Some(virtual_position.y - bottom) + } else if virtual_position.y > top { + Some(virtual_position.y - top) + } else { + None + } + } else { + None + }; + if state.last_auto_scroll != auto_scroll { + shell.publish(message(auto_scroll)); + state.last_auto_scroll = auto_scroll; + } + } } if state.drag_initiated.is_none() && !cursor.is_over(layout_bounds) { diff --git a/src/tab.rs b/src/tab.rs index 0131a1f..7228a5c 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -92,8 +92,6 @@ const MAX_SEARCH_RESULTS: usize = 200; //TODO: configurable thumbnail size? const THUMBNAIL_SIZE: u32 = (ICON_SIZE_GRID as u32) * (ICON_SCALE_MAX as u32); -const DRAG_SCROLL_DISTANCE: f32 = 15.0; - pub(crate) static SORT_OPTION_FALLBACK: LazyLock> = LazyLock::new(|| { HashMap::from_iter(dirs::download_dir().into_iter().map(|dir| { @@ -1528,11 +1526,10 @@ pub enum Command { #[derive(Clone, Debug)] pub enum Message { AddNetworkDrive, + AutoScroll(Option), Click(Option), DoubleClick(Option), ClickRelease(Option), - CursorMoved(Point), - DragEnd(Option), Config(TabConfig), ContextAction(Action), ContextMenu(Option), @@ -1540,6 +1537,7 @@ pub enum Message { LocationContextMenuIndex(Option), LocationMenuAction(LocationMenuAction), Drag(Option), + DragEnd, EditLocation(Option), EditLocationComplete(usize), EditLocationEnable, @@ -2402,12 +2400,6 @@ pub struct Tab { modifiers: Modifiers, last_right_click: Option, search_context: Option, - global_cursor_position: Option, - current_drag_rect: Option, - virtual_cursor_offset: Option, - last_scroll_position: Option, - last_scroll_offset: Option, - scroll_bounds_opt: Option, date_time_formatter: DateTimeFormatter, time_formatter: DateTimeFormatter, } @@ -2518,12 +2510,6 @@ impl Tab { modifiers: Modifiers::default(), last_right_click: None, search_context: None, - global_cursor_position: None, - current_drag_rect: None, - virtual_cursor_offset: None, - last_scroll_position: None, - last_scroll_offset: None, - scroll_bounds_opt: None, date_time_formatter: date_time_formatter(config.military_time), time_formatter: time_formatter(config.military_time), } @@ -2831,7 +2817,6 @@ impl Tab { self.items_opt = None; //TODO: remember scroll by location? self.scroll_opt = None; - self.scroll_bounds_opt = None; self.select_focus = None; self.search_context = None; if let Some(history_i) = history_i_opt { @@ -2872,6 +2857,9 @@ impl Tab { Message::AddNetworkDrive => { commands.push(Command::AddNetworkDrive); } + Message::AutoScroll(auto_scroll) => { + commands.push(Command::AutoScroll(auto_scroll)); + } Message::ClickRelease(click_i_opt) => { if click_i_opt == self.clicked.take() { return commands; @@ -2891,80 +2879,8 @@ 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(scroll_bounds) = self.scroll_bounds_opt { - if !scroll_bounds.contains(pos) { - if pos.y < scroll_bounds.y - || pos.y > (scroll_bounds.y + scroll_bounds.height) - { - // if our mouse is above the scroll bounds, we want to scroll up - let drag_start_point = Point { - x: scroll_bounds.x, - y: scroll_bounds.y, - }; - // diff_y should be NEGATIVE here when close to y=0 (above the MouseArea) - // and positive when below the scroll bounds - let diff_y = pos.y - drag_start_point.y; - let scroll_y: f32 = if diff_y > 0.0 { - DRAG_SCROLL_DISTANCE - } else if diff_y < 0.0 { - -DRAG_SCROLL_DISTANCE - } else { - 0.0 - }; - - commands.push(Command::AutoScroll(Some(scroll_y))); - } else { - if let Some(last_scroll_offset) = self.last_scroll_offset { - if let Some(last_scroll_position) = self.last_scroll_position { - self.virtual_cursor_offset = Some(Point { - x: 0.0, - y: (pos.y - last_scroll_position.y - + last_scroll_offset.y), - }); - } - } else { - if let Some(last_scroll_position) = self.last_scroll_position { - self.virtual_cursor_offset = Some(Point { - x: 0.0, - y: (pos.y - last_scroll_position.y), - }); - } else { - self.virtual_cursor_offset = Some(Point { x: 0.0, y: 0.0 }); - } - } - - commands.push(Command::AutoScroll(None)); - } - } else { - // reset our virtual cursor offset when we're back in bounds - self.virtual_cursor_offset = None; - self.last_scroll_position = Some(pos); - self.last_scroll_offset = None; - - commands.push(Command::AutoScroll(None)); - } - } - } - } - Message::DragEnd(_) => { + Message::DragEnd => { self.clicked = None; - self.virtual_cursor_offset = None; - self.last_scroll_offset = None; - self.last_scroll_position = None; - - self.current_drag_rect = None; - if let Some(ref mut items) = self.items_opt { - for item in items.iter_mut() { - item.overlaps_drag_rect = false; - } - } - - commands.push(Command::AutoScroll(None)); } Message::DoubleClick(click_i_opt) => { if let Some(clicked_item) = self @@ -3225,9 +3141,6 @@ impl Tab { } } Message::Drag(rect_opt) => { - if self.mode.multiple() { - self.current_drag_rect = rect_opt; - } if let Some(rect) = rect_opt { self.context_menu = None; self.location_context_menu_index = None; @@ -3655,31 +3568,9 @@ impl Tab { } Message::Scroll(viewport) => { - self.scroll_bounds_opt = Some(viewport.bounds()); self.scroll_opt = Some(viewport.absolute_offset()); } Message::ScrollTab(scroll_speed) => { - let mut new_offset = Point { - x: 0.0, - y: scroll_speed, - }; - - if let Some(virtual_cursor_offset) = self.virtual_cursor_offset { - new_offset = Point { - x: new_offset.x + virtual_cursor_offset.x, - y: new_offset.y + virtual_cursor_offset.y, - }; - } - - if let Some(last_scroll_position) = self.last_scroll_position { - if let Some(global_cursor_position) = self.global_cursor_position { - new_offset.x = global_cursor_position.x - last_scroll_position.x; - } - } - - self.virtual_cursor_offset = Some(new_offset); - self.last_scroll_offset = Some(new_offset); - commands.push(Command::Iced( scrollable::scroll_by( self.scrollable_id.clone(), @@ -5009,8 +4900,9 @@ impl Tab { }), mouse_area::MouseArea::new(widget::column::with_children(children).width(Length::Fill)) .on_press(|_| Message::Click(None)) + .on_auto_scroll(Message::AutoScroll) .on_drag(Message::Drag) - .on_drag_end(|_| Message::DragEnd(None)) + .on_drag_end(|_| Message::DragEnd) .show_drag_rect(self.mode.multiple()) .on_release(|_| Message::ClickRelease(None)) .into(), @@ -5394,8 +5286,9 @@ impl Tab { ) .with_id(Id::new("list-view")) .on_press(|_| Message::Click(None)) + .on_auto_scroll(Message::AutoScroll) .on_drag(Message::Drag) - .on_drag_end(|_| Message::DragEnd(None)) + .on_drag_end(|_| Message::DragEnd) .show_drag_rect(self.mode.multiple()) .on_release(|_| Message::ClickRelease(None)) .into(),