Adjust scroll when using arrow keys
This commit is contained in:
parent
08a7f6faed
commit
501e4f48eb
3 changed files with 69 additions and 4 deletions
|
|
@ -9,6 +9,7 @@ use cosmic::{
|
||||||
futures::{self, SinkExt},
|
futures::{self, SinkExt},
|
||||||
keyboard::{Event as KeyEvent, Key, Modifiers},
|
keyboard::{Event as KeyEvent, Key, Modifiers},
|
||||||
subscription::{self, Subscription},
|
subscription::{self, Subscription},
|
||||||
|
widget::scrollable,
|
||||||
window, Alignment, Event, Length,
|
window, Alignment, Event, Length,
|
||||||
},
|
},
|
||||||
style, theme,
|
style, theme,
|
||||||
|
|
@ -1065,6 +1066,9 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tab::Command::Scroll(id, offset) => {
|
||||||
|
commands.push(scrollable::scroll_to(id, offset));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Command::batch(commands);
|
return Command::batch(commands);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use cosmic::{
|
||||||
keyboard::{Event as KeyEvent, Modifiers},
|
keyboard::{Event as KeyEvent, Modifiers},
|
||||||
multi_window::Application as IcedApplication,
|
multi_window::Application as IcedApplication,
|
||||||
subscription::{self, Subscription},
|
subscription::{self, Subscription},
|
||||||
|
widget::scrollable,
|
||||||
window, Event, Length, Size,
|
window, Event, Length, Size,
|
||||||
},
|
},
|
||||||
theme,
|
theme,
|
||||||
|
|
@ -592,6 +593,9 @@ impl Application for App {
|
||||||
commands.push(self.update(Message::Open));
|
commands.push(self.update(Message::Open));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tab::Command::Scroll(id, offset) => {
|
||||||
|
commands.push(scrollable::scroll_to(id, offset));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Command::batch(commands);
|
return Command::batch(commands);
|
||||||
|
|
|
||||||
65
src/tab.rs
65
src/tab.rs
|
|
@ -6,7 +6,10 @@ use cosmic::{
|
||||||
keyboard::Modifiers,
|
keyboard::Modifiers,
|
||||||
subscription::{self, Subscription},
|
subscription::{self, Subscription},
|
||||||
//TODO: export in cosmic::widget
|
//TODO: export in cosmic::widget
|
||||||
widget::{horizontal_rule, scrollable::Viewport},
|
widget::{
|
||||||
|
horizontal_rule,
|
||||||
|
scrollable::{AbsoluteOffset, Viewport},
|
||||||
|
},
|
||||||
Alignment,
|
Alignment,
|
||||||
Color,
|
Color,
|
||||||
ContentFit,
|
ContentFit,
|
||||||
|
|
@ -385,6 +388,7 @@ pub enum Command {
|
||||||
FocusButton(widget::Id),
|
FocusButton(widget::Id),
|
||||||
FocusTextInput(widget::Id),
|
FocusTextInput(widget::Id),
|
||||||
OpenFile(PathBuf),
|
OpenFile(PathBuf),
|
||||||
|
Scroll(widget::Id, AbsoluteOffset),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -568,7 +572,7 @@ pub struct Tab {
|
||||||
pub context_menu: Option<Point>,
|
pub context_menu: Option<Point>,
|
||||||
pub view: View,
|
pub view: View,
|
||||||
pub dialog: Option<DialogKind>,
|
pub dialog: Option<DialogKind>,
|
||||||
pub scroll_opt: Option<Viewport>,
|
pub scroll_opt: Option<AbsoluteOffset>,
|
||||||
pub size_opt: Option<Size>,
|
pub size_opt: Option<Size>,
|
||||||
pub edit_location: Option<Location>,
|
pub edit_location: Option<Location>,
|
||||||
pub edit_location_id: widget::Id,
|
pub edit_location_id: widget::Id,
|
||||||
|
|
@ -576,6 +580,7 @@ pub struct Tab {
|
||||||
pub history: Vec<Location>,
|
pub history: Vec<Location>,
|
||||||
pub config: TabConfig,
|
pub config: TabConfig,
|
||||||
items_opt: Option<Vec<Item>>,
|
items_opt: Option<Vec<Item>>,
|
||||||
|
scrollable_id: widget::Id,
|
||||||
select_focus: Option<usize>,
|
select_focus: Option<usize>,
|
||||||
select_shift: Option<usize>,
|
select_shift: Option<usize>,
|
||||||
sort_name: HeadingOptions,
|
sort_name: HeadingOptions,
|
||||||
|
|
@ -600,6 +605,7 @@ impl Tab {
|
||||||
history,
|
history,
|
||||||
config,
|
config,
|
||||||
items_opt: None,
|
items_opt: None,
|
||||||
|
scrollable_id: widget::Id::unique(),
|
||||||
select_focus: None,
|
select_focus: None,
|
||||||
select_shift: None,
|
select_shift: None,
|
||||||
sort_name,
|
sort_name,
|
||||||
|
|
@ -742,6 +748,38 @@ impl Tab {
|
||||||
item.pos_opt.get()
|
item.pos_opt.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_focus_scroll(&mut self) -> Option<AbsoluteOffset> {
|
||||||
|
let items = self.items_opt.as_ref()?;
|
||||||
|
let item = items.get(self.select_focus?)?;
|
||||||
|
let rect = item.rect_opt.get()?;
|
||||||
|
|
||||||
|
//TODO: move to function
|
||||||
|
let visible_rect = {
|
||||||
|
let point = match self.scroll_opt {
|
||||||
|
Some(offset) => Point::new(0.0, offset.y),
|
||||||
|
None => Point::new(0.0, 0.0),
|
||||||
|
};
|
||||||
|
let size = self.size_opt.unwrap_or_else(|| Size::new(0.0, 0.0));
|
||||||
|
Rectangle::new(point, size)
|
||||||
|
};
|
||||||
|
|
||||||
|
if rect.y < visible_rect.y {
|
||||||
|
// Scroll up to rect
|
||||||
|
self.scroll_opt = Some(AbsoluteOffset { x: 0.0, y: rect.y });
|
||||||
|
self.scroll_opt
|
||||||
|
} else if (rect.y + rect.height) > (visible_rect.y + visible_rect.height) {
|
||||||
|
// Scroll down to rect
|
||||||
|
self.scroll_opt = Some(AbsoluteOffset {
|
||||||
|
x: 0.0,
|
||||||
|
y: rect.y + rect.height - visible_rect.height,
|
||||||
|
});
|
||||||
|
self.scroll_opt
|
||||||
|
} else {
|
||||||
|
// Do not scroll
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn select_shift_pos_opt(&self) -> Option<(usize, usize)> {
|
fn select_shift_pos_opt(&self) -> Option<(usize, usize)> {
|
||||||
let items = self.items_opt.as_ref()?;
|
let items = self.items_opt.as_ref()?;
|
||||||
let item = items.get(self.select_shift?)?;
|
let item = items.get(self.select_shift?)?;
|
||||||
|
|
@ -856,8 +894,12 @@ impl Tab {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
|
//TODO: select first in scroll
|
||||||
self.select_position(0, 0, mod_shift);
|
self.select_position(0, 0, mod_shift);
|
||||||
}
|
}
|
||||||
|
if let Some(offset) = self.select_focus_scroll() {
|
||||||
|
commands.push(Command::Scroll(self.scrollable_id.clone(), offset));
|
||||||
|
}
|
||||||
if let Some(id) = self.select_focus_id() {
|
if let Some(id) = self.select_focus_id() {
|
||||||
commands.push(Command::FocusButton(id));
|
commands.push(Command::FocusButton(id));
|
||||||
}
|
}
|
||||||
|
|
@ -890,8 +932,12 @@ impl Tab {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
|
//TODO: select first in scroll
|
||||||
self.select_position(0, 0, mod_shift);
|
self.select_position(0, 0, mod_shift);
|
||||||
}
|
}
|
||||||
|
if let Some(offset) = self.select_focus_scroll() {
|
||||||
|
commands.push(Command::Scroll(self.scrollable_id.clone(), offset));
|
||||||
|
}
|
||||||
if let Some(id) = self.select_focus_id() {
|
if let Some(id) = self.select_focus_id() {
|
||||||
commands.push(Command::FocusButton(id));
|
commands.push(Command::FocusButton(id));
|
||||||
}
|
}
|
||||||
|
|
@ -908,8 +954,12 @@ impl Tab {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
|
//TODO: select first in scroll
|
||||||
self.select_position(0, 0, mod_shift);
|
self.select_position(0, 0, mod_shift);
|
||||||
}
|
}
|
||||||
|
if let Some(offset) = self.select_focus_scroll() {
|
||||||
|
commands.push(Command::Scroll(self.scrollable_id.clone(), offset));
|
||||||
|
}
|
||||||
if let Some(id) = self.select_focus_id() {
|
if let Some(id) = self.select_focus_id() {
|
||||||
commands.push(Command::FocusButton(id));
|
commands.push(Command::FocusButton(id));
|
||||||
}
|
}
|
||||||
|
|
@ -927,8 +977,12 @@ impl Tab {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
|
//TODO: select first in scroll
|
||||||
self.select_position(0, 0, mod_shift);
|
self.select_position(0, 0, mod_shift);
|
||||||
}
|
}
|
||||||
|
if let Some(offset) = self.select_focus_scroll() {
|
||||||
|
commands.push(Command::Scroll(self.scrollable_id.clone(), offset));
|
||||||
|
}
|
||||||
if let Some(id) = self.select_focus_id() {
|
if let Some(id) = self.select_focus_id() {
|
||||||
commands.push(Command::FocusButton(id));
|
commands.push(Command::FocusButton(id));
|
||||||
}
|
}
|
||||||
|
|
@ -987,7 +1041,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Scroll(viewport) => {
|
Message::Scroll(viewport) => {
|
||||||
self.scroll_opt = Some(viewport);
|
self.scroll_opt = Some(viewport.absolute_offset());
|
||||||
}
|
}
|
||||||
Message::Thumbnail(path, thumbnail_res) => {
|
Message::Thumbnail(path, thumbnail_res) => {
|
||||||
if let Some(ref mut items) = self.items_opt {
|
if let Some(ref mut items) = self.items_opt {
|
||||||
|
|
@ -1418,6 +1472,7 @@ impl Tab {
|
||||||
.on_drag(Message::Drag)
|
.on_drag(Message::Drag)
|
||||||
.show_drag_rect(true),
|
.show_drag_rect(true),
|
||||||
)
|
)
|
||||||
|
.id(self.scrollable_id.clone())
|
||||||
.on_scroll(Message::Scroll)
|
.on_scroll(Message::Scroll)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
|
|
@ -1569,6 +1624,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
widget::scrollable(widget::column::with_children(children).padding([0, space_m]))
|
widget::scrollable(widget::column::with_children(children).padding([0, space_m]))
|
||||||
|
.id(self.scrollable_id.clone())
|
||||||
.on_scroll(Message::Scroll)
|
.on_scroll(Message::Scroll)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
|
|
@ -1613,9 +1669,10 @@ impl Tab {
|
||||||
let jobs = 8;
|
let jobs = 8;
|
||||||
let mut subscriptions = Vec::with_capacity(jobs);
|
let mut subscriptions = Vec::with_capacity(jobs);
|
||||||
|
|
||||||
|
//TODO: move to function
|
||||||
let visible_rect = {
|
let visible_rect = {
|
||||||
let point = match self.scroll_opt {
|
let point = match self.scroll_opt {
|
||||||
Some(viewport) => Point::new(0.0, viewport.absolute_offset().y),
|
Some(offset) => Point::new(0.0, offset.y),
|
||||||
None => Point::new(0.0, 0.0),
|
None => Point::new(0.0, 0.0),
|
||||||
};
|
};
|
||||||
let size = self.size_opt.unwrap_or_else(|| Size::new(0.0, 0.0));
|
let size = self.size_opt.unwrap_or_else(|| Size::new(0.0, 0.0));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue