Implement condensed list view

This commit is contained in:
Jeremy Soller 2024-02-29 19:47:27 -07:00
parent d485e51acb
commit f8521d5b0d
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
4 changed files with 113 additions and 59 deletions

View file

@ -546,7 +546,10 @@ impl Application for App {
} }
/// Creates the application, and optionally emits command on initialize. /// Creates the application, and optionally emits command on initialize.
fn init(core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) { fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
//TODO: make set_nav_bar_toggle_condensed pub
core.nav_bar_toggle_condensed();
let app_themes = vec![fl!("match-desktop"), fl!("dark"), fl!("light")]; let app_themes = vec![fl!("match-desktop"), fl!("dark"), fl!("light")];
let mut nav_model = segmented_button::ModelBuilder::default(); let mut nav_model = segmented_button::ModelBuilder::default();

View file

@ -12,6 +12,7 @@ pub const CONFIG_VERSION: u64 = 1;
// Default icon sizes // Default icon sizes
const ICON_SIZE_LIST: u16 = 24; const ICON_SIZE_LIST: u16 = 24;
const ICON_SIZE_LIST_CONDENSED: u16 = 48;
const ICON_SIZE_GRID: u16 = 64; const ICON_SIZE_GRID: u16 = 64;
// TODO: 5 is an arbitrary number. Maybe there's a better icon size max // TODO: 5 is an arbitrary number. Maybe there's a better icon size max
const ICON_SCALE_MAX: u16 = 5; const ICON_SCALE_MAX: u16 = 5;
@ -98,6 +99,10 @@ impl IconSizes {
percent!(self.list, ICON_SIZE_LIST) as _ percent!(self.list, ICON_SIZE_LIST) as _
} }
pub fn list_condensed(&self) -> u16 {
percent!(self.list, ICON_SIZE_LIST_CONDENSED) as _
}
pub fn grid(&self) -> u16 { pub fn grid(&self) -> u16 {
percent!(self.grid, ICON_SIZE_GRID) as _ percent!(self.grid, ICON_SIZE_GRID) as _
} }

View file

@ -312,6 +312,8 @@ impl Application for App {
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Message>) { fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Message>) {
core.window.show_maximize = false; core.window.show_maximize = false;
core.window.show_minimize = false; core.window.show_minimize = false;
//TODO: make set_nav_bar_toggle_condensed pub
core.nav_bar_toggle_condensed();
let mut nav_model = segmented_button::ModelBuilder::default(); let mut nav_model = segmented_button::ModelBuilder::default();
if let Some(dir) = dirs::home_dir() { if let Some(dir) = dirs::home_dir() {

View file

@ -226,15 +226,18 @@ pub fn scan_path(tab_path: &PathBuf, sizes: IconSizes) -> Vec<Item> {
let mime_guess = MimeGuess::from_path(&path); let mime_guess = MimeGuess::from_path(&path);
let (icon_handle_grid, icon_handle_list) = if metadata.is_dir() { let (icon_handle_grid, icon_handle_list, icon_handle_list_condensed) =
if metadata.is_dir() {
( (
folder_icon(&path, sizes.grid()), folder_icon(&path, sizes.grid()),
folder_icon(&path, sizes.list()), folder_icon(&path, sizes.list()),
folder_icon(&path, sizes.list_condensed()),
) )
} else { } else {
( (
mime_icon(&path, sizes.grid()), mime_icon(&path, sizes.grid()),
mime_icon(&path, sizes.list()), mime_icon(&path, sizes.list()),
mime_icon(&path, sizes.list_condensed()),
) )
}; };
@ -259,6 +262,7 @@ pub fn scan_path(tab_path: &PathBuf, sizes: IconSizes) -> Vec<Item> {
mime_guess, mime_guess,
icon_handle_grid, icon_handle_grid,
icon_handle_list, icon_handle_list,
icon_handle_list_condensed,
thumbnail_res_opt: match mime_guess.first() { thumbnail_res_opt: match mime_guess.first() {
Some(mime) if mime.type_() == "image" => None, Some(mime) if mime.type_() == "image" => None,
_ => Some(Err(())), _ => Some(Err(())),
@ -326,14 +330,17 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
let mime_guess = MimeGuess::from_path(&path); let mime_guess = MimeGuess::from_path(&path);
let (icon_handle_grid, icon_handle_list) = match metadata.size { let (icon_handle_grid, icon_handle_list, icon_handle_list_condensed) =
match metadata.size {
trash::TrashItemSize::Entries(_) => ( trash::TrashItemSize::Entries(_) => (
folder_icon(&path, sizes.grid()), folder_icon(&path, sizes.grid()),
folder_icon(&path, sizes.list()), folder_icon(&path, sizes.list()),
folder_icon(&path, sizes.list_condensed()),
), ),
trash::TrashItemSize::Bytes(_) => ( trash::TrashItemSize::Bytes(_) => (
mime_icon(&path, sizes.grid()), mime_icon(&path, sizes.grid()),
mime_icon(&path, sizes.list()), mime_icon(&path, sizes.list()),
mime_icon(&path, sizes.list_condensed()),
), ),
}; };
@ -345,6 +352,7 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
mime_guess, mime_guess,
icon_handle_grid, icon_handle_grid,
icon_handle_list, icon_handle_list,
icon_handle_list_condensed,
thumbnail_res_opt: Some(Err(())), thumbnail_res_opt: Some(Err(())),
button_id: widget::Id::unique(), button_id: widget::Id::unique(),
pos_opt: Cell::new(None), pos_opt: Cell::new(None),
@ -450,6 +458,7 @@ pub struct Item {
pub mime_guess: MimeGuess, pub mime_guess: MimeGuess,
pub icon_handle_grid: widget::icon::Handle, pub icon_handle_grid: widget::icon::Handle,
pub icon_handle_list: widget::icon::Handle, pub icon_handle_list: widget::icon::Handle,
pub icon_handle_list_condensed: widget::icon::Handle,
pub thumbnail_res_opt: Option<Result<image::RgbaImage, ()>>, pub thumbnail_res_opt: Option<Result<image::RgbaImage, ()>>,
pub button_id: widget::Id, pub button_id: widget::Id,
pub pos_opt: Cell<Option<(usize, usize)>>, pub pos_opt: Cell<Option<(usize, usize)>>,
@ -1483,11 +1492,23 @@ impl Tab {
space_m, space_xxs, .. space_m, space_xxs, ..
} = theme::active().cosmic().spacing; } = theme::active().cosmic().spacing;
let TabConfig {
show_hidden,
icon_sizes,
} = self.config;
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));
let row_height = 40; //TODO: allow resizing?
//TODO: make adaptive? let name_width = 300.0;
let modified_width = Length::Fixed(200.0); let modified_width = 200.0;
let size_width = Length::Fixed(100.0); let size_width = 100.0;
let condensed = size.width < (name_width + modified_width + size_width);
let icon_size = if condensed {
icon_sizes.list_condensed()
} else {
icon_sizes.list()
};
let row_height = icon_size + 2 * space_xxs;
let heading_item = |name, width, msg| { let heading_item = |name, width, msg| {
let mut row = widget::row::with_capacity(2) let mut row = widget::row::with_capacity(2)
@ -1511,12 +1532,18 @@ impl Tab {
}; };
let mut children: Vec<Element<_>> = Vec::new(); let mut children: Vec<Element<_>> = Vec::new();
let mut y = 0;
if !condensed {
children.push( children.push(
widget::row::with_children(vec![ widget::row::with_children(vec![
heading_item(fl!("name"), Length::Fill, HeadingOptions::Name), heading_item(fl!("name"), Length::Fill, HeadingOptions::Name),
//TODO: do not show modified column when in the trash //TODO: do not show modified column when in the trash
heading_item(fl!("modified"), modified_width, HeadingOptions::Modified), heading_item(
heading_item(fl!("size"), size_width, HeadingOptions::Size), fl!("modified"),
Length::Fixed(modified_width),
HeadingOptions::Modified,
),
heading_item(fl!("size"), Length::Fixed(size_width), HeadingOptions::Size),
]) ])
.align_items(Alignment::Center) .align_items(Alignment::Center)
.height(Length::Fixed(row_height as f32)) .height(Length::Fixed(row_height as f32))
@ -1524,18 +1551,14 @@ impl Tab {
.spacing(space_xxs) .spacing(space_xxs)
.into(), .into(),
); );
let mut y = row_height; y += row_height;
children.push(horizontal_rule(1).into()); children.push(horizontal_rule(1).into());
y += 1; y += 1;
}
if let Some(items) = self.column_sort() { if let Some(items) = self.column_sort() {
let mut count = 0; let mut count = 0;
let mut hidden = 0; let mut hidden = 0;
let TabConfig {
show_hidden,
icon_sizes,
} = self.config;
for (i, item) in items { for (i, item) in items {
if !show_hidden && item.hidden { if !show_hidden && item.hidden {
item.pos_opt.set(None); item.pos_opt.set(None);
@ -1585,20 +1608,41 @@ impl Tab {
}, },
}; };
//TODO: align columns let row = if condensed {
let button = widget::button( widget::row::with_children(vec![
widget::icon::icon(item.icon_handle_list_condensed.clone())
.content_fit(ContentFit::Contain)
.size(icon_size)
.into(),
widget::column::with_children(vec![
widget::text(item.name.clone()).into(),
//TODO: translate?
widget::text(format!("{} - {}", modified_text, size_text)).into(),
])
.into(),
])
.align_items(Alignment::Center)
.spacing(space_xxs)
} else {
widget::row::with_children(vec![ widget::row::with_children(vec![
widget::icon::icon(item.icon_handle_list.clone()) widget::icon::icon(item.icon_handle_list.clone())
.content_fit(ContentFit::Contain) .content_fit(ContentFit::Contain)
.size(icon_sizes.list()) .size(icon_size)
.into(), .into(),
widget::text(item.name.clone()).width(Length::Fill).into(), widget::text(item.name.clone()).width(Length::Fill).into(),
widget::text(modified_text).width(modified_width).into(), widget::text(modified_text)
widget::text(size_text).width(size_width).into(), .width(Length::Fixed(modified_width))
.into(),
widget::text(size_text)
.width(Length::Fixed(size_width))
.into(),
]) ])
.align_items(Alignment::Center) .align_items(Alignment::Center)
.spacing(space_xxs), .spacing(space_xxs)
) };
let button = widget::button(row)
.width(Length::Fill)
.height(Length::Fixed(row_height as f32)) .height(Length::Fixed(row_height as f32))
.id(item.button_id.clone()) .id(item.button_id.clone())
.padding(space_xxs) .padding(space_xxs)