gardesk/garfield / e61c363

Browse files

ui: add icon size cycling for grid view (Ctrl+=)

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
e61c3639a346958e48d9b7f4f0ee5b4346e0048d
Parents
a467a52
Tree
e54d52f

4 changed files

StatusFile+-
M garfield/src/app.rs 9 0
M garfield/src/ui/grid_view.rs 105 19
M garfield/src/ui/help_modal.rs 1 0
M garfield/src/ui/tab.rs 5 0
garfield/src/app.rsmodified
@@ -618,6 +618,15 @@ impl App {
618618
                     self.set_view_mode(ViewMode::Columns);
619619
                     return;
620620
                 }
621
+                Key::Char('+') | Key::Char('=') => {
622
+                    // Cycle icon size in grid view
623
+                    if let Some(pane) = self.focused_pane_mut() {
624
+                        if let Some(tab) = pane.active_tab_mut() {
625
+                            tab.cycle_icon_size();
626
+                        }
627
+                    }
628
+                    return;
629
+                }
621630
                 Key::Char('t') | Key::Char('T') => {
622631
                     self.new_tab();
623632
                     return;
garfield/src/ui/grid_view.rsmodified
@@ -5,15 +5,65 @@ use gartk_core::{Color, Modifiers, Point, Rect};
55
 use gartk_render::{Renderer, TextAlign, TextStyle};
66
 use std::collections::HashSet;
77
 
8
-/// Size of each grid cell.
9
-pub const CELL_SIZE: u32 = 100;
10
-
11
-/// Icon size within each cell.
12
-pub const ICON_SIZE: u32 = 48;
13
-
148
 /// Padding around cells.
159
 pub const CELL_PADDING: u32 = 8;
1610
 
11
+/// Icon size setting for grid view.
12
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
13
+pub enum IconSize {
14
+    Small,
15
+    #[default]
16
+    Medium,
17
+    Large,
18
+}
19
+
20
+impl IconSize {
21
+    /// Get the cell size for this icon size.
22
+    pub fn cell_size(&self) -> u32 {
23
+        match self {
24
+            IconSize::Small => 70,
25
+            IconSize::Medium => 100,
26
+            IconSize::Large => 140,
27
+        }
28
+    }
29
+
30
+    /// Get the icon size within the cell.
31
+    pub fn icon_size(&self) -> u32 {
32
+        match self {
33
+            IconSize::Small => 32,
34
+            IconSize::Medium => 48,
35
+            IconSize::Large => 64,
36
+        }
37
+    }
38
+
39
+    /// Get the font size for labels.
40
+    pub fn font_size(&self) -> f64 {
41
+        match self {
42
+            IconSize::Small => 10.0,
43
+            IconSize::Medium => 12.0,
44
+            IconSize::Large => 14.0,
45
+        }
46
+    }
47
+
48
+    /// Cycle to the next size.
49
+    pub fn next(&self) -> Self {
50
+        match self {
51
+            IconSize::Small => IconSize::Medium,
52
+            IconSize::Medium => IconSize::Large,
53
+            IconSize::Large => IconSize::Small,
54
+        }
55
+    }
56
+
57
+    /// Get display name.
58
+    pub fn name(&self) -> &'static str {
59
+        match self {
60
+            IconSize::Small => "Small",
61
+            IconSize::Medium => "Medium",
62
+            IconSize::Large => "Large",
63
+        }
64
+    }
65
+}
66
+
1767
 /// Grid view for displaying file entries as icons.
1868
 pub struct GridView {
1969
     /// Entries to display.
@@ -38,12 +88,15 @@ pub struct GridView {
3888
     drag_start: Option<Point>,
3989
     /// Rubber band current position.
4090
     drag_current: Option<Point>,
91
+    /// Icon size setting.
92
+    icon_size: IconSize,
4193
 }
4294
 
4395
 impl GridView {
4496
     /// Create a new grid view.
4597
     pub fn new(bounds: Rect) -> Self {
46
-        let columns = Self::calculate_columns(bounds.width);
98
+        let icon_size = IconSize::default();
99
+        let columns = Self::calculate_columns_for_size(bounds.width, icon_size);
47100
         Self {
48101
             entries: Vec::new(),
49102
             focused: 0,
@@ -56,12 +109,35 @@ impl GridView {
56109
             hovered: None,
57110
             drag_start: None,
58111
             drag_current: None,
112
+            icon_size,
59113
         }
60114
     }
61115
 
116
+    /// Calculate number of columns that fit in the given width for a specific icon size.
117
+    fn calculate_columns_for_size(width: u32, icon_size: IconSize) -> usize {
118
+        let cell_size = icon_size.cell_size();
119
+        ((width - CELL_PADDING) / (cell_size + CELL_PADDING)).max(1) as usize
120
+    }
121
+
62122
     /// Calculate number of columns that fit in the given width.
63
-    fn calculate_columns(width: u32) -> usize {
64
-        ((width - CELL_PADDING) / (CELL_SIZE + CELL_PADDING)).max(1) as usize
123
+    fn calculate_columns(&self, width: u32) -> usize {
124
+        Self::calculate_columns_for_size(width, self.icon_size)
125
+    }
126
+
127
+    /// Get the current icon size.
128
+    pub fn icon_size(&self) -> IconSize {
129
+        self.icon_size
130
+    }
131
+
132
+    /// Set the icon size.
133
+    pub fn set_icon_size(&mut self, size: IconSize) {
134
+        self.icon_size = size;
135
+        self.columns = self.calculate_columns(self.bounds.width);
136
+    }
137
+
138
+    /// Cycle to the next icon size.
139
+    pub fn cycle_icon_size(&mut self) {
140
+        self.set_icon_size(self.icon_size.next());
65141
     }
66142
 
67143
     /// Set the entries to display.
@@ -104,7 +180,8 @@ impl GridView {
104180
 
105181
     /// Get the number of visible rows that fit in the view.
106182
     fn visible_rows(&self) -> usize {
107
-        (self.bounds.height / (CELL_SIZE + CELL_PADDING)).max(1) as usize
183
+        let cell_size = self.icon_size.cell_size();
184
+        (self.bounds.height / (cell_size + CELL_PADDING)).max(1) as usize
108185
     }
109186
 
110187
     /// Get current sort settings (grid view doesn't track these, uses external).
@@ -226,7 +303,7 @@ impl GridView {
226303
     /// Update bounds.
227304
     pub fn set_bounds(&mut self, bounds: Rect) {
228305
         self.bounds = bounds;
229
-        self.columns = Self::calculate_columns(bounds.width);
306
+        self.columns = self.calculate_columns(bounds.width);
230307
     }
231308
 
232309
     /// Get cell bounds for an index.
@@ -234,11 +311,12 @@ impl GridView {
234311
         let visible_index = index.saturating_sub(self.scroll_offset * self.columns);
235312
         let col = visible_index % self.columns;
236313
         let row = visible_index / self.columns;
314
+        let cell_size = self.icon_size.cell_size();
237315
 
238
-        let x = self.bounds.x + CELL_PADDING as i32 + (col as i32 * (CELL_SIZE + CELL_PADDING) as i32);
239
-        let y = self.bounds.y + CELL_PADDING as i32 + (row as i32 * (CELL_SIZE + CELL_PADDING) as i32);
316
+        let x = self.bounds.x + CELL_PADDING as i32 + (col as i32 * (cell_size + CELL_PADDING) as i32);
317
+        let y = self.bounds.y + CELL_PADDING as i32 + (row as i32 * (cell_size + CELL_PADDING) as i32);
240318
 
241
-        Rect::new(x, y, CELL_SIZE, CELL_SIZE)
319
+        Rect::new(x, y, cell_size, cell_size)
242320
     }
243321
 
244322
     /// Handle mouse move for hover effects and rubber band drag.
@@ -448,14 +526,20 @@ impl GridView {
448526
                 }
449527
             };
450528
 
529
+            // Scale icon font size based on icon size setting
530
+            let icon_font_size = match self.icon_size {
531
+                IconSize::Small => 24.0,
532
+                IconSize::Medium => 32.0,
533
+                IconSize::Large => 48.0,
534
+            };
451535
             let icon_style = TextStyle::new()
452536
                 .font_family(&theme.font_family)
453
-                .font_size(32.0)
537
+                .font_size(icon_font_size)
454538
                 .color(icon_color);
455539
 
456540
             // Center icon horizontally in cell
457541
             let icon_center_x = cell.x + cell.width as i32 / 2;
458
-            let icon_center_y = cell.y + 10 + 16; // 10px top padding + half icon height
542
+            let icon_center_y = cell.y + 10 + (icon_font_size / 2.0) as i32;
459543
             renderer.text_centered(icon, Point::new(icon_center_x, icon_center_y), &icon_style)?;
460544
 
461545
             // File name (truncated)
@@ -467,9 +551,10 @@ impl GridView {
467551
                 theme.item_foreground
468552
             };
469553
 
554
+            let name_font_size = self.icon_size.font_size();
470555
             let name_style = TextStyle::new()
471556
                 .font_family(&theme.font_family)
472
-                .font_size(theme.font_size - 1.0)
557
+                .font_size(name_font_size)
473558
                 .color(name_color);
474559
 
475560
             // Use Pango CENTER alignment for proper text centering (like Dolphin/Nautilus)
@@ -479,11 +564,12 @@ impl GridView {
479564
                 .max_width((cell.width - 8) as i32);
480565
 
481566
             // Rectangle for the text area below the icon
567
+            let icon_size = self.icon_size.icon_size();
482568
             let text_rect = Rect::new(
483569
                 cell.x + 4,
484
-                cell.y + ICON_SIZE as i32 + 8,
570
+                cell.y + icon_size as i32 + 8,
485571
                 cell.width - 8,
486
-                cell.height - ICON_SIZE - 12,
572
+                cell.height - icon_size - 12,
487573
             );
488574
             // Add "@" suffix for symlinks
489575
             let display_name = if entry.is_symlink {
garfield/src/ui/help_modal.rsmodified
@@ -34,6 +34,7 @@ const KEYBINDS: &[(&str, &[KeybindEntry])] = &[
3434
         KeybindEntry { key: "Ctrl+2", description: "Grid view" },
3535
         KeybindEntry { key: "Ctrl+3", description: "Column view" },
3636
         KeybindEntry { key: "Ctrl+H", description: "Toggle hidden files" },
37
+        KeybindEntry { key: "Ctrl+=", description: "Cycle icon size" },
3738
     ]),
3839
     ("Tabs & Panes", &[
3940
         KeybindEntry { key: "Ctrl+T", description: "New tab" },
garfield/src/ui/tab.rsmodified
@@ -103,6 +103,11 @@ impl Tab {
103103
         self.view_mode = mode;
104104
     }
105105
 
106
+    /// Cycle icon size in grid view.
107
+    pub fn cycle_icon_size(&mut self) {
108
+        self.grid_view.cycle_icon_size();
109
+    }
110
+
106111
     /// Get history reference.
107112
     pub fn history(&self) -> &History {
108113
         &self.history