@@ -49,6 +49,12 @@ pub enum ToolbarAction { |
| 49 | 49 | Trash, |
| 50 | 50 | /// Create new folder. |
| 51 | 51 | NewFolder, |
| 52 | + /// Small icon size (grid view). |
| 53 | + IconSizeSmall, |
| 54 | + /// Medium icon size (grid view). |
| 55 | + IconSizeMedium, |
| 56 | + /// Large icon size (grid view). |
| 57 | + IconSizeLarge, |
| 52 | 58 | } |
| 53 | 59 | |
| 54 | 60 | /// A toolbar button. |
@@ -65,6 +71,7 @@ pub struct Toolbar { |
| 65 | 71 | buttons: Vec<ToolbarButton>, |
| 66 | 72 | hovered: Option<usize>, |
| 67 | 73 | active_view: ToolbarAction, |
| 74 | + active_icon_size: ToolbarAction, |
| 68 | 75 | can_go_back: bool, |
| 69 | 76 | can_go_forward: bool, |
| 70 | 77 | has_selection: bool, |
@@ -79,6 +86,7 @@ impl Toolbar { |
| 79 | 86 | buttons: Vec::new(), |
| 80 | 87 | hovered: None, |
| 81 | 88 | active_view: ToolbarAction::ViewList, |
| 89 | + active_icon_size: ToolbarAction::IconSizeMedium, |
| 82 | 90 | can_go_back: false, |
| 83 | 91 | can_go_forward: false, |
| 84 | 92 | has_selection: false, |
@@ -99,6 +107,11 @@ impl Toolbar { |
| 99 | 107 | self.active_view = action; |
| 100 | 108 | } |
| 101 | 109 | |
| 110 | + /// Set active icon size. |
| 111 | + pub fn set_active_icon_size(&mut self, action: ToolbarAction) { |
| 112 | + self.active_icon_size = action; |
| 113 | + } |
| 114 | + |
| 102 | 115 | /// Set navigation state. |
| 103 | 116 | pub fn set_nav_state(&mut self, can_back: bool, can_forward: bool) { |
| 104 | 117 | self.can_go_back = can_back; |
@@ -154,6 +167,24 @@ impl Toolbar { |
| 154 | 167 | |
| 155 | 168 | x += GROUP_SEPARATOR as i32; |
| 156 | 169 | |
| 170 | + // Icon size buttons (for grid view) |
| 171 | + let size_buttons = [ |
| 172 | + (ToolbarAction::IconSizeSmall, "Small Icons (Ctrl+-)"), |
| 173 | + (ToolbarAction::IconSizeMedium, "Medium Icons"), |
| 174 | + (ToolbarAction::IconSizeLarge, "Large Icons (Ctrl++)"), |
| 175 | + ]; |
| 176 | + |
| 177 | + for (action, tooltip) in size_buttons { |
| 178 | + self.buttons.push(ToolbarButton { |
| 179 | + action, |
| 180 | + bounds: Rect::new(x, y, BUTTON_SIZE, BUTTON_SIZE), |
| 181 | + tooltip, |
| 182 | + }); |
| 183 | + x += BUTTON_SIZE as i32 + BUTTON_PADDING as i32; |
| 184 | + } |
| 185 | + |
| 186 | + x += GROUP_SEPARATOR as i32; |
| 187 | + |
| 157 | 188 | // Tab/pane buttons |
| 158 | 189 | let pane_buttons = [ |
| 159 | 190 | (ToolbarAction::NewTab, "New Tab (Ctrl+T)"), |
@@ -323,6 +354,9 @@ impl Toolbar { |
| 323 | 354 | ToolbarAction::ViewList | ToolbarAction::ViewGrid | ToolbarAction::ViewColumns => { |
| 324 | 355 | button.action == self.active_view |
| 325 | 356 | } |
| 357 | + ToolbarAction::IconSizeSmall | ToolbarAction::IconSizeMedium | ToolbarAction::IconSizeLarge => { |
| 358 | + button.action == self.active_icon_size |
| 359 | + } |
| 326 | 360 | _ => false, |
| 327 | 361 | }; |
| 328 | 362 | let is_disabled = match button.action { |
@@ -330,6 +364,10 @@ impl Toolbar { |
| 330 | 364 | ToolbarAction::GoForward => !self.can_go_forward, |
| 331 | 365 | ToolbarAction::Copy | ToolbarAction::Cut | ToolbarAction::Trash => !self.has_selection, |
| 332 | 366 | ToolbarAction::Paste => !self.has_clipboard, |
| 367 | + // Icon size buttons disabled when not in grid view |
| 368 | + ToolbarAction::IconSizeSmall | ToolbarAction::IconSizeMedium | ToolbarAction::IconSizeLarge => { |
| 369 | + self.active_view != ToolbarAction::ViewGrid |
| 370 | + } |
| 333 | 371 | _ => false, |
| 334 | 372 | }; |
| 335 | 373 | |
@@ -364,6 +402,9 @@ impl Toolbar { |
| 364 | 402 | ToolbarAction::ViewList => self.draw_list_icon(renderer, cx, cy, icon_color)?, |
| 365 | 403 | ToolbarAction::ViewGrid => self.draw_grid_icon(renderer, cx, cy, icon_color)?, |
| 366 | 404 | ToolbarAction::ViewColumns => self.draw_columns_icon(renderer, cx, cy, icon_color)?, |
| 405 | + ToolbarAction::IconSizeSmall => self.draw_size_small_icon(renderer, cx, cy, icon_color)?, |
| 406 | + ToolbarAction::IconSizeMedium => self.draw_size_medium_icon(renderer, cx, cy, icon_color)?, |
| 407 | + ToolbarAction::IconSizeLarge => self.draw_size_large_icon(renderer, cx, cy, icon_color)?, |
| 367 | 408 | ToolbarAction::NewTab => self.draw_new_tab_icon(renderer, cx, cy, icon_color)?, |
| 368 | 409 | ToolbarAction::SplitHorizontal => self.draw_split_h_icon(renderer, cx, cy, icon_color)?, |
| 369 | 410 | ToolbarAction::SplitVertical => self.draw_split_v_icon(renderer, cx, cy, icon_color)?, |
@@ -444,6 +485,57 @@ impl Toolbar { |
| 444 | 485 | Ok(()) |
| 445 | 486 | } |
| 446 | 487 | |
| 488 | + fn draw_size_small_icon(&self, renderer: &Renderer, cx: f64, cy: f64, color: gartk_core::Color) -> Result<()> { |
| 489 | + // Small grid of tiny squares (4x4) |
| 490 | + let size = 2.0; |
| 491 | + let gap = 1.5; |
| 492 | + let total = 4.0 * size + 3.0 * gap; |
| 493 | + let start = -total / 2.0; |
| 494 | + for row in 0..4 { |
| 495 | + for col in 0..4 { |
| 496 | + let x = cx + start + (col as f64) * (size + gap); |
| 497 | + let y = cy + start + (row as f64) * (size + gap); |
| 498 | + let rect = Rect::new(x as i32, y as i32, size as u32, size as u32); |
| 499 | + renderer.fill_rect(rect, color)?; |
| 500 | + } |
| 501 | + } |
| 502 | + Ok(()) |
| 503 | + } |
| 504 | + |
| 505 | + fn draw_size_medium_icon(&self, renderer: &Renderer, cx: f64, cy: f64, color: gartk_core::Color) -> Result<()> { |
| 506 | + // Medium grid of squares (3x3) |
| 507 | + let size = 3.0; |
| 508 | + let gap = 2.0; |
| 509 | + let total = 3.0 * size + 2.0 * gap; |
| 510 | + let start = -total / 2.0; |
| 511 | + for row in 0..3 { |
| 512 | + for col in 0..3 { |
| 513 | + let x = cx + start + (col as f64) * (size + gap); |
| 514 | + let y = cy + start + (row as f64) * (size + gap); |
| 515 | + let rect = Rect::new(x as i32, y as i32, size as u32, size as u32); |
| 516 | + renderer.fill_rect(rect, color)?; |
| 517 | + } |
| 518 | + } |
| 519 | + Ok(()) |
| 520 | + } |
| 521 | + |
| 522 | + fn draw_size_large_icon(&self, renderer: &Renderer, cx: f64, cy: f64, color: gartk_core::Color) -> Result<()> { |
| 523 | + // Large grid of squares (2x2) |
| 524 | + let size = 5.0; |
| 525 | + let gap = 2.0; |
| 526 | + let total = 2.0 * size + gap; |
| 527 | + let start = -total / 2.0; |
| 528 | + for row in 0..2 { |
| 529 | + for col in 0..2 { |
| 530 | + let x = cx + start + (col as f64) * (size + gap); |
| 531 | + let y = cy + start + (row as f64) * (size + gap); |
| 532 | + let rect = Rect::new(x as i32, y as i32, size as u32, size as u32); |
| 533 | + renderer.fill_rect(rect, color)?; |
| 534 | + } |
| 535 | + } |
| 536 | + Ok(()) |
| 537 | + } |
| 538 | + |
| 447 | 539 | fn draw_new_tab_icon(&self, renderer: &Renderer, cx: f64, cy: f64, color: gartk_core::Color) -> Result<()> { |
| 448 | 540 | // Plus sign |
| 449 | 541 | let size = 8.0; |