Implement view menu, fixes #184

This commit is contained in:
Jeremy Soller 2024-05-28 10:40:36 -06:00
parent e947bee833
commit 322dad2b8a
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
6 changed files with 114 additions and 10 deletions

View file

@ -115,8 +115,13 @@ paste = Paste
select-all = Select all
## View
zoom-in = Zoom in
default-size = Default size
zoom-out = Zoom out
view = View
grid-view = Grid view
list-view = List view
show-hidden-files = Show hidden files
list-directories-first = List directories first
menu-settings = Settings...
menu-about = About COSMIC Files...

View file

@ -93,10 +93,14 @@ pub enum Action {
TabPrev,
TabViewGrid,
TabViewList,
ToggleFoldersFirst,
ToggleShowHidden,
ToggleSort(HeadingOptions),
WindowClose,
WindowNew,
ZoomDefault,
ZoomIn,
ZoomOut,
}
impl Action {
@ -137,10 +141,20 @@ impl Action {
Action::TabViewList => {
Message::TabMessage(entity_opt, tab::Message::View(tab::View::List))
}
Action::ToggleShowHidden => Message::TabMessage(None, tab::Message::ToggleShowHidden),
Action::ToggleSort(sort) => Message::TabMessage(None, tab::Message::ToggleSort(*sort)),
Action::ToggleFoldersFirst => {
Message::TabMessage(entity_opt, tab::Message::ToggleFoldersFirst)
}
Action::ToggleShowHidden => {
Message::TabMessage(entity_opt, tab::Message::ToggleShowHidden)
}
Action::ToggleSort(sort) => {
Message::TabMessage(entity_opt, tab::Message::ToggleSort(*sort))
}
Action::WindowClose => Message::WindowClose,
Action::WindowNew => Message::WindowNew,
Action::ZoomDefault => Message::TabMessage(entity_opt, tab::Message::ZoomDefault),
Action::ZoomIn => Message::TabMessage(entity_opt, tab::Message::ZoomIn),
Action::ZoomOut => Message::TabMessage(entity_opt, tab::Message::ZoomOut),
}
}
}
@ -1951,7 +1965,7 @@ impl Application for App {
}
fn header_start(&self) -> Vec<Element<Self::Message>> {
vec![menu::menu_bar(&self.key_binds).into()]
vec![menu::menu_bar(self.tab_model.active_data::<Tab>(), &self.key_binds).into()]
}
fn header_end(&self) -> Vec<Element<Self::Message>> {

View file

@ -111,6 +111,8 @@ impl Default for Config {
/// locally. Local changes aren't saved to the main config.
#[derive(Clone, Copy, Debug, Eq, PartialEq, CosmicConfigEntry, Deserialize, Serialize)]
pub struct TabConfig {
/// Show folders before files
pub folders_first: bool,
/// Show hidden files and folders
pub show_hidden: bool,
/// Sorter
@ -123,6 +125,7 @@ pub struct TabConfig {
impl Default for TabConfig {
fn default() -> Self {
Self {
folders_first: true,
show_hidden: false,
sort_name: HeadingOptions::Name,
sort_direction: true,

View file

@ -51,6 +51,9 @@ pub fn key_binds() -> HashMap<KeyBind, Action> {
bind!([Ctrl], Key::Character("h".into()), ToggleShowHidden);
bind!([Ctrl], Key::Character("q".into()), WindowClose);
bind!([Ctrl], Key::Character("n".into()), WindowNew);
bind!([Ctrl], Key::Character("=".into()), ZoomIn);
bind!([Ctrl], Key::Character("0".into()), ZoomDefault);
bind!([Ctrl], Key::Character("-".into()), ZoomOut);
key_binds
}

View file

@ -169,7 +169,10 @@ pub fn context_menu<'a>(
.into()
}
pub fn menu_bar<'a>(key_binds: &HashMap<KeyBind, Action>) -> Element<'a, Message> {
pub fn menu_bar<'a>(
tab_opt: Option<&Tab>,
key_binds: &HashMap<KeyBind, Action>,
) -> Element<'a, Message> {
MenuBar::new(vec![
menu::Tree::with_children(
menu::root(fl!("file")),
@ -212,8 +215,31 @@ pub fn menu_bar<'a>(key_binds: &HashMap<KeyBind, Action>) -> Element<'a, Message
menu::items(
key_binds,
vec![
menu::Item::Button(fl!("grid-view"), Action::TabViewGrid),
menu::Item::Button(fl!("list-view"), Action::TabViewList),
menu::Item::Button(fl!("zoom-in"), Action::ZoomIn),
menu::Item::Button(fl!("default-size"), Action::ZoomDefault),
menu::Item::Button(fl!("zoom-out"), Action::ZoomOut),
menu::Item::Divider,
menu::Item::CheckBox(
fl!("grid-view"),
tab_opt.map_or(false, |tab| matches!(tab.view, tab::View::Grid)),
Action::TabViewGrid,
),
menu::Item::CheckBox(
fl!("list-view"),
tab_opt.map_or(false, |tab| matches!(tab.view, tab::View::List)),
Action::TabViewList,
),
menu::Item::Divider,
menu::Item::CheckBox(
fl!("show-hidden-files"),
tab_opt.map_or(false, |tab| tab.config.show_hidden),
Action::ToggleShowHidden,
),
menu::Item::CheckBox(
fl!("list-directories-first"),
tab_opt.map_or(false, |tab| tab.config.folders_first),
Action::ToggleFoldersFirst,
),
menu::Item::Divider,
menu::Item::Button(fl!("menu-settings"), Action::Settings),
menu::Item::Divider,

View file

@ -36,6 +36,7 @@ use std::{
collections::HashMap,
fmt,
fs::{self, Metadata},
num::NonZeroU16,
path::PathBuf,
time::{Duration, Instant},
};
@ -465,6 +466,7 @@ pub enum Message {
Scroll(Viewport),
SelectAll,
Thumbnail(PathBuf, ItemThumbnail),
ToggleFoldersFirst,
ToggleShowHidden,
View(View),
ToggleSort(HeadingOptions),
@ -472,6 +474,9 @@ pub enum Message {
DndHover(Location),
DndEnter(Location),
DndLeave(Location),
ZoomDefault,
ZoomIn,
ZoomOut,
}
#[derive(Clone, Debug)]
@ -1394,6 +1399,7 @@ impl Tab {
}
}
}
Message::ToggleFoldersFirst => self.config.folders_first = !self.config.folders_first,
Message::ToggleShowHidden => self.config.show_hidden = !self.config.show_hidden,
Message::View(view) => {
@ -1453,6 +1459,48 @@ impl Tab {
self.dnd_hovered = None;
}
}
Message::ZoomDefault => match self.view {
View::List => self.config.icon_sizes.list = 100.try_into().unwrap(),
View::Grid => self.config.icon_sizes.grid = 100.try_into().unwrap(),
},
Message::ZoomIn => {
let zoom_in = |size: &mut NonZeroU16, min: u16, max: u16| {
let mut step = min;
while step <= max {
if size.get() < step {
*size = step.try_into().unwrap();
break;
}
step += 25;
}
if size.get() > step {
*size = step.try_into().unwrap();
}
};
match self.view {
View::List => zoom_in(&mut self.config.icon_sizes.list, 100, 500),
View::Grid => zoom_in(&mut self.config.icon_sizes.grid, 50, 500),
}
}
Message::ZoomOut => {
let zoom_out = |size: &mut NonZeroU16, min: u16, max: u16| {
let mut step = max;
while step >= min {
if size.get() > step {
*size = step.try_into().unwrap();
break;
}
step -= 25;
}
if size.get() < step {
*size = step.try_into().unwrap();
}
};
match self.view {
View::List => zoom_out(&mut self.config.icon_sizes.list, 100, 500),
View::Grid => zoom_out(&mut self.config.icon_sizes.grid, 50, 500),
}
}
}
if let Some(location) = cd {
if location != self.location {
@ -1509,10 +1557,14 @@ impl Tab {
})
}
HeadingOptions::Name => items.sort_by(|a, b| {
let ord = match (a.1.metadata.is_dir(), b.1.metadata.is_dir()) {
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
_ => lexical_sort::natural_lexical_cmp(&a.1.name, &b.1.name),
let ord = if self.config.folders_first {
match (a.1.metadata.is_dir(), b.1.metadata.is_dir()) {
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
_ => lexical_sort::natural_lexical_cmp(&a.1.name, &b.1.name),
}
} else {
lexical_sort::natural_lexical_cmp(&a.1.name, &b.1.name)
};
check_reverse(ord, heading_sort)
}),
@ -1993,6 +2045,7 @@ impl Tab {
icon_sizes,
sort_name,
sort_direction,
..
} = self.config;
let size = self.size_opt.unwrap_or_else(|| Size::new(0.0, 0.0));