Improve keyboard focus handling

This commit is contained in:
Jeremy Soller 2024-02-29 21:13:03 -07:00
parent 4690225d95
commit d2d0b02afd
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
2 changed files with 88 additions and 9 deletions

View file

@ -99,7 +99,7 @@ impl Action {
Action::Properties => Message::ToggleContextPage(ContextPage::Properties),
Action::Rename => Message::Rename(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::TabClose => Message::TabClose(entity_opt),
Action::TabNew => Message::TabNew,
@ -142,7 +142,6 @@ pub enum Message {
PendingProgress(u64, f32),
Rename(Option<segmented_button::Entity>),
RestoreFromTrash(Option<segmented_button::Entity>),
SelectAll(Option<segmented_button::Entity>),
SystemThemeModeChange(cosmic_theme::ThemeMode),
TabActivate(segmented_button::Entity),
TabNext,
@ -946,12 +945,6 @@ impl Application for App {
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) => {
return self.update_config();
}

View file

@ -417,6 +417,7 @@ pub enum Message {
Resize(Size),
RightClick(usize),
Scroll(Viewport),
SelectAll,
Thumbnail(PathBuf, Result<image::RgbaImage, ()>),
ToggleShowHidden,
View(View),
@ -669,7 +670,7 @@ impl Tab {
pub fn select_name(&mut self, name: &str) {
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 {
item.selected = true;
} else {
@ -788,6 +789,64 @@ impl Tab {
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> {
let mut commands = Vec::new();
let mut cd = None;
@ -843,6 +902,10 @@ impl Tab {
}
}
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) => {
self.config = config;
@ -859,6 +922,10 @@ impl Tab {
Message::Drag(rect_opt) => match rect_opt {
Some(rect) => {
self.select_rect(rect);
if self.select_focus.take().is_some() {
// Unfocus currently focused button
commands.push(Command::FocusButton(widget::Id::unique()));
}
}
None => {}
},
@ -892,6 +959,9 @@ impl Tab {
// Ensure current item is still selected if there are no other items
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 {
// Select first item
//TODO: select first in scroll
@ -930,6 +1000,9 @@ impl Tab {
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 {
// Select first item
//TODO: select first in scroll
@ -952,6 +1025,9 @@ impl Tab {
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 {
// Select first item
//TODO: select first in scroll
@ -975,6 +1051,9 @@ impl Tab {
// Ensure current item is still selected if there are no other items
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 {
// Select first item
//TODO: select first in scroll
@ -1043,6 +1122,13 @@ impl Tab {
Message::Scroll(viewport) => {
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) => {
if let Some(ref mut items) = self.items_opt {
for item in items.iter_mut() {