Moving autoscroll to a subscription on fixed timer + calculating speed based off of distance to edge
This commit is contained in:
parent
169d8ef365
commit
9d60ca1564
2 changed files with 61 additions and 13 deletions
18
src/app.rs
18
src/app.rs
|
|
@ -18,6 +18,7 @@ use cosmic::{
|
||||||
app::{self, context_drawer, message, Core, Task},
|
app::{self, context_drawer, message, Core, Task},
|
||||||
cosmic_config, cosmic_theme, executor,
|
cosmic_config, cosmic_theme, executor,
|
||||||
iced::{
|
iced::{
|
||||||
|
self,
|
||||||
clipboard::dnd::DndAction,
|
clipboard::dnd::DndAction,
|
||||||
event,
|
event,
|
||||||
futures::{self, SinkExt},
|
futures::{self, SinkExt},
|
||||||
|
|
@ -332,6 +333,7 @@ pub enum Message {
|
||||||
Rename(Option<Entity>),
|
Rename(Option<Entity>),
|
||||||
ReplaceResult(ReplaceResult),
|
ReplaceResult(ReplaceResult),
|
||||||
RestoreFromTrash(Option<Entity>),
|
RestoreFromTrash(Option<Entity>),
|
||||||
|
ScrollTab(f32),
|
||||||
SearchActivate,
|
SearchActivate,
|
||||||
SearchClear,
|
SearchClear,
|
||||||
SearchInput(String),
|
SearchInput(String),
|
||||||
|
|
@ -550,6 +552,7 @@ pub struct App {
|
||||||
tab_dnd_hover: Option<(Entity, Instant)>,
|
tab_dnd_hover: Option<(Entity, Instant)>,
|
||||||
nav_drag_id: DragId,
|
nav_drag_id: DragId,
|
||||||
tab_drag_id: DragId,
|
tab_drag_id: DragId,
|
||||||
|
auto_scroll_speed: Option<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -1628,6 +1631,7 @@ impl Application for App {
|
||||||
tab_dnd_hover: None,
|
tab_dnd_hover: None,
|
||||||
nav_drag_id: DragId::new(),
|
nav_drag_id: DragId::new(),
|
||||||
tab_drag_id: DragId::new(),
|
tab_drag_id: DragId::new(),
|
||||||
|
auto_scroll_speed: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut commands = vec![app.update_config()];
|
let mut commands = vec![app.update_config()];
|
||||||
|
|
@ -2794,6 +2798,10 @@ impl Application for App {
|
||||||
self.operation(Operation::Restore { items: trash_items });
|
self.operation(Operation::Restore { items: trash_items });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Message::ScrollTab(scroll_speed) => {
|
||||||
|
let entity = self.tab_model.active();
|
||||||
|
return self.update(Message::TabMessage(Some(entity), tab::Message::ScrollTab(scroll_speed)));
|
||||||
|
}
|
||||||
Message::SearchActivate => {
|
Message::SearchActivate => {
|
||||||
return if self.search_get().is_none() {
|
return if self.search_get().is_none() {
|
||||||
self.search_set_active(Some(String::new()))
|
self.search_set_active(Some(String::new()))
|
||||||
|
|
@ -2931,6 +2939,9 @@ impl Application for App {
|
||||||
config_set!(favorites, favorites);
|
config_set!(favorites, favorites);
|
||||||
commands.push(self.update_config());
|
commands.push(self.update_config());
|
||||||
}
|
}
|
||||||
|
tab::Command::AutoScroll(scroll_speed) => {
|
||||||
|
self.auto_scroll_speed = scroll_speed;
|
||||||
|
}
|
||||||
tab::Command::ChangeLocation(tab_title, tab_path, selection_paths) => {
|
tab::Command::ChangeLocation(tab_title, tab_path, selection_paths) => {
|
||||||
self.activate_nav_model_location(&tab_path);
|
self.activate_nav_model_location(&tab_path);
|
||||||
|
|
||||||
|
|
@ -4714,6 +4725,13 @@ impl Application for App {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if let Some(scroll_speed) = self.auto_scroll_speed {
|
||||||
|
subscriptions.push(
|
||||||
|
iced::time::every(time::Duration::from_millis(10))
|
||||||
|
.map(move |_| Message::ScrollTab(scroll_speed))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for (key, mounter) in MOUNTERS.iter() {
|
for (key, mounter) in MOUNTERS.iter() {
|
||||||
subscriptions.push(
|
subscriptions.push(
|
||||||
mounter.subscription().with(*key).map(
|
mounter.subscription().with(*key).map(
|
||||||
|
|
|
||||||
56
src/tab.rs
56
src/tab.rs
|
|
@ -83,7 +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 = 1;
|
const DRAG_SCROLL_DISTANCE: f32 = 15.0;
|
||||||
|
const DRAG_SCROLL_RATIO_MAXIMUM: f32 = 3.0;
|
||||||
|
|
||||||
//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";
|
||||||
|
|
@ -1100,6 +1101,7 @@ pub enum Command {
|
||||||
Action(Action),
|
Action(Action),
|
||||||
AddNetworkDrive,
|
AddNetworkDrive,
|
||||||
AddToSidebar(PathBuf),
|
AddToSidebar(PathBuf),
|
||||||
|
AutoScroll(Option<f32>),
|
||||||
ChangeLocation(String, Location, Option<Vec<PathBuf>>),
|
ChangeLocation(String, Location, Option<Vec<PathBuf>>),
|
||||||
DropFiles(PathBuf, ClipboardPaste),
|
DropFiles(PathBuf, ClipboardPaste),
|
||||||
EmptyTrash,
|
EmptyTrash,
|
||||||
|
|
@ -1157,6 +1159,7 @@ pub enum Message {
|
||||||
RightClick(Option<usize>),
|
RightClick(Option<usize>),
|
||||||
MiddleClick(usize),
|
MiddleClick(usize),
|
||||||
Scroll(Viewport),
|
Scroll(Viewport),
|
||||||
|
ScrollTab(f32),
|
||||||
ScrollToFocus,
|
ScrollToFocus,
|
||||||
SearchContext(Location, SearchContextWrapper),
|
SearchContext(Location, SearchContextWrapper),
|
||||||
SearchReady(bool),
|
SearchReady(bool),
|
||||||
|
|
@ -2231,17 +2234,36 @@ impl Tab {
|
||||||
// diff_y should be NEGATIVE here when close to y=0 (above the MouseArea)
|
// diff_y should be NEGATIVE here when close to y=0 (above the MouseArea)
|
||||||
// and positive when below the viewport
|
// and positive when below the viewport
|
||||||
let diff_y = pos.y - drag_start_point.y;
|
let diff_y = pos.y - drag_start_point.y;
|
||||||
let scroll_y: i8 = if diff_y > 0.0 {
|
let mut scroll_y: f32 = if diff_y > 0.0 {
|
||||||
DRAG_SCROLL_DISTANCE as i8
|
DRAG_SCROLL_DISTANCE
|
||||||
} else if diff_y < 0.0 {
|
} else if diff_y < 0.0 {
|
||||||
DRAG_SCROLL_DISTANCE as i8 * -1
|
DRAG_SCROLL_DISTANCE * -1.0
|
||||||
} else {
|
} else {
|
||||||
0
|
0.0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// estimate distance and use that to control speed
|
||||||
|
// go up to 3x speed
|
||||||
|
let quarter_height = viewport.height / 4.0;
|
||||||
|
let cursor_y_distance = if diff_y > 0.0 {
|
||||||
|
pos.y - (viewport.y + viewport.height)
|
||||||
|
} else if diff_y < 0.0 {
|
||||||
|
pos.y - viewport.y
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}.abs();
|
||||||
|
|
||||||
|
let mut speed_ratio = (cursor_y_distance / quarter_height) + 1.0;
|
||||||
|
if speed_ratio > DRAG_SCROLL_RATIO_MAXIMUM {
|
||||||
|
speed_ratio = DRAG_SCROLL_RATIO_MAXIMUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroll_y = scroll_y * speed_ratio;
|
||||||
|
|
||||||
let mut new_offset = Point {
|
let mut new_offset = Point {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: scroll_y as f32
|
y: scroll_y
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(virtual_cursor_offset) = self.virtual_cursor_offset {
|
if let Some(virtual_cursor_offset) = self.virtual_cursor_offset {
|
||||||
|
|
@ -2258,12 +2280,7 @@ impl Tab {
|
||||||
self.virtual_cursor_offset = Some(new_offset);
|
self.virtual_cursor_offset = Some(new_offset);
|
||||||
self.last_scroll_offset = Some(new_offset);
|
self.last_scroll_offset = Some(new_offset);
|
||||||
|
|
||||||
commands.push(Command::Iced(
|
commands.push(Command::AutoScroll(Some(scroll_y)));
|
||||||
scrollable::scroll_by(self.scrollable_id.clone(), AbsoluteOffset {
|
|
||||||
x: 0.0,
|
|
||||||
y: scroll_y as f32
|
|
||||||
}).into(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if let Some(last_scroll_offset) = self.last_scroll_offset {
|
if let Some(last_scroll_offset) = self.last_scroll_offset {
|
||||||
|
|
@ -2288,8 +2305,9 @@ impl Tab {
|
||||||
y: 0.0
|
y: 0.0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commands.push(Command::AutoScroll(None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -2297,6 +2315,8 @@ impl Tab {
|
||||||
self.virtual_cursor_offset = None;
|
self.virtual_cursor_offset = None;
|
||||||
self.last_scroll_position = Some(pos);
|
self.last_scroll_position = Some(pos);
|
||||||
self.last_scroll_offset = None;
|
self.last_scroll_offset = None;
|
||||||
|
|
||||||
|
commands.push(Command::AutoScroll(None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2329,6 +2349,8 @@ impl Tab {
|
||||||
item.overlaps_drag_rect = false;
|
item.overlaps_drag_rect = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commands.push(Command::AutoScroll(None));
|
||||||
}
|
}
|
||||||
Message::DoubleClick(click_i_opt) => {
|
Message::DoubleClick(click_i_opt) => {
|
||||||
if let Some(clicked_item) = self
|
if let Some(clicked_item) = self
|
||||||
|
|
@ -2959,6 +2981,14 @@ impl Tab {
|
||||||
Message::Scroll(viewport) => {
|
Message::Scroll(viewport) => {
|
||||||
self.scroll_opt = Some(viewport.absolute_offset());
|
self.scroll_opt = Some(viewport.absolute_offset());
|
||||||
}
|
}
|
||||||
|
Message::ScrollTab(scroll_speed) => {
|
||||||
|
commands.push(Command::Iced(
|
||||||
|
scrollable::scroll_by(self.scrollable_id.clone(), AbsoluteOffset {
|
||||||
|
x: 0.0,
|
||||||
|
y: scroll_speed
|
||||||
|
}).into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
Message::ScrollToFocus => {
|
Message::ScrollToFocus => {
|
||||||
if let Some(offset) = self.select_focus_scroll() {
|
if let Some(offset) = self.select_focus_scroll() {
|
||||||
commands.push(Command::Iced(
|
commands.push(Command::Iced(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue