@@ -23,6 +23,12 @@ const HEADER_HEIGHT: u32 = 40; |
| 23 | 23 | /// Graph height. |
| 24 | 24 | const GRAPH_HEIGHT: u32 = 150; |
| 25 | 25 | |
| 26 | +/// Horizontal content padding. |
| 27 | +const CONTENT_PADDING: u32 = 16; |
| 28 | + |
| 29 | +/// Vertical gap between sections. |
| 30 | +const SECTION_GAP: u32 = 12; |
| 31 | + |
| 26 | 32 | /// Default window dimensions. |
| 27 | 33 | const DEFAULT_WIDTH: u32 = 800; |
| 28 | 34 | const DEFAULT_HEIGHT: u32 = 600; |
@@ -87,7 +93,8 @@ impl App { |
| 87 | 93 | |
| 88 | 94 | // Create components |
| 89 | 95 | let header = HeaderBar::new(Rect::new(0, 0, width, HEADER_HEIGHT)); |
| 90 | | - let tab_bar = TabBar::new(Rect::new(0, HEADER_HEIGHT as i32, width, TAB_BAR_HEIGHT)); |
| 96 | + let tab_bar_y = HEADER_HEIGHT + 4; // Small gap below header |
| 97 | + let tab_bar = TabBar::new(Rect::new(0, tab_bar_y as i32, width, TAB_BAR_HEIGHT)); |
| 91 | 98 | let process_list = Self::create_process_list(width, height); |
| 92 | 99 | |
| 93 | 100 | // Check if daemon is available |
@@ -117,9 +124,12 @@ impl App { |
| 117 | 124 | |
| 118 | 125 | /// Create process list with correct bounds. |
| 119 | 126 | fn create_process_list(width: u32, height: u32) -> ProcessList { |
| 120 | | - let content_start = HEADER_HEIGHT + TAB_BAR_HEIGHT + GRAPH_HEIGHT + 24; // 24 for graph label |
| 127 | + // Account for: header + gap + tab bar + section gap + graph label + graph + section gap |
| 128 | + let tab_bar_y = HEADER_HEIGHT + 4; |
| 129 | + let content_start = tab_bar_y + TAB_BAR_HEIGHT + SECTION_GAP + 20 + GRAPH_HEIGHT + SECTION_GAP; |
| 121 | 130 | let list_height = height.saturating_sub(content_start); |
| 122 | | - ProcessList::new(Rect::new(0, content_start as i32, width, list_height)) |
| 131 | + let list_width = width.saturating_sub(CONTENT_PADDING * 2); |
| 132 | + ProcessList::new(Rect::new(CONTENT_PADDING as i32, content_start as i32, list_width, list_height)) |
| 123 | 133 | } |
| 124 | 134 | |
| 125 | 135 | /// Check if daemon is available by attempting a connection. |
@@ -271,8 +281,7 @@ impl App { |
| 271 | 281 | |
| 272 | 282 | /// Render the content for the active tab. |
| 273 | 283 | fn render_tab_content(&self, content_y: i32, _content_height: u32) -> Result<()> { |
| 274 | | - let padding = 12; |
| 275 | | - let graph_width = self.width - (padding * 2) as u32; |
| 284 | + let graph_width = self.width - (CONTENT_PADDING * 2); |
| 276 | 285 | |
| 277 | 286 | // Get Cairo context for graph rendering |
| 278 | 287 | let ctx = self.renderer.context()?; |
@@ -281,7 +290,7 @@ impl App { |
| 281 | 290 | ..LineGraph::default() |
| 282 | 291 | }; |
| 283 | 292 | |
| 284 | | - let mut y = content_y + padding as i32; |
| 293 | + let mut y = content_y + SECTION_GAP as i32; |
| 285 | 294 | |
| 286 | 295 | match self.tab_bar.active() { |
| 287 | 296 | Tab::Cpu => { |
@@ -293,7 +302,7 @@ impl App { |
| 293 | 302 | }; |
| 294 | 303 | self.renderer.text( |
| 295 | 304 | &cpu_label, |
| 296 | | - padding as f64, |
| 305 | + CONTENT_PADDING as f64, |
| 297 | 306 | y as f64 + 14.0, |
| 298 | 307 | &TextStyle { |
| 299 | 308 | font_family: "monospace".to_string(), |
@@ -322,7 +331,7 @@ impl App { |
| 322 | 331 | y += 20; |
| 323 | 332 | |
| 324 | 333 | // CPU Graph |
| 325 | | - let graph_rect = Rect::new(padding as i32, y, graph_width, GRAPH_HEIGHT); |
| 334 | + let graph_rect = Rect::new(CONTENT_PADDING as i32, y, graph_width, GRAPH_HEIGHT); |
| 326 | 335 | let mut cpu_series = DataSeries::new("CPU", self.theme.cpu_color); |
| 327 | 336 | cpu_series.set_values(self.cpu_history.iter().map(|s| s.usage_percent).collect()); |
| 328 | 337 | graph.render(&ctx, graph_rect, &[cpu_series], &self.theme); |
@@ -342,7 +351,7 @@ impl App { |
| 342 | 351 | }; |
| 343 | 352 | self.renderer.text( |
| 344 | 353 | &mem_label, |
| 345 | | - padding as f64, |
| 354 | + CONTENT_PADDING as f64, |
| 346 | 355 | y as f64 + 14.0, |
| 347 | 356 | &TextStyle { |
| 348 | 357 | font_family: "monospace".to_string(), |
@@ -375,7 +384,7 @@ impl App { |
| 375 | 384 | y += 20; |
| 376 | 385 | |
| 377 | 386 | // Memory Graph |
| 378 | | - let graph_rect = Rect::new(padding as i32, y, graph_width, GRAPH_HEIGHT); |
| 387 | + let graph_rect = Rect::new(CONTENT_PADDING as i32, y, graph_width, GRAPH_HEIGHT); |
| 379 | 388 | let mut mem_series = DataSeries::new("Memory", self.theme.memory_color); |
| 380 | 389 | let mut swap_series = DataSeries::new("Swap", self.theme.swap_color); |
| 381 | 390 | mem_series.set_values(self.memory_history.iter().map(|s| s.usage_percent).collect()); |
@@ -436,7 +445,8 @@ impl App { |
| 436 | 445 | |
| 437 | 446 | // Update component bounds |
| 438 | 447 | self.header = HeaderBar::new(Rect::new(0, 0, width, HEADER_HEIGHT)); |
| 439 | | - self.tab_bar.set_bounds(Rect::new(0, HEADER_HEIGHT as i32, width, TAB_BAR_HEIGHT)); |
| 448 | + let tab_bar_y = HEADER_HEIGHT + 4; |
| 449 | + self.tab_bar.set_bounds(Rect::new(0, tab_bar_y as i32, width, TAB_BAR_HEIGHT)); |
| 440 | 450 | self.process_list = Self::create_process_list(width, height); |
| 441 | 451 | self.process_list.set_processes(self.processes.clone()); |
| 442 | 452 | |