Skip to main content

edb_tui/ui/
borders.rs

1// EDB - Ethereum Debugger
2// Copyright (C) 2024 Zhuo Zhang and Wuqi Zhang
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Affero General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17//! Enhanced border system with Unicode box-drawing characters
18//!
19//! Provides beautiful rounded borders and dynamic highlighting for focused panels
20
21use ratatui::style::{Color, Style};
22use ratatui::widgets::{Block, BorderType, Borders};
23
24/// Enhanced border styles for panels
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum EnhancedBorderStyle {
27    /// Standard rounded corners with elegant Unicode characters
28    Rounded,
29    /// Double-line borders for emphasis
30    Double,
31    /// Thick borders for high priority panels
32    Thick,
33    /// Classic square borders (default ratatui style)
34    Square,
35}
36
37/// Enhanced border builder for panels
38pub struct EnhancedBorder {
39    style: EnhancedBorderStyle,
40    focused: bool,
41    title: Option<String>,
42    focused_color: Color,
43    unfocused_color: Color,
44}
45
46impl EnhancedBorder {
47    /// Create a new enhanced border
48    pub fn new(style: EnhancedBorderStyle) -> Self {
49        Self {
50            style,
51            focused: false,
52            title: None,
53            focused_color: Color::Cyan,
54            unfocused_color: Color::Gray,
55        }
56    }
57
58    /// Set focus state
59    pub fn focused(mut self, focused: bool) -> Self {
60        self.focused = focused;
61        self
62    }
63
64    /// Set border title
65    pub fn title<S: Into<String>>(mut self, title: S) -> Self {
66        self.title = Some(title.into());
67        self
68    }
69
70    /// Set focused border color
71    pub fn focused_color(mut self, color: Color) -> Self {
72        self.focused_color = color;
73        self
74    }
75
76    /// Set unfocused border color
77    pub fn unfocused_color(mut self, color: Color) -> Self {
78        self.unfocused_color = color;
79        self
80    }
81
82    /// Build the Block widget with enhanced styling
83    pub fn build(self) -> Block<'static> {
84        let border_color = if self.focused { self.focused_color } else { self.unfocused_color };
85
86        let border_type = match self.style {
87            EnhancedBorderStyle::Rounded => BorderType::Rounded,
88            EnhancedBorderStyle::Double => BorderType::Double,
89            EnhancedBorderStyle::Thick => BorderType::Thick,
90            EnhancedBorderStyle::Square => BorderType::Plain,
91        };
92
93        let mut block = Block::default()
94            .borders(Borders::ALL)
95            .border_type(border_type)
96            .border_style(self.get_border_style(border_color));
97
98        if let Some(title) = self.title {
99            // Add special indicators for focused panels
100            let title_with_indicator = if self.focused {
101                match self.style {
102                    EnhancedBorderStyle::Rounded => format!("╭─ {title} ─╮"),
103                    EnhancedBorderStyle::Double => format!("╔═ {title} ═╗"),
104                    EnhancedBorderStyle::Thick => format!("┏━ {title} ━┓"),
105                    EnhancedBorderStyle::Square => format!("┌─ {title} ─┐"),
106                }
107            } else {
108                title
109            };
110            block = block.title(title_with_indicator);
111        }
112
113        block
114    }
115
116    /// Get enhanced border style with potential animation effects
117    fn get_border_style(&self, base_color: Color) -> Style {
118        if self.focused {
119            // Enhanced styling for focused panels
120            Style::default().fg(base_color)
121        } else {
122            Style::default().fg(base_color)
123        }
124    }
125}
126
127/// Convenience functions for common border styles
128impl EnhancedBorder {
129    /// Create a rounded border (most common style)
130    pub fn rounded() -> Self {
131        Self::new(EnhancedBorderStyle::Rounded)
132    }
133
134    /// Create a double-line border for emphasis
135    pub fn double() -> Self {
136        Self::new(EnhancedBorderStyle::Double)
137    }
138
139    /// Create a thick border for high priority
140    pub fn thick() -> Self {
141        Self::new(EnhancedBorderStyle::Thick)
142    }
143
144    /// Create a square border (classic style)
145    pub fn square() -> Self {
146        Self::new(EnhancedBorderStyle::Square)
147    }
148}
149
150/// Enhanced border presets for different panel types
151pub struct BorderPresets;
152
153impl BorderPresets {
154    /// Terminal panel border - rounded with system styling
155    pub fn terminal(
156        focused: bool,
157        title: String,
158        focused_color: Color,
159        unfocused_color: Color,
160    ) -> Block<'static> {
161        EnhancedBorder::rounded()
162            .focused(focused)
163            .title(title)
164            .focused_color(focused_color)
165            .unfocused_color(unfocused_color)
166            .build()
167    }
168
169    /// Code panel border - double-line for emphasis
170    pub fn code(
171        focused: bool,
172        title: String,
173        focused_color: Color,
174        unfocused_color: Color,
175    ) -> Block<'static> {
176        EnhancedBorder::double()
177            .focused(focused)
178            .title(title)
179            .focused_color(focused_color)
180            .unfocused_color(unfocused_color)
181            .build()
182    }
183
184    /// Trace panel border - thick for importance
185    pub fn trace(
186        focused: bool,
187        title: String,
188        focused_color: Color,
189        unfocused_color: Color,
190    ) -> Block<'static> {
191        EnhancedBorder::thick()
192            .focused(focused)
193            .title(title)
194            .focused_color(focused_color)
195            .unfocused_color(unfocused_color)
196            .build()
197    }
198
199    /// Display panel border - rounded standard
200    pub fn display(
201        focused: bool,
202        title: String,
203        focused_color: Color,
204        unfocused_color: Color,
205    ) -> Block<'static> {
206        EnhancedBorder::rounded()
207            .focused(focused)
208            .title(title)
209            .focused_color(focused_color)
210            .unfocused_color(unfocused_color)
211            .build()
212    }
213}