Implement view menu, fixes #184
This commit is contained in:
parent
e947bee833
commit
322dad2b8a
6 changed files with 114 additions and 10 deletions
|
|
@ -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...
|
||||
|
|
|
|||
20
src/app.rs
20
src/app.rs
|
|
@ -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>> {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
32
src/menu.rs
32
src/menu.rs
|
|
@ -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,
|
||||
|
|
|
|||
61
src/tab.rs
61
src/tab.rs
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue