Improve keyboard focus handling
This commit is contained in:
parent
4690225d95
commit
d2d0b02afd
2 changed files with 88 additions and 9 deletions
|
|
@ -99,7 +99,7 @@ impl Action {
|
||||||
Action::Properties => Message::ToggleContextPage(ContextPage::Properties),
|
Action::Properties => Message::ToggleContextPage(ContextPage::Properties),
|
||||||
Action::Rename => Message::Rename(entity_opt),
|
Action::Rename => Message::Rename(entity_opt),
|
||||||
Action::RestoreFromTrash => Message::RestoreFromTrash(entity_opt),
|
Action::RestoreFromTrash => Message::RestoreFromTrash(entity_opt),
|
||||||
Action::SelectAll => Message::SelectAll(entity_opt),
|
Action::SelectAll => Message::TabMessage(entity_opt, tab::Message::SelectAll),
|
||||||
Action::Settings => Message::ToggleContextPage(ContextPage::Settings),
|
Action::Settings => Message::ToggleContextPage(ContextPage::Settings),
|
||||||
Action::TabClose => Message::TabClose(entity_opt),
|
Action::TabClose => Message::TabClose(entity_opt),
|
||||||
Action::TabNew => Message::TabNew,
|
Action::TabNew => Message::TabNew,
|
||||||
|
|
@ -142,7 +142,6 @@ pub enum Message {
|
||||||
PendingProgress(u64, f32),
|
PendingProgress(u64, f32),
|
||||||
Rename(Option<segmented_button::Entity>),
|
Rename(Option<segmented_button::Entity>),
|
||||||
RestoreFromTrash(Option<segmented_button::Entity>),
|
RestoreFromTrash(Option<segmented_button::Entity>),
|
||||||
SelectAll(Option<segmented_button::Entity>),
|
|
||||||
SystemThemeModeChange(cosmic_theme::ThemeMode),
|
SystemThemeModeChange(cosmic_theme::ThemeMode),
|
||||||
TabActivate(segmented_button::Entity),
|
TabActivate(segmented_button::Entity),
|
||||||
TabNext,
|
TabNext,
|
||||||
|
|
@ -946,12 +945,6 @@ impl Application for App {
|
||||||
self.operation(Operation::Restore { paths });
|
self.operation(Operation::Restore { paths });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::SelectAll(entity_opt) => {
|
|
||||||
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
|
||||||
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
|
|
||||||
tab.select_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Message::SystemThemeModeChange(_theme_mode) => {
|
Message::SystemThemeModeChange(_theme_mode) => {
|
||||||
return self.update_config();
|
return self.update_config();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
88
src/tab.rs
88
src/tab.rs
|
|
@ -417,6 +417,7 @@ pub enum Message {
|
||||||
Resize(Size),
|
Resize(Size),
|
||||||
RightClick(usize),
|
RightClick(usize),
|
||||||
Scroll(Viewport),
|
Scroll(Viewport),
|
||||||
|
SelectAll,
|
||||||
Thumbnail(PathBuf, Result<image::RgbaImage, ()>),
|
Thumbnail(PathBuf, Result<image::RgbaImage, ()>),
|
||||||
ToggleShowHidden,
|
ToggleShowHidden,
|
||||||
View(View),
|
View(View),
|
||||||
|
|
@ -669,7 +670,7 @@ impl Tab {
|
||||||
|
|
||||||
pub fn select_name(&mut self, name: &str) {
|
pub fn select_name(&mut self, name: &str) {
|
||||||
if let Some(ref mut items) = self.items_opt {
|
if let Some(ref mut items) = self.items_opt {
|
||||||
for (i, item) in items.iter_mut().enumerate() {
|
for item in items.iter_mut() {
|
||||||
if item.name == name {
|
if item.name == name {
|
||||||
item.selected = true;
|
item.selected = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -788,6 +789,64 @@ impl Tab {
|
||||||
item.pos_opt.get()
|
item.pos_opt.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn select_first_pos_opt(&self) -> Option<(usize, usize)> {
|
||||||
|
let items = self.items_opt.as_ref()?;
|
||||||
|
let mut first = None;
|
||||||
|
for item in items.iter() {
|
||||||
|
if !item.selected {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (row, col) = match item.pos_opt.get() {
|
||||||
|
Some(some) => some,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
first = Some(match first {
|
||||||
|
Some((first_row, first_col)) => {
|
||||||
|
if row < first_row {
|
||||||
|
(row, col)
|
||||||
|
} else if row == first_row {
|
||||||
|
(row, col.min(first_row))
|
||||||
|
} else {
|
||||||
|
(first_row, first_col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => (row, col),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
first
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_last_pos_opt(&self) -> Option<(usize, usize)> {
|
||||||
|
let items = self.items_opt.as_ref()?;
|
||||||
|
let mut last = None;
|
||||||
|
for item in items.iter() {
|
||||||
|
if !item.selected {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (row, col) = match item.pos_opt.get() {
|
||||||
|
Some(some) => some,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
last = Some(match last {
|
||||||
|
Some((last_row, last_col)) => {
|
||||||
|
if row > last_row {
|
||||||
|
(row, col)
|
||||||
|
} else if row == last_row {
|
||||||
|
(row, col.max(last_row))
|
||||||
|
} else {
|
||||||
|
(last_row, last_col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => (row, col),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
last
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, message: Message, modifiers: Modifiers) -> Vec<Command> {
|
pub fn update(&mut self, message: Message, modifiers: Modifiers) -> Vec<Command> {
|
||||||
let mut commands = Vec::new();
|
let mut commands = Vec::new();
|
||||||
let mut cd = None;
|
let mut cd = None;
|
||||||
|
|
@ -843,6 +902,10 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.context_menu = None;
|
self.context_menu = None;
|
||||||
|
if self.select_focus.take().is_some() {
|
||||||
|
// Unfocus currently focused button
|
||||||
|
commands.push(Command::FocusButton(widget::Id::unique()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Message::Config(config) => {
|
Message::Config(config) => {
|
||||||
self.config = config;
|
self.config = config;
|
||||||
|
|
@ -859,6 +922,10 @@ impl Tab {
|
||||||
Message::Drag(rect_opt) => match rect_opt {
|
Message::Drag(rect_opt) => match rect_opt {
|
||||||
Some(rect) => {
|
Some(rect) => {
|
||||||
self.select_rect(rect);
|
self.select_rect(rect);
|
||||||
|
if self.select_focus.take().is_some() {
|
||||||
|
// Unfocus currently focused button
|
||||||
|
commands.push(Command::FocusButton(widget::Id::unique()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
},
|
},
|
||||||
|
|
@ -892,6 +959,9 @@ impl Tab {
|
||||||
// Ensure current item is still selected if there are no other items
|
// Ensure current item is still selected if there are no other items
|
||||||
self.select_position(row, col, mod_shift);
|
self.select_position(row, col, mod_shift);
|
||||||
}
|
}
|
||||||
|
} else if let Some((row, col)) = self.select_last_pos_opt() {
|
||||||
|
// Select last item in current selection to focus it
|
||||||
|
self.select_position(row, col, mod_shift);
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
//TODO: select first in scroll
|
//TODO: select first in scroll
|
||||||
|
|
@ -930,6 +1000,9 @@ impl Tab {
|
||||||
self.select_position(row, col, mod_shift);
|
self.select_position(row, col, mod_shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let Some((row, col)) = self.select_first_pos_opt() {
|
||||||
|
// Select first item in current selection to focus it
|
||||||
|
self.select_position(row, col, mod_shift);
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
//TODO: select first in scroll
|
//TODO: select first in scroll
|
||||||
|
|
@ -952,6 +1025,9 @@ impl Tab {
|
||||||
self.select_position(row, col, mod_shift);
|
self.select_position(row, col, mod_shift);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let Some((row, col)) = self.select_last_pos_opt() {
|
||||||
|
// Select last item in current selection to focus it
|
||||||
|
self.select_position(row, col, mod_shift);
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
//TODO: select first in scroll
|
//TODO: select first in scroll
|
||||||
|
|
@ -975,6 +1051,9 @@ impl Tab {
|
||||||
// Ensure current item is still selected if there are no other items
|
// Ensure current item is still selected if there are no other items
|
||||||
self.select_position(row, col, mod_shift);
|
self.select_position(row, col, mod_shift);
|
||||||
}
|
}
|
||||||
|
} else if let Some((row, col)) = self.select_first_pos_opt() {
|
||||||
|
// Select first item in current selection to focus it
|
||||||
|
self.select_position(row, col, mod_shift);
|
||||||
} else {
|
} else {
|
||||||
// Select first item
|
// Select first item
|
||||||
//TODO: select first in scroll
|
//TODO: select first in scroll
|
||||||
|
|
@ -1043,6 +1122,13 @@ impl Tab {
|
||||||
Message::Scroll(viewport) => {
|
Message::Scroll(viewport) => {
|
||||||
self.scroll_opt = Some(viewport.absolute_offset());
|
self.scroll_opt = Some(viewport.absolute_offset());
|
||||||
}
|
}
|
||||||
|
Message::SelectAll => {
|
||||||
|
self.select_all();
|
||||||
|
if self.select_focus.take().is_some() {
|
||||||
|
// Unfocus currently focused button
|
||||||
|
commands.push(Command::FocusButton(widget::Id::unique()));
|
||||||
|
}
|
||||||
|
}
|
||||||
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 {
|
||||||
for item in items.iter_mut() {
|
for item in items.iter_mut() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue