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 {
618
                     self.set_view_mode(ViewMode::Columns);
618
                     self.set_view_mode(ViewMode::Columns);
619
                     return;
619
                     return;
620
                 }
620
                 }
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
+                }
621
                 Key::Char('t') | Key::Char('T') => {
630
                 Key::Char('t') | Key::Char('T') => {
622
                     self.new_tab();
631
                     self.new_tab();
623
                     return;
632
                     return;
garfield/src/ui/grid_view.rsmodified
@@ -5,15 +5,65 @@ use gartk_core::{Color, Modifiers, Point, Rect};
5
 use gartk_render::{Renderer, TextAlign, TextStyle};
5
 use gartk_render::{Renderer, TextAlign, TextStyle};
6
 use std::collections::HashSet;
6
 use std::collections::HashSet;
7
 
7
 
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
-
14
 /// Padding around cells.
8
 /// Padding around cells.
15
 pub const CELL_PADDING: u32 = 8;
9
 pub const CELL_PADDING: u32 = 8;
16
 
10
 
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
+
17
 /// Grid view for displaying file entries as icons.
67
 /// Grid view for displaying file entries as icons.
18
 pub struct GridView {
68
 pub struct GridView {
19
     /// Entries to display.
69
     /// Entries to display.
@@ -38,12 +88,15 @@ pub struct GridView {
38
     drag_start: Option<Point>,
88
     drag_start: Option<Point>,
39
     /// Rubber band current position.
89
     /// Rubber band current position.
40
     drag_current: Option<Point>,
90
     drag_current: Option<Point>,
91
+    /// Icon size setting.
92
+    icon_size: IconSize,
41
 }
93
 }
42
 
94
 
43
 impl GridView {
95
 impl GridView {
44
     /// Create a new grid view.
96
     /// Create a new grid view.
45
     pub fn new(bounds: Rect) -> Self {
97
     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);
47
         Self {
100
         Self {
48
             entries: Vec::new(),
101
             entries: Vec::new(),
49
             focused: 0,
102
             focused: 0,
@@ -56,12 +109,35 @@ impl GridView {
56
             hovered: None,
109
             hovered: None,
57
             drag_start: None,
110
             drag_start: None,
58
             drag_current: None,
111
             drag_current: None,
112
+            icon_size,
59
         }
113
         }
60
     }
114
     }
61
 
115
 
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
+
62
     /// Calculate number of columns that fit in the given width.
122
     /// Calculate number of columns that fit in the given width.
63
-    fn calculate_columns(width: u32) -> usize {
123
+    fn calculate_columns(&self, width: u32) -> usize {
64
-        ((width - CELL_PADDING) / (CELL_SIZE + CELL_PADDING)).max(1) as 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());
65
     }
141
     }
66
 
142
 
67
     /// Set the entries to display.
143
     /// Set the entries to display.
@@ -104,7 +180,8 @@ impl GridView {
104
 
180
 
105
     /// Get the number of visible rows that fit in the view.
181
     /// Get the number of visible rows that fit in the view.
106
     fn visible_rows(&self) -> usize {
182
     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
108
     }
185
     }
109
 
186
 
110
     /// Get current sort settings (grid view doesn't track these, uses external).
187
     /// Get current sort settings (grid view doesn't track these, uses external).
@@ -226,7 +303,7 @@ impl GridView {
226
     /// Update bounds.
303
     /// Update bounds.
227
     pub fn set_bounds(&mut self, bounds: Rect) {
304
     pub fn set_bounds(&mut self, bounds: Rect) {
228
         self.bounds = bounds;
305
         self.bounds = bounds;
229
-        self.columns = Self::calculate_columns(bounds.width);
306
+        self.columns = self.calculate_columns(bounds.width);
230
     }
307
     }
231
 
308
 
232
     /// Get cell bounds for an index.
309
     /// Get cell bounds for an index.
@@ -234,11 +311,12 @@ impl GridView {
234
         let visible_index = index.saturating_sub(self.scroll_offset * self.columns);
311
         let visible_index = index.saturating_sub(self.scroll_offset * self.columns);
235
         let col = visible_index % self.columns;
312
         let col = visible_index % self.columns;
236
         let row = visible_index / self.columns;
313
         let row = visible_index / self.columns;
314
+        let cell_size = self.icon_size.cell_size();
237
 
315
 
238
-        let x = self.bounds.x + CELL_PADDING as i32 + (col 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);
239
-        let y = self.bounds.y + CELL_PADDING as i32 + (row 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);
240
 
318
 
241
-        Rect::new(x, y, CELL_SIZE, CELL_SIZE)
319
+        Rect::new(x, y, cell_size, cell_size)
242
     }
320
     }
243
 
321
 
244
     /// Handle mouse move for hover effects and rubber band drag.
322
     /// Handle mouse move for hover effects and rubber band drag.
@@ -448,14 +526,20 @@ impl GridView {
448
                 }
526
                 }
449
             };
527
             };
450
 
528
 
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
+            };
451
             let icon_style = TextStyle::new()
535
             let icon_style = TextStyle::new()
452
                 .font_family(&theme.font_family)
536
                 .font_family(&theme.font_family)
453
-                .font_size(32.0)
537
+                .font_size(icon_font_size)
454
                 .color(icon_color);
538
                 .color(icon_color);
455
 
539
 
456
             // Center icon horizontally in cell
540
             // Center icon horizontally in cell
457
             let icon_center_x = cell.x + cell.width as i32 / 2;
541
             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;
459
             renderer.text_centered(icon, Point::new(icon_center_x, icon_center_y), &icon_style)?;
543
             renderer.text_centered(icon, Point::new(icon_center_x, icon_center_y), &icon_style)?;
460
 
544
 
461
             // File name (truncated)
545
             // File name (truncated)
@@ -467,9 +551,10 @@ impl GridView {
467
                 theme.item_foreground
551
                 theme.item_foreground
468
             };
552
             };
469
 
553
 
554
+            let name_font_size = self.icon_size.font_size();
470
             let name_style = TextStyle::new()
555
             let name_style = TextStyle::new()
471
                 .font_family(&theme.font_family)
556
                 .font_family(&theme.font_family)
472
-                .font_size(theme.font_size - 1.0)
557
+                .font_size(name_font_size)
473
                 .color(name_color);
558
                 .color(name_color);
474
 
559
 
475
             // Use Pango CENTER alignment for proper text centering (like Dolphin/Nautilus)
560
             // Use Pango CENTER alignment for proper text centering (like Dolphin/Nautilus)
@@ -479,11 +564,12 @@ impl GridView {
479
                 .max_width((cell.width - 8) as i32);
564
                 .max_width((cell.width - 8) as i32);
480
 
565
 
481
             // Rectangle for the text area below the icon
566
             // Rectangle for the text area below the icon
567
+            let icon_size = self.icon_size.icon_size();
482
             let text_rect = Rect::new(
568
             let text_rect = Rect::new(
483
                 cell.x + 4,
569
                 cell.x + 4,
484
-                cell.y + ICON_SIZE as i32 + 8,
570
+                cell.y + icon_size as i32 + 8,
485
                 cell.width - 8,
571
                 cell.width - 8,
486
-                cell.height - ICON_SIZE - 12,
572
+                cell.height - icon_size - 12,
487
             );
573
             );
488
             // Add "@" suffix for symlinks
574
             // Add "@" suffix for symlinks
489
             let display_name = if entry.is_symlink {
575
             let display_name = if entry.is_symlink {
garfield/src/ui/help_modal.rsmodified
@@ -34,6 +34,7 @@ const KEYBINDS: &[(&str, &[KeybindEntry])] = &[
34
         KeybindEntry { key: "Ctrl+2", description: "Grid view" },
34
         KeybindEntry { key: "Ctrl+2", description: "Grid view" },
35
         KeybindEntry { key: "Ctrl+3", description: "Column view" },
35
         KeybindEntry { key: "Ctrl+3", description: "Column view" },
36
         KeybindEntry { key: "Ctrl+H", description: "Toggle hidden files" },
36
         KeybindEntry { key: "Ctrl+H", description: "Toggle hidden files" },
37
+        KeybindEntry { key: "Ctrl+=", description: "Cycle icon size" },
37
     ]),
38
     ]),
38
     ("Tabs & Panes", &[
39
     ("Tabs & Panes", &[
39
         KeybindEntry { key: "Ctrl+T", description: "New tab" },
40
         KeybindEntry { key: "Ctrl+T", description: "New tab" },
garfield/src/ui/tab.rsmodified
@@ -103,6 +103,11 @@ impl Tab {
103
         self.view_mode = mode;
103
         self.view_mode = mode;
104
     }
104
     }
105
 
105
 
106
+    /// Cycle icon size in grid view.
107
+    pub fn cycle_icon_size(&mut self) {
108
+        self.grid_view.cycle_icon_size();
109
+    }
110
+
106
     /// Get history reference.
111
     /// Get history reference.
107
     pub fn history(&self) -> &History {
112
     pub fn history(&self) -> &History {
108
         &self.history
113
         &self.history