tui_gradient_block/
lib.rs

1use bitflags::bitflags;
2use ratatui::{
3    buffer::Buffer,
4    layout::Rect,
5    style::{Color, Style},
6    symbols::border::{DOUBLE, PLAIN, ROUNDED, THICK},
7    text::{Line, Span},
8    widgets::{Block, Borders, Paragraph, Widget, Wrap},
9};
10use std::rc::Rc;
11use unicode_width::UnicodeWidthChar;
12/// A struct that represents a customizable block with gradient text, borders, and other visual elements.
13///
14/// This struct allows you to create and manage blocks that have a gradient color effect for text,
15/// customizable borders, and areas with specific alignments and fill styles.
16///
17/// # Fields
18/// - `bordertype`: Specifies the type of border style used for the block.
19/// - `fill`: Defines the fill style for the block's area (e.g., solid or gradient).
20/// - `top_titles`: A vector of tuples where each tuple contains:
21///   - A `String` representing the title text.
22///   - A `TitleAlignment` indicating the alignment of the title.
23///   - An optional tuple of gradient colors (represented as a vector of `(u8, u8, u8)` tuples) and
24///     a factor that controls the spread of the gradient effect.
25/// - `bottom_titles`: A similar vector to `top_titles`, but for titles placed at the bottom of the block.
26/// - `border_symbols`: Defines the symbols used for the block's borders.
27/// - `border_segments`: Defines the segments of the block's border.
28/// - `split_segments`: Specifies how the block's border is split into different sections.
29/// - `area`: A `Rect` representing the block's area, typically used for positioning and layout.
30///
31/// # Example
32/// ```rust
33/// let gradient_block = TuiGradientblock {
34///     bordertype: BorderStyle::Solid,
35///     fill: Fill::SolidColor((255, 0, 0)),
36///     top_titles: vec![("Top Title".to_owned(), TitleAlignment::Center, None)],
37///     bottom_titles: vec![("Bottom Title".to_owned(), TitleAlignment::Right, None)],
38///     border_symbols: BorderSymbols::Default,
39///     border_segments: BorderSegments::Full,
40///     split_segments: SplitBorderSegments::None,
41///     area: Rect::new(0, 0, 10, 5),
42/// };
43/// ```
44
45#[derive(Clone)]
46pub struct TuiGradientblock {
47    bordertype: BorderStyle,
48    fill: Fill,
49    top_titles: Vec<(String, TitleAlignment, Option<(Vec<(u8, u8, u8)>, f32)>)>,
50    bottom_titles: Vec<(String, TitleAlignment, Option<(Vec<(u8, u8, u8)>, f32)>)>,
51    border_symbols: BorderSymbols,
52    border_segments: BorderSegments,
53    split_segments: SplitBorderSegments,
54    area: Rect,
55}
56/// A constant error message displayed when there are not enough colors provided for a gradient.
57/// It encourages the user to use at least two colors for a gradient effect or repeat the same color
58/// if a solid color is desired.
59///
60/// Example of how to provide colors for a solid color:
61/// ❌ `[(250, 2, 238)]`
62/// ✅ `[(250, 2, 238), (250, 2, 238)]`
63pub const ERROR_MESSAGE: &str = "
64╓───── IMPORTANT ─────╖
65║                     ║
66║ Use at least two    ║
67║ colors.             ║
68║                     ║
69║ If you want to use  ║
70║ a solid color,      ║
71║ enter the same      ║
72║ color more than once║
73║                     ║
74║ Example: Solid pink ║
75║                     ║
76║ ❌ [(250, 2, 238)]  ║
77║ ✅ [                ║
78║     (250, 2, 238),  ║
79║     (250, 2, 238),  ║
80║    ]                ║
81║                     ║
82╙─────────────────────╜
83";
84
85/// A set of predefined border styles for different visual aesthetics. Each `BorderStyleInfo`
86/// instance defines the characters to be used for different parts of the border (corners, sides, and centers).
87///
88/// # Variants:
89/// - `MISC1`: A style with standard "+" corners, and "=" for top/bottom edges, with "|" for side edges.
90/// - `MISC2`: A style with "╘" and "╛" for the bottom corners, and "=" for top and bottom edges.
91/// - `MISC3`: A style with "╬" for the corners and sides, and "═" for the top and bottom edges.
92/// - `MISC4`: A unique style with "$" corners, "~" for center sides, and "─" for top and bottom edges.
93///
94/// These styles can be used to customize the appearance of borders for blocks, areas, or text layouts.
95pub const MISC1: BorderStyleInfo = BorderStyleInfo {
96    top_left: '+',
97    bottom_left: '+',
98    top_right: '+',
99    bottom_right: '+',
100    top: '=',
101    bottom: '=',
102    left: '|',
103    right: '|',
104    bottom_center: '=',
105    top_center: '=',
106    right_center: '|',
107    left_center: '|',
108};
109
110/// A border style with special bottom corners "╘" and "╛" and "═" edges for a different aesthetic.
111pub const MISC2: BorderStyleInfo = BorderStyleInfo {
112    top_left: '╔',
113    bottom_left: '╚',
114    top_right: '╗',
115    bottom_right: '╝',
116    top: '═',
117    bottom: '═',
118    right_center: '╬',
119    left_center: '╬',
120    left: '║',
121    right: '║',
122    bottom_center: '╬',
123    top_center: '╬',
124};
125
126/// A border style with "╬" for the corners and sides, giving a more solid and ornate border.
127pub const MISC3: BorderStyleInfo = BorderStyleInfo {
128    top_left: '╬',
129    bottom_left: '╬',
130    top_right: '╬',
131    bottom_right: '╬',
132    top: '═',
133    bottom: '═',
134    left: '║',
135    right: '║',
136    bottom_center: '═',
137    top_center: '═',
138    right_center: '║',
139    left_center: '║',
140};
141
142/// A more unique border style featuring "$" for the corners, "~" for the center sides, and "─" for the edges.
143pub const MISC4: BorderStyleInfo = BorderStyleInfo {
144    top_left: '$',
145    bottom_left: '$',
146    top_right: '$',
147    bottom_right: '$',
148    top: '─',
149    bottom: '─',
150    left: '│',
151    right: '│',
152    bottom_center: '$',
153    top_center: '~',
154    right_center: '~',
155    left_center: '~',
156};
157
158/// A struct that defines the characters used for different parts of a border's visual appearance.
159/// Each field specifies a character to represent a particular section of the border.
160///
161/// # Fields
162/// - `top_left`: The character used for the top-left corner of the border.
163/// - `bottom_left`: The character used for the bottom-left corner of the border.
164/// - `top_right`: The character used for the top-right corner of the border.
165/// - `bottom_right`: The character used for the bottom-right corner of the border.
166/// - `top`: The character used for the top edge of the border.
167/// - `bottom`: The character used for the bottom edge of the border.
168/// - `left`: The character used for the left side of the border.
169/// - `right`: The character used for the right side of the border.
170/// - `bottom_center`: The character used for the bottom center section of the border.
171/// - `top_center`: The character used for the top center section of the border.
172/// - `right_center`: The character used for the right center section of the border.
173/// - `left_center`: The character used for the left center section of the border.
174pub struct BorderStyleInfo {
175    pub top_left: char,
176    pub bottom_left: char,
177    pub top_right: char,
178    pub bottom_right: char,
179    pub top: char,
180    pub bottom: char,
181    pub left: char,
182    pub right: char,
183    pub bottom_center: char,
184    pub top_center: char,
185    pub right_center: char,
186    pub left_center: char,
187}
188
189impl TuiGradientblock {
190    pub fn new(area: &Rect, split_segments: SplitBorderSegments) -> Self {
191        Self {
192            bordertype: BorderStyle::Plain,
193            fill: Fill {
194                fill_string: None,
195                gradient: None,
196            },
197            top_titles: Vec::new(),
198            bottom_titles: Vec::new(),
199            border_symbols: BorderSymbols {
200                top_left: None,
201                top_right: None,
202                bottom_left: None,
203                bottom_right: None,
204                top_center: None,
205                bottom_center: None,
206                left_center: None,
207                right_center: None,
208                bottom_horizontal: None,
209                top_horizontal: None,
210                left_vertical: None,
211                right_vertical: None,
212                top_horizontal_right: None,
213                bottom_horizontal_right: None,
214                top_horizontal_left: None,
215                bottom_horizontal_left: None,
216                top_vertical_right: None,
217                bottom_vertical_right: None,
218                top_vertical_left: None,
219                bottom_vertical_left: None,
220            },
221            border_segments: BorderSegments::new(area),
222            split_segments,
223            area: *area,
224        }
225    }
226    /// Interpolates between two colors based on a factor and a time value (t).
227    /// This function computes a smooth transition between the `start` and `end` RGB colors
228    /// using the given parameter `t` (which represents the position between the colors)
229    /// and `factor` (which controls the curve of the interpolation).
230    ///
231    /// # Parameters
232    /// - `start`: A tuple representing the RGB values of the starting color (each value is a `u8`).
233    /// - `end`: A tuple representing the RGB values of the ending color (each value is a `u8`).
234    /// - `t`: A floating-point value (`f32`) between 0 and 1 that represents the interpolation factor,
235    ///   where `t = 0` gives the `start` color, and `t = 1` gives the `end` color.
236    /// - `factor`: A floating-point value (`f32`) that influences the smoothness or intensity of the interpolation.
237    ///   Higher values make the interpolation curve sharper, while lower values create a more gradual transition.
238    ///
239    /// # Returns
240    /// A tuple `(u8, u8, u8)` representing the interpolated RGB color, where each value is a byte (0-255).
241    ///
242    /// # Example
243    /// ```rust
244    /// let start_color = (255, 0, 0); // Red
245    /// let end_color = (0, 0, 255); // Blue
246    /// let t = 0.5; // Midway between the colors
247    /// let factor = 1.0; // Linear interpolation
248    /// let result = interpolate_color(start_color, end_color, t, factor);
249    /// ```
250    /// In this example, `result` will contain an RGB value that is a mix of red and blue, producing purple.
251    /// # Note
252    /// - The interpolation is calculated using a smooth function based on `t` raised to the power of `factor`,
253    ///   which controls the rate of transition between the `start` and `end` colors.
254    pub fn interpolate_color(
255        start: (u8, u8, u8),
256        end: (u8, u8, u8),
257        t: f32,
258        factor: f32,
259    ) -> (u8, u8, u8) {
260        let lerp = |s, e| ((1.0 - t.powf(factor)) * (s as f32) + t.powf(factor) * (e as f32)) as u8;
261        (
262            lerp(start.0, end.0),
263            lerp(start.1, end.1),
264            lerp(start.2, end.2),
265        )
266    }
267    /// Creates a gradient effect on a given text by interpolating between a list of colors
268    /// based on the position of each character in the string.
269    ///
270    /// # Parameters
271    /// - `text`: A reference to the input `String` for which the gradient effect will be applied.
272    /// - `colors`: A vector of tuples representing the RGB values of the gradient colors. Each tuple
273    ///   contains three `u8` values representing the Red, Green, and Blue components of a color.
274    /// - `factor`: A floating-point value (`f32`) that determines the intensity or spread of the gradient.
275    ///   Higher values will increase the spread of the gradient colors.
276    ///
277    /// # Returns
278    /// A `Vec<Span<'static>>` containing `Span` elements, where each `Span` represents a styled portion
279    /// of the input text with the corresponding color from the gradient.
280    ///
281    /// # Panics
282    /// This function will panic if the number of colors in `colors` is less than 2. A gradient requires
283    /// at least two colors to interpolate between. If fewer colors are provided, the following error message
284    /// will be displayed:
285    ///
286    /// ```text
287    /// ╓───── IMPORTANT ─────╖
288    /// ║                     ║
289    /// ║ Use at least two    ║
290    /// ║ colors.             ║
291    /// ║                     ║
292    /// ║ If you want to use  ║
293    /// ║ a solid color,      ║
294    /// ║ enter the same      ║
295    /// ║ color more than once║
296    /// ║                     ║
297    /// ║ Example: Solid pink ║
298    /// ║                     ║
299    /// ║ ❌ [(250, 2, 238)]  ║
300    /// ║ ✅ [                ║
301    /// ║     (250, 2, 238),  ║
302    /// ║     (250, 2, 238),  ║
303    /// ║    ]                ║
304    /// ║                     ║
305    /// ╙─────────────────────╜
306    /// ```
307
308    /// # Example
309    /// ```rust
310    /// let text = "Hello, World!".to_string();
311    /// let colors = vec![(255, 0, 0), (0, 255, 0), (0, 0, 255)];
312    /// let factor = 1.0;
313    /// let gradient_text = create_gradient_text(&text, colors, factor);
314    /// ```
315    /// In the above example, the `gradient_text` will be a vector of `Span`s with the text "Hello, World!"
316    /// styled with a gradient transitioning from red to green to blue.
317    /// # Note
318    /// - The `interpolate_color` function is used internally to calculate the intermediate colors based on the
319    ///   position of the character relative to the total width of the text.
320
321    pub fn create_gradient_text(
322        text: &str,
323        colors: Vec<(u8, u8, u8)>,
324        factor: f32,
325    ) -> Vec<Span<'static>> {
326        let mut gradient_colors = Vec::new();
327
328        let char_widths: Vec<usize> = text.chars().map(|c| c.width().unwrap_or(1)).collect();
329        let total_width: usize = char_widths.iter().sum();
330
331        let num_colors = colors.len();
332
333        if num_colors < 2 {
334            ratatui::restore();
335            panic!("{}", ERROR_MESSAGE);
336        }
337        let mut accumulated_width = 0.0;
338        for (i, _) in text.chars().enumerate() {
339            let char_width = char_widths[i] as f32;
340            let relative_pos = accumulated_width / total_width as f32;
341            let section_index = (relative_pos * (num_colors - 1) as f32).floor() as usize;
342            let t = (relative_pos * (num_colors - 1) as f32) % 1.0;
343            let next_color_index = (section_index + 1).min(num_colors - 1);
344            gradient_colors.push(Self::interpolate_color(
345                colors[section_index],
346                colors[next_color_index],
347                t,
348                factor,
349            ));
350            accumulated_width += char_width;
351        }
352        let mut gradient_text = Vec::new();
353        for (i, c) in text.chars().zip(gradient_colors) {
354            gradient_text.push(Span::styled(
355                i.to_string(),
356                Style::default().fg(Color::Rgb(c.0, c.1, c.2)),
357            ));
358        }
359        gradient_text
360    }
361    /// Sets gradient colors for specific segments of the border.
362    ///
363    /// # Parameters
364    /// - `gradientlist`: A vector of tuples where each tuple contains:
365    ///   - A `GradientSegments` enum value specifying which border segment to apply the gradient to.
366    ///   - A vector of RGB color tuples (`Vec<(u8, u8, u8)>`) representing the gradient colors.
367    ///   - A `f32` value representing the gradient factor (e.g., intensity or blending weight).
368    ///
369    /// # Notes
370    /// - If a gradient should be a solid color, provide the same RGB value twice.
371    /// - Gradients must have at least two different colors to transition properly.
372    ///
373    /// # Example 1: Applying a gradient to the top border
374    /// ```
375    /// let border = TuiGradientblock::new().set_gradients(vec![
376    ///     (GradientSegments::Top, vec![(255, 0, 0), (0, 0, 255)], 0.5),
377    /// ]);
378    /// ```
379    ///
380    /// # Example 2: Applying a solid color to the right border
381    /// ```
382    /// let border = TuiGradientblock::new().set_gradients(vec![
383    ///     (GradientSegments::Right, vec![(50, 50, 50), (50, 50, 50)], 1.0),
384    /// ]);
385    /// ```
386    pub fn set_gradients(
387        mut self,
388        gradientlist: Vec<(GradientSegments, Vec<(u8, u8, u8)>, f32)>,
389    ) -> Self {
390        for (segment, colors, factor) in gradientlist {
391            let gradient_data = Some((colors, factor));
392
393            match segment {
394                GradientSegments::Top => {
395                    self.border_segments.top_ln.gradient = gradient_data;
396                    self.border_segments.top_ln.should_use_gradient = true;
397                }
398                GradientSegments::Bottom => {
399                    self.border_segments.bottom_ln.gradient = gradient_data;
400                    self.border_segments.bottom_ln.should_use_gradient = true;
401                }
402                GradientSegments::Left => {
403                    self.border_segments.left_ln.gradient = gradient_data;
404                    self.border_segments.left_ln.should_use_gradient = true;
405                }
406                GradientSegments::Right => {
407                    self.border_segments.right_ln.gradient = gradient_data;
408                    self.border_segments.right_ln.should_use_gradient = true;
409                }
410                GradientSegments::TopHorizontalLeftLn => {
411                    self.border_segments.top_horizontal_left_ln.gradient = gradient_data;
412                    self.border_segments
413                        .top_horizontal_left_ln
414                        .should_use_gradient = true;
415                }
416                GradientSegments::TopHorizontalRightLn => {
417                    self.border_segments.top_horizontal_right_ln.gradient = gradient_data;
418                    self.border_segments
419                        .top_horizontal_right_ln
420                        .should_use_gradient = true;
421                }
422                GradientSegments::BottomHorizontalLeftLn => {
423                    self.border_segments.bottom_horizontal_left_ln.gradient = gradient_data;
424                    self.border_segments
425                        .bottom_horizontal_left_ln
426                        .should_use_gradient = true;
427                }
428                GradientSegments::BottomHorizontalRightLn => {
429                    self.border_segments.bottom_horizontal_right_ln.gradient = gradient_data;
430                    self.border_segments
431                        .bottom_horizontal_right_ln
432                        .should_use_gradient = true;
433                }
434                GradientSegments::TopVerticalLeftLn => {
435                    self.border_segments.top_vertical_left_ln.gradient = gradient_data;
436                    self.border_segments
437                        .top_vertical_left_ln
438                        .should_use_gradient = true;
439                }
440                GradientSegments::TopVerticalRightLn => {
441                    self.border_segments.top_vertical_right_ln.gradient = gradient_data;
442                    self.border_segments
443                        .top_vertical_right_ln
444                        .should_use_gradient = true;
445                }
446                GradientSegments::BottomVerticalLeftLn => {
447                    self.border_segments.bottom_vertical_left_ln.gradient = gradient_data;
448                    self.border_segments
449                        .bottom_vertical_left_ln
450                        .should_use_gradient = true;
451                }
452                GradientSegments::BottomVerticalRightLn => {
453                    self.border_segments.bottom_vertical_right_ln.gradient = gradient_data;
454                    self.border_segments
455                        .bottom_vertical_right_ln
456                        .should_use_gradient = true;
457                }
458            }
459        }
460        self
461    }
462
463    /// Sets the border style for the block.
464    ///
465    /// If this function is not called, the border will be plain by default.
466    ///
467    /// # Parameters
468    /// - `style`: A `BorderStyle` enum value that determines the appearance of the border.
469    ///   - `BorderStyle::Plain`: A simple, unstyled border.
470    ///   - `BorderStyle::Double`: A double-lined border.
471    ///   - `BorderStyle::Thick`: A thick-stroked border.
472    ///   - `BorderStyle::Rounded`: A border with rounded corners.
473    ///   - `BorderStyle::MiscBorder(MiscBorderTypes)`: A selection of miscellaneous predefined border styles.
474    ///   - `BorderStyle::CustomBorderType`: Allows custom border symbols to be set manually.
475    ///
476    /// # Example 1: Using a standard border style
477    /// ```
478    /// let border = TuiGradientblock::new().border_style(BorderStyle::Double);
479    /// ```
480    ///
481    /// # Example 2: Using a miscellaneous border style
482    /// ```
483    /// let border = TuiGradientblock::new().border_style(BorderStyle::MiscBorder(MiscBorderTypes::Misc2));
484    /// ```
485    ///
486    /// # Example 3: Using a custom border type
487    /// ```
488    /// let border = TuiGradientblock::new()
489    ///     .border_style(BorderStyle::CustomBorderType)
490    ///     .top_left('╔')
491    ///     .top_right('╗')
492    ///     .bottom_left('╚')
493    ///     .bottom_right('╝');
494    /// ```
495    /// Sets the border style of the block.
496    ///
497    /// This function allows setting a predefined border style or a custom one.
498    ///
499    /// # Parameters
500    /// - `style`: A `BorderStyle` enum variant specifying the desired border style.
501    ///
502    /// # Behavior
503    /// - `BorderStyle::CustomBorderType`: Does not set predefined symbols, allowing manual customization.
504    /// - `BorderStyle::MiscBorder(MiscBorderTypes)`: Uses a predefined miscellaneous border style.
505    /// - `BorderStyle::Plain`, `BorderStyle::Double`, `BorderStyle::Thick`, `BorderStyle::Rounded`:
506    ///   Sets the block's borders to one of these predefined styles.
507    ///
508    /// # Example
509    /// ```
510    /// let block = TuiGradientblock::new().border_style(BorderStyle::Double);
511    /// ```
512    pub fn border_style(mut self, style: BorderStyle) -> Self {
513        match &style {
514            BorderStyle::CustomBorderType => {
515                // Does not set predefined symbols, allowing manual customization.
516            }
517            BorderStyle::MiscBorder(t) => {
518                let miscborder = match t {
519                    MiscBorderTypes::Misc1 => MISC1,
520                    MiscBorderTypes::Misc2 => MISC2,
521                    MiscBorderTypes::Misc3 => MISC3,
522                    MiscBorderTypes::Misc4 => MISC4,
523                };
524                self.border_symbols.top_left = Some(miscborder.top_left);
525                self.border_symbols.bottom_left = Some(miscborder.bottom_left);
526                self.border_symbols.top_right = Some(miscborder.top_right);
527                self.border_symbols.bottom_right = Some(miscborder.bottom_right);
528                self.border_symbols.top_horizontal = Some(miscborder.top);
529                self.border_symbols.bottom_horizontal = Some(miscborder.bottom);
530                self.border_symbols.left_vertical = Some(miscborder.left);
531                self.border_symbols.right_vertical = Some(miscborder.right);
532                self.border_symbols.bottom_center = Some(miscborder.bottom_center);
533                self.border_symbols.top_center = Some(miscborder.top_center);
534                self.border_symbols.right_center = Some(miscborder.right_center);
535                self.border_symbols.left_center = Some(miscborder.left_center);
536            }
537            regborder => {
538                let reg = match regborder {
539                    BorderStyle::Plain => PLAIN,
540                    BorderStyle::Double => DOUBLE,
541                    BorderStyle::Thick => THICK,
542                    BorderStyle::Rounded => ROUNDED,
543                    _ => PLAIN, // Fallback to plain border.
544                };
545                self.border_symbols.top_left = Some(reg.top_left.parse().unwrap());
546                self.border_symbols.bottom_left = Some(reg.bottom_left.parse().unwrap());
547                self.border_symbols.top_right = Some(reg.top_right.parse().unwrap());
548                self.border_symbols.bottom_right = Some(reg.bottom_right.parse().unwrap());
549                self.border_symbols.top_horizontal = Some(reg.horizontal_top.parse().unwrap());
550                self.border_symbols.bottom_horizontal =
551                    Some(reg.horizontal_bottom.parse().unwrap());
552                self.border_symbols.left_vertical = Some(reg.vertical_left.parse().unwrap());
553                self.border_symbols.right_vertical = Some(reg.vertical_right.parse().unwrap());
554                self.border_symbols.bottom_center = Some(reg.horizontal_bottom.parse().unwrap());
555                self.border_symbols.top_center = Some(reg.horizontal_top.parse().unwrap());
556                self.border_symbols.right_center = Some(reg.vertical_right.parse().unwrap());
557                self.border_symbols.left_center = Some(reg.vertical_left.parse().unwrap());
558            }
559        };
560        self.bordertype = style;
561        self
562    }
563
564    /// Sets the titles that appear at the bottom of the border.
565    ///
566    /// # Parameters
567    /// - `titles`: A vector of tuples where each tuple contains:
568    ///   - A `String` representing the title text.
569    ///   - A `TitleAlignment` indicating how the title should be aligned (e.g., left, center, right).
570    ///   - An optional tuple containing a vector of RGB colors and a gradient factor (f32).
571    ///
572    /// # Example
573    /// ```
574    /// let border = Border::new().bottom_titles(vec![
575    ///     ("Footer", TitleAlignment::Center, Some((vec![(255, 0, 0), (190, 3, 252)], 0.5))),
576    /// ]);
577    /// ```
578    pub fn bottom_titles(
579        mut self,
580        titles: Vec<(String, TitleAlignment, Option<(Vec<(u8, u8, u8)>, f32)>)>,
581    ) -> Self {
582        for (title, align, colors) in titles {
583            self.bottom_titles.push((title, align, colors));
584        }
585        self
586    }
587
588    /// Sets the titles that appear at the top of the border.
589    ///
590    /// # Parameters
591    /// - `titles`: A vector of tuples where each tuple contains:
592    ///   - A `String` representing the title text.
593    ///   - A `TitleAlignment` indicating how the title should be aligned (e.g., left, center, right).
594    ///   - An optional tuple containing a vector of RGB colors and a gradient factor (f32).
595    ///
596    /// # Example 1: Without Gradient
597    /// ```
598    /// let border = TuiGradientblock::new().top_titles(vec![
599    ///     ("Header", TitleAlignment::Left, None),
600    /// ]);
601    /// ```
602    ///
603    /// # Example 2: With Gradient
604    /// In this example, we use two different colors for the gradient (Red to Blue).
605    /// ```
606    /// let border = TuiGradientblock::new().top_titles(vec![
607    ///     ("Header", TitleAlignment::Center, Some((vec![(255, 0, 0), (0, 0, 255)], 0.5))),
608    /// ]);
609    /// ```
610    pub fn top_titles(
611        mut self,
612        titles: Vec<(String, TitleAlignment, Option<(Vec<(u8, u8, u8)>, f32)>)>,
613    ) -> Self {
614        for (title, align, colors) in titles {
615            self.top_titles.push((title, align, colors));
616        }
617        self
618    }
619
620    /// Sets the symbol for the top-right corner of the border.
621    ///
622    /// # Parameters
623    /// - `symb`: A `char` representing the symbol to be used in the top-right corner.
624    ///
625    /// # Example
626    /// ```
627    /// let border = TuiGradientblock::new().top_right('#');
628    /// ```
629    pub fn top_right(mut self, symb: char) -> Self {
630        self.border_symbols.top_right = Some(symb);
631        self
632    }
633
634    /// Sets the symbol for the top-left corner of the border.
635    ///
636    /// # Parameters
637    /// - `symb`: A `char` representing the symbol to be used in the top-left corner.
638    ///
639    /// # Example
640    /// ```
641    /// let border = TuiGradientblock::new().top_left('*');
642    /// ```
643    pub fn top_left(mut self, symb: char) -> Self {
644        self.border_symbols.top_left = Some(symb);
645        self
646    }
647
648    /// Sets the symbol for the bottom-right corner of the border.
649    ///
650    /// # Parameters
651    /// - `symb`: A `char` representing the symbol to be used in the bottom-right corner.
652    ///
653    /// # Example
654    /// ```
655    /// let border = TuiGradientblock::new().bottom_right('%');
656    /// ```
657    pub fn bottom_right(mut self, symb: char) -> Self {
658        self.border_symbols.bottom_right = Some(symb);
659        self
660    }
661
662    /// Sets the symbol for the bottom-left corner of the border.
663    ///
664    /// # Parameters
665    /// - `symb`: A `char` representing the symbol to be used in the bottom-left corner.
666    ///
667    /// # Example
668    /// ```
669    /// let border = TuiGradientblock::new().bottom_left('@');
670    /// ```
671    pub fn bottom_left(mut self, symb: char) -> Self {
672        self.border_symbols.bottom_left = Some(symb);
673        self
674    }
675
676    /// Sets the symbol for the bottom horizontal segment.
677    ///
678    /// # Parameters
679    /// - `symb`: A `char` representing the symbol to be used for the bottom horizontal border.
680    ///
681    /// # Example
682    /// ```
683    /// let border = TuiGradientblockr::new().bottom_horizontal_symbol('-');
684    /// ```
685    pub fn bottom_horizontal_symbol(mut self, symb: char) -> Self {
686        self.border_symbols.bottom_horizontal = Some(symb);
687        self
688    }
689
690    /// Sets the symbol for the top horizontal border segment.
691    ///
692    /// # Parameters
693    /// - `symb`: A `char` representing the symbol to be used for the top horizontal border.
694    ///
695    /// # Example
696    /// ```
697    /// let border = Border::new().top_horizontal_symbol('=');
698    /// ```
699    pub fn top_horizontal_symbol(mut self, symb: char) -> Self {
700        self.border_symbols.top_horizontal = Some(symb);
701        self
702    }
703
704    /// Sets the symbol for the right vertical border segment.
705    ///
706    /// # Parameters
707    /// - `symb`: A `char` representing the symbol to be used for the right vertical border.
708    ///
709    /// # Example
710    /// ```
711    /// let border = TuiGradientblock::new().right_vertical_symbol('|');
712    /// ```
713    pub fn right_vertical_symbol(mut self, symb: char) -> Self {
714        self.border_symbols.right_vertical = Some(symb);
715        self
716    }
717    /// Sets the left vertical border symbol.
718    ///
719    /// # Example
720    /// ```
721    /// let widget = TuiGradientblock::new().left_vertical_symbol('|');
722    /// ```
723    pub fn left_vertical_symbol(mut self, symb: char) -> Self {
724        self.border_symbols.left_vertical = Some(symb);
725        self
726    }
727
728    /// Sets the top center border symbol.
729    ///
730    /// # Example
731    /// ```
732    /// let widget = TuiGradientblock::new().top_center_symbol('─');
733    /// ```
734    pub fn top_center_symbol(mut self, symb: char) -> Self {
735        self.border_symbols.top_center = Some(symb);
736        self
737    }
738
739    /// Sets the bottom center border symbol.
740    ///
741    /// # Example
742    /// ```
743    /// let widget = TuiGradientblock::new().bottom_center_symbol('═');
744    /// ```
745    pub fn bottom_center_symbol(mut self, symb: char) -> Self {
746        self.border_symbols.bottom_center = Some(symb);
747        self
748    }
749
750    /// Sets the left center vertical border symbol.
751    ///
752    /// # Example
753    /// ```
754    /// let widget = TuiGradientblock::new().left_center_symbol('+');
755    /// ```
756    pub fn left_center_symbol(mut self, symb: char) -> Self {
757        self.border_symbols.left_center = Some(symb);
758        self
759    }
760
761    /// Sets the right center vertical border symbol.
762    ///
763    /// # Example
764    /// ```
765    /// let widget = TuiGradientblock::new().right_center_symbol('+');
766    /// ```
767    pub fn right_center_symbol(mut self, symb: char) -> Self {
768        self.border_symbols.right_center = Some(symb);
769        self
770    }
771
772    /// Sets the top right horizontal border symbol.
773    ///
774    /// # Example
775    /// ```
776    /// let widget = TuiGradientblock::new().top_horizontal_right_symbol('┐');
777    /// ```
778    pub fn top_horizontal_right_symbol(mut self, symb: char) -> Self {
779        self.border_symbols.top_horizontal_right = Some(symb);
780        self
781    }
782    /// Sets the symbol used for the repeated section of the bottom horizontal border (right side).
783    ///
784    /// # Example
785    /// ```
786    /// let block = TuiGradientblock::new().bottom_horizontal_right_symbol('*');
787    /// ```
788    pub fn bottom_horizontal_right_symbol(mut self, symb: char) -> Self {
789        self.border_symbols.bottom_horizontal_right = Some(symb);
790        self
791    }
792
793    /// Sets the symbol for the top horizontal left connector.
794    ///
795    /// # Example
796    /// ```
797    /// let block = TuiGradientblock::new().top_horizontal_left_symbol('=');
798    /// ```
799    pub fn top_horizontal_left_symbol(mut self, symb: char) -> Self {
800        self.border_symbols.top_horizontal_left = Some(symb);
801        self
802    }
803
804    /// Sets the symbol for the bottom horizontal left connector.
805    ///
806    /// # Example
807    /// ```
808    /// let block = TuiGradientblock::new().bottom_horizontal_left_symbol('=');
809    /// ```
810    pub fn bottom_horizontal_left_symbol(mut self, symb: char) -> Self {
811        self.border_symbols.bottom_horizontal_left = Some(symb);
812        self
813    }
814
815    /// Sets the symbol for the top vertical right connector.
816    ///
817    /// # Example
818    /// ```
819    /// let block = TuiGradientblock::new().top_vertical_right_symbol('|');
820    /// ```
821    pub fn top_vertical_right_symbol(mut self, symb: char) -> Self {
822        self.border_symbols.top_vertical_right = Some(symb);
823        self
824    }
825
826    /// Sets the symbol for the bottom vertical right connector.
827    ///
828    /// # Example
829    /// ```
830    /// let block = TuiGradientblock::new().bottom_vertical_right_symbol('|');
831    /// ```
832    pub fn bottom_vertical_right_symbol(mut self, symb: char) -> Self {
833        self.border_symbols.bottom_vertical_right = Some(symb);
834        self
835    }
836
837    /// Sets the symbol for the top vertical left connector.
838    ///
839    /// # Example
840    /// ```
841    /// let block = TuiGradientblock::new().top_vertical_left_symbol('|');
842    /// ```
843    pub fn top_vertical_left_symbol(mut self, symb: char) -> Self {
844        self.border_symbols.top_vertical_left = Some(symb);
845        self
846    }
847
848    /// Sets the symbol for the bottom vertical left connector.
849    ///
850    /// # Example
851    /// ```
852    /// let block = TuiGradientblock::new().bottom_vertical_left_symbol('|');
853    /// ```
854    pub fn bottom_vertical_left_symbol(mut self, symb: char) -> Self {
855        self.border_symbols.bottom_vertical_left = Some(symb);
856        self
857    }
858
859    /// Sets the fill string for the block.
860    ///
861    /// This string is used to fill the inner area of the block.
862    ///
863    /// # Example
864    /// ```
865    /// let block = TuiGradientblock::new().fill_string(String::from("Hello"));
866    /// ```
867    pub fn fill_string(mut self, string: String) -> Self {
868        self.fill.fill_string = Some(string);
869        self
870    }
871
872    /// Sets the fill gradient for the block.
873    ///
874    /// The gradient is defined as a list of RGB colors and a factor to control the blending effect.
875    ///
876    /// # Example
877    /// ```
878    /// let colors = vec![(255, 0, 0), (0, 255, 0), (0, 0, 255)];
879    /// let block = TuiGradientblock::new().fill_gradient(colors, 0.5);
880    /// ```
881    pub fn fill_gradient(mut self, colors: Vec<(u8, u8, u8)>, factor: f32) -> Self {
882        self.fill.gradient = Some((colors, factor));
883        self
884    }
885
886    /// Sets the border line segments based on the area and border symbols.
887    ///
888    /// This method configures the border segments (top, bottom, left, right) and any possible splits
889    /// within the block. It calculates and sets the text for each border line segment using the provided
890    /// border symbols and the block's area. The function supports setting up horizontal and vertical
891    /// lines, as well as handling special cases where the border is split into smaller sections.
892    ///
893    /// **Important:**
894    /// - This function should be called **last** after all other block properties are set, as it depends
895    ///   on the final values of the area and border symbols.
896    ///
897    /// # Behavior
898    /// - The function calculates the appropriate border segments, including top, bottom, left, and right borders.
899    /// - It uses the provided `border_symbols` to determine the characters used for the borders.
900    /// - If the `split_segments` attribute contains any of `TOP`, `BOTTOM`, `LEFT`, or `RIGHT`, the respective
901    ///   segments are split into smaller parts, and the relevant segments are marked for rendering.
902    /// - In the case of the `ALL` split, all border lines are broken into smaller segments and set to be rendered.
903    /// - If no split is needed (`NONE`), the function disables the rendering of split border lines.
904    ///
905    /// # Parameters
906    /// - This method takes no parameters and modifies the internal state of the struct it's called on.
907    ///
908    /// # Returns
909    /// - A modified instance of the struct (self), with the border segments set according to the configurations.
910    pub fn set_lines(mut self) -> Self {
911        let border_symbols = &self.border_symbols;
912        let area = &self.area;
913        let top_horizontal = border_symbols
914            .top_horizontal
915            .unwrap_or(PLAIN.horizontal_top.parse().unwrap());
916        let left_vertical = border_symbols
917            .left_vertical
918            .unwrap_or(PLAIN.vertical_left.parse().unwrap());
919        let bottom_horizontal = border_symbols
920            .bottom_horizontal
921            .unwrap_or(PLAIN.horizontal_top.parse().unwrap());
922        let right_vertical = border_symbols
923            .right_vertical
924            .unwrap_or(PLAIN.vertical_right.parse().unwrap());
925        let top_center_char = border_symbols.top_center.unwrap_or(top_horizontal);
926        let bottom_center_char = border_symbols.bottom_center.unwrap_or(bottom_horizontal);
927        let left_center_char = border_symbols.left_center.unwrap_or(left_vertical);
928        let right_center_char = border_symbols.right_center.unwrap_or(right_vertical);
929        let top_right = border_symbols
930            .top_right
931            .unwrap_or(PLAIN.top_right.parse().unwrap());
932        let top_left: char = border_symbols
933            .top_left
934            .unwrap_or(PLAIN.top_left.parse().unwrap());
935        let bottom_right = border_symbols
936            .bottom_right
937            .unwrap_or(PLAIN.bottom_right.parse().unwrap());
938        let bottom_left = border_symbols
939            .bottom_left
940            .unwrap_or(PLAIN.bottom_left.parse().unwrap());
941        let top_horizontal_right = border_symbols
942            .top_horizontal_right
943            .unwrap_or(top_horizontal);
944        let bottom_horizontal_right = border_symbols
945            .bottom_horizontal_right
946            .unwrap_or(bottom_horizontal);
947        let top_horizontal_left = border_symbols.top_horizontal_left.unwrap_or(top_horizontal);
948        let bottom_horizontal_left = border_symbols
949            .bottom_horizontal_left
950            .unwrap_or(bottom_horizontal);
951        let top_vertical_right = border_symbols.top_vertical_right.unwrap_or(right_vertical);
952        let bottom_vertical_right = border_symbols
953            .bottom_vertical_right
954            .unwrap_or(right_vertical);
955        let top_vertical_left = border_symbols.top_vertical_left.unwrap_or(left_vertical);
956        let bottom_vertical_left = border_symbols.bottom_vertical_left.unwrap_or(left_vertical);
957        let top_horizontal_right_ln = format!(
958            "{}{}{}",
959            top_center_char,
960            top_horizontal_right
961                .to_string()
962                .repeat((area.width as usize - 1) / 2 - 1),
963            top_right,
964        );
965        let top_horizontal_left_ln = format!(
966            "{}{}{}",
967            top_left,
968            top_horizontal_left
969                .to_string()
970                .repeat((area.width as usize - 1) / 2 - 1),
971            top_center_char
972        );
973        let bottom_horizontal_left_ln = format!(
974            "{}{}{}",
975            bottom_left,
976            bottom_horizontal_left
977                .to_string()
978                .repeat((area.width as usize - 1) / 2 - 1),
979            bottom_center_char,
980        );
981        let bottom_horizontal_right_ln = format!(
982            "{}{}{}",
983            bottom_center_char,
984            bottom_horizontal_right
985                .to_string()
986                .repeat((area.width as usize - 1) / 2 - 1),
987            bottom_right,
988        );
989        let top_vertical_right_ln = format!(
990            "{}{}{}",
991            top_right,
992            top_vertical_right
993                .to_string()
994                .repeat(((area.height as usize + 1) / 2).saturating_sub(2)),
995            right_center_char
996        );
997        let top_vertical_left_ln = format!(
998            "{}{}{}",
999            top_left,
1000            top_vertical_left
1001                .to_string()
1002                .repeat(((area.height as usize + 1) / 2).saturating_sub(2)),
1003            left_center_char,
1004        );
1005        let bottom_vertical_left_ln = format!(
1006            "{}{}{}",
1007            left_center_char,
1008            bottom_vertical_left
1009                .to_string()
1010                .repeat((area.height as usize / 2).saturating_sub(1)),
1011            bottom_left,
1012        );
1013        let bottom_vertical_right_ln = format!(
1014            "{}{}{}",
1015            right_center_char,
1016            bottom_vertical_right
1017                .to_string()
1018                .repeat((area.height as usize / 2).saturating_sub(1)),
1019            bottom_right,
1020        );
1021        let top_ln = format!(
1022            "{}{}{}{}{}",
1023            top_left,
1024            top_horizontal_left
1025                .to_string()
1026                .repeat(((area.width as usize + 1) / 2).saturating_sub(2)),
1027            top_center_char,
1028            top_horizontal_right
1029                .to_string()
1030                .repeat((area.width as usize / 2).saturating_sub(1)),
1031            top_right,
1032        );
1033        let bottom_ln = format!(
1034            "{}{}{}{}{}",
1035            bottom_left,
1036            bottom_horizontal_left
1037                .to_string()
1038                .repeat(((area.width as usize + 1) / 2).saturating_sub(1)),
1039            bottom_center_char,
1040            bottom_horizontal_right
1041                .to_string()
1042                .repeat((area.width as usize / 2).saturating_sub(1)),
1043            bottom_right,
1044        );
1045        let right_ln = format!(
1046            "{}{}{}{}{}",
1047            top_right,
1048            top_vertical_right
1049                .to_string()
1050                .repeat(((area.height as usize + 1) / 2).saturating_sub(2)),
1051            right_center_char,
1052            bottom_vertical_right
1053                .to_string()
1054                .repeat((area.height as usize / 2).saturating_sub(1)),
1055            bottom_right,
1056        );
1057        let left_ln = format!(
1058            "{}{}{}{}{}",
1059            top_left,
1060            top_vertical_left
1061                .to_string()
1062                .repeat(((area.height as usize + 1) / 2).saturating_sub(2)),
1063            left_center_char,
1064            bottom_vertical_left
1065                .to_string()
1066                .repeat((area.height as usize / 2).saturating_sub(1)),
1067            bottom_left
1068        );
1069        self.border_segments.top_ln.should_be_rendered = true;
1070        self.border_segments.top_ln.segment_text = top_ln;
1071        self.border_segments.bottom_ln.should_be_rendered = true;
1072        self.border_segments.bottom_ln.segment_text = bottom_ln;
1073        self.border_segments.left_ln.should_be_rendered = true;
1074        self.border_segments.left_ln.segment_text = left_ln;
1075        self.border_segments.right_ln.should_be_rendered = true;
1076        self.border_segments.right_ln.segment_text = right_ln;
1077        if self.split_segments.contains(SplitBorderSegments::TOP) {
1078            self.border_segments.top_ln.should_be_rendered = false;
1079            self.border_segments
1080                .top_horizontal_left_ln
1081                .should_be_rendered = true;
1082            self.border_segments.top_horizontal_left_ln.segment_text = top_horizontal_left_ln;
1083            self.border_segments
1084                .top_horizontal_right_ln
1085                .should_be_rendered = true;
1086            self.border_segments.top_horizontal_right_ln.segment_text = top_horizontal_right_ln;
1087        }
1088
1089        if self.split_segments.contains(SplitBorderSegments::BOTTOM) {
1090            self.border_segments.bottom_ln.should_be_rendered = false;
1091            self.border_segments.bottom_horizontal_left_ln.segment_text = bottom_horizontal_left_ln;
1092            self.border_segments
1093                .bottom_horizontal_left_ln
1094                .should_be_rendered = true;
1095
1096            self.border_segments.bottom_horizontal_right_ln.segment_text =
1097                bottom_horizontal_right_ln;
1098            self.border_segments
1099                .bottom_horizontal_right_ln
1100                .should_be_rendered = true;
1101        }
1102        if self.split_segments.contains(SplitBorderSegments::LEFT) {
1103            self.border_segments.left_ln.should_be_rendered = false;
1104            self.border_segments.top_vertical_left_ln.should_be_rendered = true;
1105            self.border_segments.top_vertical_left_ln.segment_text = top_vertical_left_ln;
1106            self.border_segments
1107                .bottom_vertical_left_ln
1108                .should_be_rendered = true;
1109            self.border_segments.bottom_vertical_left_ln.segment_text = bottom_vertical_left_ln;
1110        }
1111        if self.split_segments.contains(SplitBorderSegments::RIGHT) {
1112            self.border_segments.right_ln.should_be_rendered = false;
1113            self.border_segments
1114                .top_vertical_right_ln
1115                .should_be_rendered = true;
1116            self.border_segments.top_vertical_right_ln.segment_text = top_vertical_right_ln;
1117            self.border_segments
1118                .bottom_vertical_right_ln
1119                .should_be_rendered = true;
1120            self.border_segments.bottom_vertical_right_ln.segment_text = bottom_vertical_right_ln;
1121        }
1122        if self.split_segments == SplitBorderSegments::ALL {
1123            self.border_segments.top_ln.should_be_rendered = false;
1124            self.border_segments.bottom_ln.should_be_rendered = false;
1125            self.border_segments.left_ln.should_be_rendered = false;
1126            self.border_segments.right_ln.should_be_rendered = false;
1127            self.border_segments
1128                .top_horizontal_left_ln
1129                .should_be_rendered = true;
1130            self.border_segments
1131                .top_horizontal_right_ln
1132                .should_be_rendered = true;
1133            self.border_segments
1134                .bottom_horizontal_left_ln
1135                .should_be_rendered = true;
1136            self.border_segments
1137                .bottom_horizontal_right_ln
1138                .should_be_rendered = true;
1139            self.border_segments.top_vertical_left_ln.should_be_rendered = true;
1140            self.border_segments
1141                .top_vertical_right_ln
1142                .should_be_rendered = true;
1143            self.border_segments
1144                .bottom_vertical_left_ln
1145                .should_be_rendered = true;
1146            self.border_segments
1147                .bottom_vertical_right_ln
1148                .should_be_rendered = true;
1149        }
1150
1151        if self.split_segments == SplitBorderSegments::NONE {
1152            self.border_segments
1153                .top_horizontal_left_ln
1154                .should_be_rendered = false;
1155            self.border_segments
1156                .top_horizontal_right_ln
1157                .should_be_rendered = false;
1158            self.border_segments
1159                .bottom_horizontal_left_ln
1160                .should_be_rendered = false;
1161            self.border_segments
1162                .bottom_horizontal_right_ln
1163                .should_be_rendered = false;
1164        }
1165        self
1166    }
1167    /// Renders the border segments of the block.
1168    ///
1169    /// This private function iterates through all defined border segments and renders only those
1170    /// that are marked to be rendered (`should_be_rendered == true`).
1171    ///
1172    /// It uses a list of tuples where each tuple contains a border segment and its corresponding
1173    /// render function. If a segment is marked as `should_be_rendered`, the associated render function
1174    /// is invoked to render that segment.
1175    ///
1176    /// # Parameters
1177    /// - `buf`: A mutable reference to the [`Buffer`] where the border segments will be drawn.
1178    ///
1179    /// # Behavior
1180    /// - The function checks each border segment and invokes the corresponding render function if the
1181    ///   segment is set to be rendered.
1182    ///
1183    /// # Note
1184    /// This function is called internally by the program when rendering the custom block, and isn't meant
1185    /// to be directly called by users.
1186    fn render_block(&self, buf: &mut Buffer) {
1187        let segments: &[(&BorderSegment, fn(&Self, &mut Buffer))] = &[
1188            (&self.border_segments.top_ln, Self::render_top_ln),
1189            (&self.border_segments.bottom_ln, Self::render_bottom_ln),
1190            (&self.border_segments.left_ln, Self::render_left_ln),
1191            (&self.border_segments.right_ln, Self::render_right_ln),
1192            (
1193                &self.border_segments.top_horizontal_left_ln,
1194                Self::render_top_horizontal_left_ln,
1195            ),
1196            (
1197                &self.border_segments.top_horizontal_right_ln,
1198                Self::render_top_horizontal_right_ln,
1199            ),
1200            (
1201                &self.border_segments.bottom_vertical_left_ln,
1202                Self::render_bottom_vertical_left_ln,
1203            ),
1204            (
1205                &self.border_segments.bottom_vertical_right_ln,
1206                Self::render_bottom_vertical_right_ln,
1207            ),
1208            (
1209                &self.border_segments.bottom_horizontal_left_ln,
1210                Self::render_bottom_horizontal_left_ln,
1211            ),
1212            (
1213                &self.border_segments.bottom_horizontal_right_ln,
1214                Self::render_bottom_horizontal_right_ln,
1215            ),
1216            (
1217                &self.border_segments.top_vertical_left_ln,
1218                Self::render_top_vertical_left_ln,
1219            ),
1220            (
1221                &self.border_segments.top_vertical_right_ln,
1222                Self::render_top_vertical_right_ln,
1223            ),
1224        ];
1225
1226        for (segment, render_fn) in segments {
1227            if segment.should_be_rendered {
1228                render_fn(self, buf);
1229            }
1230        }
1231    }
1232
1233    /// Renders the top horizontal line of the border with an optional gradient.
1234    ///
1235    /// This function renders the top border line. If the `top_ln` segment should use a gradient,
1236    /// it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1237    ///
1238    /// # Parameters:
1239    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1240    ///
1241    /// ## Visual Representation:
1242    /// Without the function:
1243    /// ```
1244    /// +-----+
1245    /// |     |
1246    /// |     |
1247    /// +     +
1248    /// |     |
1249    /// |     |
1250    /// +-----+
1251    /// ```
1252    fn render_top_ln(&self, buf: &mut Buffer) {
1253        let top_ln = self.border_segments.top_ln.clone();
1254        let used_top_ln = match top_ln.should_use_gradient {
1255            true => &Line::from(Self::create_gradient_text(
1256                &top_ln.segment_text,
1257                top_ln.gradient.clone().unwrap().0,
1258                top_ln.gradient.unwrap().1,
1259            )),
1260            false => &Line::from(top_ln.segment_text),
1261        };
1262        buf.set_line(top_ln.x, top_ln.y, used_top_ln, self.area.width);
1263    }
1264
1265    /// Renders the left vertical line of the border with an optional gradient.
1266    ///
1267    /// This function renders the left border line. If the `left_ln` segment should use a gradient,
1268    /// it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1269    ///
1270    /// # Parameters:
1271    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1272    ///
1273    /// ## Visual Representation:
1274    /// Without the function:
1275    /// ```
1276    /// +-----+
1277    /// |     |
1278    /// |     |
1279    /// +     +
1280    /// |     |
1281    /// |     |
1282    /// +-----+
1283    /// ```
1284    fn render_left_ln(&self, buf: &mut Buffer) {
1285        let left_ln = self.border_segments.left_ln.clone();
1286        let used_left_ln: &Vec<Span> = match left_ln.should_use_gradient {
1287            true => &Self::create_gradient_text(
1288                &left_ln.segment_text,
1289                left_ln.gradient.clone().unwrap().0,
1290                left_ln.gradient.unwrap().1,
1291            ),
1292            false => &left_ln
1293                .segment_text
1294                .chars()
1295                .map(|i| Span::raw(i.to_string()))
1296                .collect(),
1297        };
1298        for (i, ln) in used_left_ln.iter().enumerate() {
1299            buf.set_span(left_ln.x, left_ln.y + i as u16, ln, 1);
1300        }
1301    }
1302
1303    /// Renders the bottom horizontal line of the border with an optional gradient.
1304    ///
1305    /// This function renders the bottom border line. If the `bottom_ln` segment should use a gradient,
1306    /// it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1307    ///
1308    /// # Parameters:
1309    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1310    ///
1311    /// ## Visual Representation:
1312    /// Without the function:
1313    /// ```
1314    /// +-----+
1315    /// |     |
1316    /// |     |
1317    /// +     +
1318    /// |     |
1319    /// |     |
1320    /// +-----+
1321    /// ```
1322    fn render_bottom_ln(&self, buf: &mut Buffer) {
1323        let bottom_ln = self.border_segments.bottom_ln.clone();
1324        let used_bottom_ln = match bottom_ln.should_use_gradient {
1325            true => &Line::from(Self::create_gradient_text(
1326                &bottom_ln.segment_text,
1327                bottom_ln.gradient.clone().unwrap().0,
1328                bottom_ln.gradient.unwrap().1,
1329            )),
1330            false => &Line::from(bottom_ln.segment_text),
1331        };
1332        buf.set_line(bottom_ln.x, bottom_ln.y, used_bottom_ln, self.area.width);
1333    }
1334
1335    /// Renders the right vertical line of the border with an optional gradient.
1336    ///
1337    /// This function renders the right border line. If the `right_ln` segment should use a gradient,
1338    /// it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1339    ///
1340    /// # Parameters:
1341    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1342    ///
1343    /// ## Visual Representation:
1344    /// Without the function:
1345    /// ```
1346    /// +-----+
1347    /// |     |
1348    /// |     |
1349    /// +     +
1350    /// |     |
1351    /// |     |
1352    /// +-----+
1353    /// ```
1354    fn render_right_ln(&self, buf: &mut Buffer) {
1355        let mut right_ln = self.border_segments.right_ln.clone();
1356
1357        let used_right_ln: Vec<Span> = if right_ln.should_use_gradient {
1358            Self::create_gradient_text(
1359                &right_ln.clone().segment_text,
1360                right_ln.gradient.clone().unwrap().0,
1361                right_ln.gradient.as_mut().unwrap().1,
1362            )
1363        } else {
1364            right_ln
1365                .clone()
1366                .segment_text
1367                .chars()
1368                .map(|i| Span::raw(i.to_string()))
1369                .collect()
1370        };
1371        for (i, span) in used_right_ln.iter().enumerate() {
1372            buf.set_span(right_ln.x, right_ln.y + i as u16, span, 1);
1373        }
1374    }
1375
1376    /// Renders the left side of the top horizontal line of the border with an optional gradient.
1377    ///
1378    /// This function renders the left part of the top horizontal line. If the `top_horizontal_left_ln` segment
1379    /// should use a gradient, it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1380    ///
1381    /// # Parameters:
1382    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1383    ///
1384    /// ## Visual Representation:
1385    /// Without the function:
1386    /// ```
1387    /// ****~~~
1388    /// ~     ~
1389    /// ~     ~
1390    /// ~     ~
1391    /// ~     ~
1392    /// ~     ~
1393    /// ~~~~~~~
1394    /// ```
1395    fn render_top_horizontal_left_ln(&self, buf: &mut Buffer) {
1396        let top_horizontal_left_ln = self.border_segments.top_horizontal_left_ln.clone();
1397        let used_top_horizontal_left_ln = match top_horizontal_left_ln.should_use_gradient {
1398            true => &Line::from(Self::create_gradient_text(
1399                &top_horizontal_left_ln.segment_text,
1400                top_horizontal_left_ln.gradient.clone().unwrap().0,
1401                top_horizontal_left_ln.gradient.unwrap().1,
1402            )),
1403            false => &Line::from(top_horizontal_left_ln.segment_text),
1404        };
1405        buf.set_line(
1406            top_horizontal_left_ln.x,
1407            top_horizontal_left_ln.y,
1408            used_top_horizontal_left_ln,
1409            self.area.width,
1410        );
1411    }
1412
1413    /// Renders the right side of the top horizontal line of the border with an optional gradient.
1414    ///
1415    /// This function renders the right part of the top horizontal line. If the `top_horizontal_right_ln` segment
1416    /// should use a gradient, it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1417    ///
1418    /// # Parameters:
1419    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1420    ///
1421    /// ## Visual Representation:
1422    /// Without the function:
1423    /// ```
1424    /// +---  +
1425    /// |     |
1426    /// |     |
1427    /// +     +
1428    /// |     |
1429    /// |     |
1430    /// +-----+
1431    /// ```
1432    fn render_top_horizontal_right_ln(&self, buf: &mut Buffer) {
1433        let top_horizontal_right_ln = self.border_segments.top_horizontal_right_ln.clone();
1434        let used_top_horizontal_right_ln = match top_horizontal_right_ln.should_use_gradient {
1435            true => &Line::from(Self::create_gradient_text(
1436                &top_horizontal_right_ln.segment_text,
1437                top_horizontal_right_ln.gradient.clone().unwrap().0,
1438                top_horizontal_right_ln.gradient.unwrap().1,
1439            )),
1440            false => &Line::from(top_horizontal_right_ln.segment_text),
1441        };
1442        buf.set_line(
1443            top_horizontal_right_ln.x,
1444            top_horizontal_right_ln.y,
1445            used_top_horizontal_right_ln,
1446            self.area.width,
1447        );
1448    }
1449
1450    /// Renders the left side of the bottom horizontal line of the border with an optional gradient.
1451    ///
1452    /// This function renders the left part of the bottom horizontal line. If the segment should use a gradient,
1453    /// it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1454    ///
1455    /// # Parameters:
1456    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1457    ///
1458    /// ## Visual Representation:
1459    /// Without the function:
1460    /// ```
1461    /// +-----+
1462    /// |     |
1463    /// |     |
1464    /// +     +
1465    /// |     |
1466    /// |     |
1467    /// +  ---+
1468    /// ```
1469    fn render_bottom_horizontal_left_ln(&self, buf: &mut Buffer) {
1470        let bottom_horizontal_left_ln = self.border_segments.bottom_horizontal_left_ln.clone();
1471        let used_bottom_horizontal_left_ln = match bottom_horizontal_left_ln.should_use_gradient {
1472            true => &Line::from(Self::create_gradient_text(
1473                &bottom_horizontal_left_ln.segment_text,
1474                bottom_horizontal_left_ln.gradient.clone().unwrap().0,
1475                bottom_horizontal_left_ln.gradient.unwrap().1,
1476            )),
1477            false => &Line::from(bottom_horizontal_left_ln.segment_text),
1478        };
1479        buf.set_line(
1480            bottom_horizontal_left_ln.x,
1481            bottom_horizontal_left_ln.y,
1482            used_bottom_horizontal_left_ln,
1483            self.area.width,
1484        );
1485    }
1486
1487    /// Renders the right side of the bottom horizontal line of the border with an optional gradient.
1488    ///
1489    /// This function renders the right part of the bottom horizontal line. If the segment should use a gradient,
1490    /// it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1491    ///
1492    /// # Parameters:
1493    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1494    ///
1495    /// ## Visual Representation:
1496    /// Without the function:
1497    /// ```
1498    /// +-----+
1499    /// |     |
1500    /// |     |
1501    /// +     +
1502    /// |     |
1503    /// |     |
1504    /// +---  +
1505    /// ```
1506    fn render_bottom_horizontal_right_ln(&self, buf: &mut Buffer) {
1507        let bottom_horizontal_right_ln = self.border_segments.bottom_horizontal_right_ln.clone();
1508        let used_bottom_horizontal_right_ln = match bottom_horizontal_right_ln.should_use_gradient {
1509            true => &Line::from(Self::create_gradient_text(
1510                &bottom_horizontal_right_ln.segment_text,
1511                bottom_horizontal_right_ln.gradient.clone().unwrap().0,
1512                bottom_horizontal_right_ln.gradient.unwrap().1,
1513            )),
1514            false => &Line::from(bottom_horizontal_right_ln.segment_text),
1515        };
1516        buf.set_line(
1517            bottom_horizontal_right_ln.x,
1518            bottom_horizontal_right_ln.y,
1519            used_bottom_horizontal_right_ln,
1520            self.area.width,
1521        );
1522    }
1523
1524    /// Renders the top side of the left vertical line of the border with an optional gradient.
1525    ///
1526    /// This function renders the left part of the top vertical line. If the segment should use a gradient,
1527    /// it applies the gradient to the segment text. Otherwise, it renders the text as-is.
1528    ///
1529    /// # Parameters:
1530    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1531    ///
1532    /// ## Visual Representation:
1533    /// Without the function:
1534    /// ```
1535    /// +-----+
1536    ///       |
1537    ///       |
1538    /// +     +
1539    /// |     |
1540    /// |     |
1541    /// +-----+
1542    /// ```
1543    fn render_top_vertical_left_ln(&self, buf: &mut Buffer) {
1544        let mut top_vertical_left_ln = self.border_segments.top_vertical_left_ln.clone();
1545
1546        let used_top_vertical_left_ln: Vec<Span> = if top_vertical_left_ln.should_use_gradient {
1547            Self::create_gradient_text(
1548                &top_vertical_left_ln.clone().segment_text,
1549                top_vertical_left_ln.gradient.clone().unwrap().0,
1550                top_vertical_left_ln.gradient.as_mut().unwrap().1,
1551            )
1552        } else {
1553            top_vertical_left_ln
1554                .clone()
1555                .segment_text
1556                .chars()
1557                .map(|i| Span::raw(i.to_string()))
1558                .collect()
1559        };
1560        for (i, span) in used_top_vertical_left_ln.iter().enumerate() {
1561            buf.set_span(
1562                top_vertical_left_ln.x,
1563                top_vertical_left_ln.y + i as u16,
1564                span,
1565                1,
1566            );
1567        }
1568    }
1569
1570    /// Renders the top side of the right vertical line of the border with an optional gradient.
1571    ///
1572    /// # Parameters:
1573    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1574    ///
1575    /// This function renders the top-right vertical line of the border. If the segment associated with
1576    /// this line should use a gradient, it applies the gradient to the segment text using the `create_gradient_text`
1577    /// function. Otherwise, the function renders the segment text as-is.
1578    ///
1579    /// # Example:
1580    /// ```rust
1581    /// let widget = TuiGradientblock::new();
1582    /// let mut buffer = Buffer::new();
1583    /// widget.render_top_vertical_right_ln(&mut buffer);
1584    /// ```
1585    ///
1586    /// ## Visual Representation:
1587    /// Without the function:
1588    /// ```
1589    /// +-----+
1590    /// |     |
1591    /// |     |
1592    /// +     +
1593    /// |     |
1594    /// |     |
1595    /// +-----+
1596    /// ```
1597    fn render_top_vertical_right_ln(&self, buf: &mut Buffer) {
1598        let mut top_vertical_right_ln = self.border_segments.top_vertical_right_ln.clone();
1599
1600        let used_top_vertical_right_ln: Vec<Span> = if top_vertical_right_ln.should_use_gradient {
1601            Self::create_gradient_text(
1602                &top_vertical_right_ln.clone().segment_text,
1603                top_vertical_right_ln.gradient.clone().unwrap().0,
1604                top_vertical_right_ln.gradient.as_mut().unwrap().1,
1605            )
1606        } else {
1607            top_vertical_right_ln
1608                .clone()
1609                .segment_text
1610                .chars()
1611                .map(|i| Span::raw(i.to_string()))
1612                .collect()
1613        };
1614        for (i, span) in used_top_vertical_right_ln.iter().enumerate() {
1615            buf.set_span(
1616                top_vertical_right_ln.x,
1617                top_vertical_right_ln.y + i as u16,
1618                span,
1619                1,
1620            );
1621        }
1622    }
1623
1624    /// Renders the bottom vertical right line of the border with an optional gradient.
1625    ///
1626    /// # Parameters:
1627    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1628    ///
1629    /// This function renders the bottom-right vertical line of the border. If the segment associated with
1630    /// this line should use a gradient, it applies the gradient to the segment text using the `create_gradient_text`
1631    /// function. Otherwise, the function renders the segment text as-is.
1632    ///
1633    /// # Example:
1634    /// ```rust
1635    /// let widget = TuiGradientblock::new();
1636    /// let mut buffer = Buffer::new();
1637    /// widget.render_bottom_vertical_right_ln(&mut buffer);
1638    /// ```
1639    ///
1640    /// ## Visual Representation:
1641    /// Without the function:
1642    /// ```
1643    /// +-----+
1644    /// |     |
1645    /// |     |
1646    /// +     +
1647    /// |
1648    /// |
1649    /// +-----+
1650    /// ```
1651    fn render_bottom_vertical_right_ln(&self, buf: &mut Buffer) {
1652        let mut bottom_vertical_right_ln = self.border_segments.bottom_vertical_right_ln.clone();
1653        let used_bottom_vertical_right_ln: Vec<Span> =
1654            if bottom_vertical_right_ln.should_use_gradient {
1655                Self::create_gradient_text(
1656                    &bottom_vertical_right_ln.clone().segment_text,
1657                    bottom_vertical_right_ln.gradient.clone().unwrap().0,
1658                    bottom_vertical_right_ln.gradient.as_mut().unwrap().1,
1659                )
1660            } else {
1661                bottom_vertical_right_ln
1662                    .clone()
1663                    .segment_text
1664                    .chars()
1665                    .map(|i| Span::raw(i.to_string()))
1666                    .collect()
1667            };
1668        for (i, span) in used_bottom_vertical_right_ln.iter().enumerate() {
1669            buf.set_span(
1670                bottom_vertical_right_ln.x,
1671                bottom_vertical_right_ln.y + i as u16,
1672                span,
1673                1,
1674            );
1675        }
1676    }
1677
1678    /// Renders the bottom vertical left segment of the border with an optional gradient.
1679    ///
1680    /// # Parameters:
1681    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1682    ///
1683    /// This function renders the bottom-left vertical segment of the border. If the segment associated with
1684    /// this line should use a gradient, it applies the gradient to the segment text using the `create_gradient_text`
1685    /// function. Otherwise, the function renders the segment text as-is.
1686    /// ## Visual Representation:
1687    /// Without the function:
1688    /// ```
1689    /// +-----+
1690    /// |     |
1691    /// |     |
1692    /// +     +
1693    /// |
1694    /// |
1695    /// +-----+
1696    /// ```
1697    fn render_bottom_vertical_left_ln(&self, buf: &mut Buffer) {
1698        let mut bottom_vertical_left_ln = self.border_segments.bottom_vertical_left_ln.clone();
1699        let used_bottom_vertical_left_ln: Vec<Span> = if bottom_vertical_left_ln.should_use_gradient
1700        {
1701            Self::create_gradient_text(
1702                &bottom_vertical_left_ln.clone().segment_text,
1703                bottom_vertical_left_ln.gradient.clone().unwrap().0,
1704                bottom_vertical_left_ln.gradient.as_mut().unwrap().1,
1705            )
1706        } else {
1707            bottom_vertical_left_ln
1708                .clone()
1709                .segment_text
1710                .chars()
1711                .map(|i| Span::raw(i.to_string()))
1712                .collect()
1713        };
1714        for (i, span) in used_bottom_vertical_left_ln.iter().enumerate() {
1715            buf.set_span(
1716                bottom_vertical_left_ln.x,
1717                bottom_vertical_left_ln.y + i as u16,
1718                span,
1719                1,
1720            );
1721        }
1722    }
1723
1724    /// Renders the bottom titles for the `TuiGradientblock` widget, with optional gradient support.
1725    ///
1726    /// # Parameters:
1727    /// - `area`: A `Rc<Rect>` that defines the area where the bottom titles will be rendered.
1728    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1729    ///
1730    /// This function renders each title in the `bottom_titles` collection with a specified alignment:
1731    /// - **Left-aligned**: The title is rendered at the left edge of the bottom row of the area.
1732    /// - **Right-aligned**: The title is rendered at the right edge of the bottom row of the area.
1733    /// - **Centered**: The title is centered within the bottom row of the area.
1734    ///
1735    /// If a gradient is specified for a title, it is applied by calling `create_gradient_text`
1736    /// with the gradient’s start and end colors. The resulting text is then rendered with the specified alignment.
1737    fn render_bottom_titles(&self, area: Rc<Rect>, buf: &mut Buffer) {
1738        for title in &self.bottom_titles {
1739            let ln = match &title.2 {
1740                Some(s) => &Line::from(Self::create_gradient_text(&title.0, s.0.clone(), s.1)),
1741                None => &Line::from(title.0.clone()),
1742            };
1743            match title.1 {
1744                TitleAlignment::LeftAligned => {
1745                    buf.set_line(area.left() + 1, area.bottom() - 1, ln, title.0.len() as u16);
1746                }
1747                TitleAlignment::RightAligned => {
1748                    buf.set_line(
1749                        (area.right() - 1).saturating_sub(title.0.len() as u16),
1750                        area.bottom() - 1,
1751                        ln,
1752                        title.0.len() as u16,
1753                    );
1754                }
1755                TitleAlignment::Centered => {
1756                    buf.set_line(
1757                        (area.right() / 2).saturating_sub(title.0.len() as u16 / 2),
1758                        area.bottom() - 1,
1759                        ln,
1760                        title.0.len() as u16,
1761                    );
1762                }
1763            }
1764        }
1765    }
1766
1767    /// Renders the top titles for the `TuiGradientblock` widget, with optional gradient support.
1768    ///
1769    /// # Parameters:
1770    /// - `area`: A `Rc<Rect>` that defines the area where the top titles will be rendered.
1771    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1772    ///
1773    /// This function renders each title in the `top_titles` collection with a specified alignment:
1774    /// - **Left-aligned**: The title is rendered at the left edge of the area.
1775    /// - **Right-aligned**: The title is rendered at the right edge of the area.
1776    /// - **Centered**: The title is centered within the area.
1777    ///
1778    /// If a gradient is specified for a title, it is applied by calling `create_gradient_text`
1779    /// with the gradient’s start and end colors. The resulting text is then rendered with the specified alignment.
1780    ///
1781    /// # Example:
1782    /// ```rust
1783    /// let widget = TuiGradientblock::new();
1784    /// let area = Rc::new(Rect::new(0, 0, 20, 5));
1785    /// let mut buffer = Buffer::new();
1786    /// widget.render_top_titles(area, &mut buffer);
1787    /// ```
1788    fn render_top_titles(&self, area: Rc<Rect>, buf: &mut Buffer) {
1789        for title in &self.top_titles {
1790            let ln = match &title.2 {
1791                Some(s) => &Line::from(Self::create_gradient_text(&title.0, s.0.clone(), s.1)),
1792                None => &Line::from(title.0.clone()),
1793            };
1794            match title.1 {
1795                TitleAlignment::LeftAligned => {
1796                    buf.set_line(area.left() + 1, area.top(), ln, title.0.len() as u16);
1797                }
1798                TitleAlignment::RightAligned => {
1799                    buf.set_line(
1800                        (area.right() - 1).saturating_sub(title.0.len() as u16),
1801                        area.top(),
1802                        ln,
1803                        title.0.len() as u16,
1804                    );
1805                }
1806                TitleAlignment::Centered => {
1807                    buf.set_line(
1808                        (area.right() / 2).saturating_sub(title.0.len() as u16 / 2),
1809                        area.top(),
1810                        ln,
1811                        title.0.len() as u16,
1812                    );
1813                }
1814            }
1815        }
1816    }
1817
1818    /// Renders the fill for the `TuiGradientblock` widget, including optional gradient rendering.
1819    ///
1820    /// # Parameters:
1821    /// - `area`: A `Rc<Rect>` that defines the area in which to render the fill.
1822    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1823    ///
1824    /// This function performs the following:
1825    /// - If a `fill_string` is provided (via `self.fill.fill_string`), it generates a repeated string
1826    ///   pattern to fill the given `area`.
1827    /// - If no gradient is specified (`self.fill.gradient` is `None`), it renders the repeated string
1828    ///   in the specified area using a simple block with borders.
1829    /// - If a gradient is provided, the function applies the gradient to the fill and renders the
1830    ///   resulting text using a centered block with borders.
1831    ///
1832    /// The function uses `Paragraph::new` to render the text and applies wrapping and border options.
1833    /// It also calls `create_gradient_text` to generate the text with the applied gradient if a gradient
1834    /// is specified.
1835    ///
1836    /// # Example:
1837    /// ```rust
1838    /// let widget = TuiGradientblock::new();
1839    /// let area = Rc::new(Rect::new(0, 0, 10, 5));
1840    /// let mut buffer = Buffer::new();
1841    /// widget.render_fill(area, &mut buffer);
1842    /// ```
1843    fn render_fill(&self, area: Rc<Rect>, buf: &mut Buffer) {
1844        let mut string = self.fill.fill_string.clone().unwrap();
1845        string.push(' ');
1846        if self.fill.gradient.is_none() {
1847            Paragraph::new(string.repeat(area.width as usize * string.len()).to_owned())
1848                .wrap(Wrap { trim: true })
1849                .block(Block::default().borders(Borders::ALL))
1850                .render(*area, buf);
1851        } else {
1852            // Get a reference to the gradient and its color values
1853            let gradient = self.fill.gradient.as_ref().unwrap();
1854            let gradient_text = Self::create_gradient_text(
1855                &string
1856                    .repeat(area.width as usize * string.len())
1857                    .to_string(),
1858                gradient.0.clone(),
1859                gradient.1,
1860            );
1861
1862            let text = Line::from(gradient_text);
1863            Paragraph::new(text)
1864                .centered()
1865                .wrap(Wrap { trim: true })
1866                .block(Block::default().borders(Borders::ALL))
1867                .render(*area, buf);
1868        }
1869    }
1870
1871    /// Renders the `TuiGradientblock` widget, including optional fill and custom block rendering,
1872    /// along with top and bottom titles.
1873    ///
1874    /// # Parameters:
1875    /// - `area`: A reference to a `Rect` that specifies the area to render the widget in.
1876    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1877    ///
1878    /// This function:
1879    /// - Checks if there is a fill string and calls `render_fill` if present.
1880    /// - Renders the custom block using `render_custom_block`.
1881    /// - Renders the top titles using `render_top_titles`.
1882    /// - Renders the bottom titles using `render_bottom_titles`.
1883    pub fn main(&self, area: &Rect, buf: &mut Buffer) {
1884        let area_rc = Rc::new(*area);
1885        if self.fill.fill_string.is_some() {
1886            Self::render_fill(self, Rc::clone(&area_rc), buf);
1887        }
1888        self.render_block(buf);
1889        Self::render_top_titles(self, Rc::clone(&area_rc), buf);
1890        Self::render_bottom_titles(self, Rc::clone(&area_rc), buf);
1891    }
1892}
1893impl Widget for TuiGradientblock {
1894    /// Renders the `TuiGradientblock` widget using the `main` function.
1895    ///
1896    /// This is part of the `Widget` trait implementation. The `render` function takes an
1897    /// `area` and a mutable reference to the `Buffer`, and delegates rendering to the `main` function.
1898    ///
1899    /// # Parameters:
1900    /// - `area`: A `Rect` that defines the area for rendering the widget.
1901    /// - `buf`: A mutable reference to the `Buffer` where the rendered output will be stored.
1902    ///
1903    /// # Example:
1904    /// ```
1905    /// let widget = TuiGradientblock::new();
1906    /// let area = Rect::new(0, 0, 10, 10);
1907    /// let mut buffer = Buffer::new();
1908    /// widget.render(area, &mut buffer);
1909    /// ```
1910    fn render(self, area: Rect, buf: &mut Buffer) {
1911        self.main(&area, buf);
1912    }
1913}
1914#[derive(Clone)]
1915/// Contains miscellaneous border types
1916pub enum MiscBorderTypes {
1917    /// ```
1918    /// +=====+
1919    /// |     |
1920    /// |     |
1921    /// |     |
1922    /// +=====+
1923    /// ```
1924    Misc1,
1925    /// ```
1926    /// +=====+
1927    /// |     |
1928    /// +     +
1929    /// |     |
1930    /// ╘═════╛
1931    /// ```
1932    Misc2,
1933    /// ``````
1934    /// ╬═════╬
1935    /// ║     ║
1936    /// ║     ║
1937    /// ║     ║
1938    /// ╬═════╬
1939    /// ```
1940    Misc3,
1941    /// ```
1942    /// $──~──$
1943    /// |     |
1944    /// ~     ~
1945    /// |     |
1946    /// $──~──$
1947    /// ```
1948    Misc4,
1949}
1950#[derive(Clone)]
1951/// contains the custom border types
1952/// Defines different border styles that can be applied.
1953pub enum BorderStyle {
1954    /// A simple, single-line border (e.g., `│─┌┐└┘`).
1955    Plain,
1956    /// A double-line border for a more structured appearance (e.g., `║═╔╗╚╝`).
1957    Double,
1958    /// A thick border for strong emphasis (may vary depending on rendering support).
1959    Thick,
1960    /// A rounded border with smooth corners (e.g., `╭╮╰╯`).
1961    Rounded,
1962    /// A completely empty, user-defined custom border.
1963    CustomBorderType,
1964    /// A collection of miscellaneous border types.
1965    MiscBorder(MiscBorderTypes),
1966}
1967
1968#[derive(Debug, Clone)]
1969/// A set of symbols that define the appearance of a border.  
1970/// Most symbols are optional, allowing for customization of corners, edges, and intersections.
1971struct BorderSymbols {
1972    /// The character used for the top-left corner of the border (e.g., '┌' for a box).  
1973    /// If not set, a default may be used.
1974    top_left: Option<char>,
1975
1976    /// The character used for the top-right corner of the border (e.g., '┐' for a box).
1977    top_right: Option<char>,
1978
1979    /// The character used for the bottom-left corner of the border (e.g., '└' for a box).
1980    bottom_left: Option<char>,
1981
1982    /// The character used for the bottom-right corner of the border (e.g., '┘' for a box).
1983    bottom_right: Option<char>,
1984
1985    /// The character placed at the center of the top border.  
1986    /// Defaults to `top_horizontal` if not specified.
1987    top_center: Option<char>,
1988
1989    /// The character placed at the center of the bottom border.  
1990    /// Defaults to `bottom_horizontal` if not specified.
1991    bottom_center: Option<char>,
1992
1993    /// The character placed at the center of the left border.  
1994    /// Defaults to `left_vertical` if not specified.
1995    left_center: Option<char>,
1996
1997    /// The character placed at the center of the right border.  
1998    /// Defaults to `right_vertical` if not specified.
1999    right_center: Option<char>,
2000
2001    /// The character used for the horizontal segments of the top border (e.g., '─' for a solid line).  
2002    /// Defaults to '─' if not set.
2003    top_horizontal: Option<char>,
2004
2005    /// The character used for the vertical segments of the left border (e.g., '│' for a solid line).  
2006    /// Defaults to '│' if not set.
2007    left_vertical: Option<char>,
2008
2009    /// The character used for the horizontal segments of the bottom border (e.g., '─' for a solid line).  
2010    /// Defaults to '─' if not set.
2011    bottom_horizontal: Option<char>,
2012
2013    /// The character used for the vertical segments of the right border (e.g., '│' for a solid line).  
2014    /// Defaults to '│' if not set.
2015    right_vertical: Option<char>,
2016
2017    /// The character repeated for the right side of the top border.  
2018    /// Defaults to `top_horizontal` if not set.
2019    top_horizontal_right: Option<char>,
2020
2021    /// The character repeated for the right side of the bottom border.  
2022    /// Defaults to `bottom_horizontal` if not set.
2023    bottom_horizontal_right: Option<char>,
2024
2025    /// The character repeated for the left side of the top border.  
2026    /// Defaults to `top_horizontal` if not set.
2027    top_horizontal_left: Option<char>,
2028
2029    /// The character repeated for the left side of the bottom border.  
2030    /// Defaults to `bottom_horizontal` if not set.
2031    bottom_horizontal_left: Option<char>,
2032
2033    /// The character repeated for the top section of the right border.  
2034    /// Defaults to `right_vertical` if not set.
2035    top_vertical_right: Option<char>,
2036
2037    /// The character repeated for the bottom section of the right border.  
2038    /// Defaults to `right_vertical` if not set.
2039    bottom_vertical_right: Option<char>,
2040
2041    /// The character repeated for the top section of the left border.  
2042    /// Defaults to `left_vertical` if not set.
2043    top_vertical_left: Option<char>,
2044
2045    /// The character repeated for the bottom section of the left border.  
2046    /// Defaults to `left_vertical` if not set.
2047    bottom_vertical_left: Option<char>,
2048}
2049
2050#[derive(Debug, Clone)]
2051/// controls the optional fill with an optional gradient
2052struct Fill {
2053    fill_string: Option<String>,
2054    gradient: Option<(Vec<(u8, u8, u8)>, f32)>,
2055}
2056#[derive(Debug, Clone)]
2057struct BorderSegment {
2058    /// The text representation of this border segment.  
2059    /// - For a top border, this might be `"┌──────┐"`.  
2060    /// - For a right border, this might be `"┐││││┘"` (each character is rendered on a separate line from top to bottom, as newlines cannot be rendered directly).
2061    segment_text: String,
2062
2063    /// An optional gradient applied to this border segment.  
2064    /// The gradient consists of a vector of RGB color values and a scaling factor.
2065    gradient: Option<(Vec<(u8, u8, u8)>, f32)>,
2066
2067    /// Determines whether this segment should be rendered with a gradient.  
2068    /// If `false`, the gradient (if present) will be ignored.
2069    should_use_gradient: bool,
2070
2071    /// Determines whether the segment should be rendered at all.  
2072    /// If `false`, this segment will not be displayed.
2073    should_be_rendered: bool,
2074
2075    /// The X-coordinate of the segment’s position.
2076    x: u16,
2077
2078    /// The Y-coordinate of the segment’s position.
2079    y: u16,
2080}
2081impl BorderSegment {
2082    /// Creates a new, empty border segment at the specified position.  
2083    ///
2084    /// The segment starts with no text, no gradient, and is not set to be rendered by default.
2085    ///
2086    /// # Parameters
2087    /// - `x`: The X-coordinate of the segment’s position.
2088    /// - `y`: The Y-coordinate of the segment’s position.
2089    ///
2090    /// # Returns
2091    /// A `BorderSegment` instance with default values.
2092    pub fn new(x: u16, y: u16) -> Self {
2093        Self {
2094            segment_text: String::new(),
2095            gradient: None,
2096            should_use_gradient: false,
2097            should_be_rendered: false,
2098            x,
2099            y,
2100        }
2101    }
2102}
2103
2104#[derive(Debug, Clone)]
2105
2106/// A collection of border segments representing different parts of a bordered structure.  
2107///
2108/// This struct holds individual `BorderSegment` instances for each section of the border,  
2109/// ensuring flexibility in rendering complex layouts.
2110struct BorderSegments {
2111    /// The left portion of the top horizontal border.
2112    top_horizontal_left_ln: BorderSegment,
2113    /// The right portion of the top horizontal border.
2114    top_horizontal_right_ln: BorderSegment,
2115    /// The left portion of the bottom horizontal border.
2116    bottom_horizontal_left_ln: BorderSegment,
2117    /// The right portion of the bottom horizontal border.
2118    bottom_horizontal_right_ln: BorderSegment,
2119    /// The upper portion of the left vertical border.
2120    top_vertical_left_ln: BorderSegment,
2121    /// The upper portion of the right vertical border.
2122    top_vertical_right_ln: BorderSegment,
2123    /// The lower portion of the left vertical border.
2124    bottom_vertical_left_ln: BorderSegment,
2125    /// The lower portion of the right vertical border.
2126    bottom_vertical_right_ln: BorderSegment,
2127    /// The full top border segment.
2128    top_ln: BorderSegment,
2129    /// The full bottom border segment.
2130    bottom_ln: BorderSegment,
2131    /// The full left border segment.
2132    left_ln: BorderSegment,
2133    /// The full right border segment.
2134    right_ln: BorderSegment,
2135}
2136impl BorderSegments {
2137    /// Creates a new set of `BorderSegments` for a given rectangular area.
2138    ///
2139    /// This constructor initializes border segments based on the provided `Rect` dimensions,
2140    /// ensuring correct positioning for all parts of the border.
2141    ///
2142    /// # Arguments
2143    /// * `area` - A reference to a `Rect` defining the bounds of the border.
2144    ///
2145    /// # Returns
2146    /// A `BorderSegments` instance with all segments initialized at their respective positions.
2147    pub fn new(area: &Rect) -> Self {
2148        Self {
2149            top_horizontal_left_ln: BorderSegment::new(area.left(), area.top()),
2150            top_horizontal_right_ln: BorderSegment::new(area.right() / 2, area.top()),
2151            bottom_horizontal_left_ln: BorderSegment::new(area.left(), area.bottom() - 1),
2152            bottom_horizontal_right_ln: BorderSegment::new(area.right() / 2, area.bottom() - 1),
2153            top_vertical_left_ln: BorderSegment::new(area.left(), area.top()),
2154            top_vertical_right_ln: BorderSegment::new(area.right() - 1, area.top()),
2155            bottom_vertical_left_ln: BorderSegment::new(
2156                area.left(),
2157                ((area.height as usize + 1) / 2) as u16,
2158            ),
2159            bottom_vertical_right_ln: BorderSegment::new(
2160                area.right() - 1,
2161                ((area.height as usize + 1) / 2) as u16,
2162            ),
2163            top_ln: BorderSegment::new(area.left(), area.top()),
2164            bottom_ln: BorderSegment::new(area.left(), area.bottom() - 1),
2165            left_ln: BorderSegment::new(area.left(), area.top()),
2166            right_ln: BorderSegment::new(area.right() - 1, area.top()),
2167        }
2168    }
2169}
2170
2171bitflags! {
2172    /// Represents individual border segments that can be split or modified.
2173    #[derive(PartialEq, Clone)]
2174    pub struct SplitBorderSegments: u8 {
2175        /// No border segments are split.
2176        const NONE   = 0b0000;
2177        /// The left border segment is split.
2178        const LEFT   = 0b0001;
2179        /// The right border segment is split.
2180        const RIGHT  = 0b0010;
2181        /// The top border segment is split.
2182        const TOP    = 0b0100;
2183        /// The bottom border segment is split.
2184        const BOTTOM = 0b1000;
2185        /// All border segments are split.
2186        const ALL    = Self::LEFT.bits() | Self::RIGHT.bits() | Self::TOP.bits() | Self::BOTTOM.bits();
2187    }
2188}
2189#[derive(Clone)]
2190/// Represents different segments of a border where gradients can be applied.
2191///
2192/// This enum is used to control gradient effects for specific border sections,
2193/// allowing for finer customization of visual styles.
2194pub enum GradientSegments {
2195    /// The top border segment.
2196    Top,
2197    /// The bottom border segment.
2198    Bottom,
2199    /// The left border segment.
2200    Left,
2201    /// The right border segment.
2202    Right,
2203    /// The right portion of the top horizontal border.
2204    TopHorizontalRightLn,
2205    /// The left portion of the top horizontal border.
2206    TopHorizontalLeftLn,
2207    /// The right portion of the bottom horizontal border.
2208    BottomHorizontalRightLn,
2209    /// The left portion of the bottom horizontal border.
2210    BottomHorizontalLeftLn,
2211    /// The right portion of the top vertical border.
2212    TopVerticalRightLn,
2213    /// The left portion of the top vertical border.
2214    TopVerticalLeftLn,
2215    /// The right portion of the bottom vertical border.
2216    BottomVerticalRightLn,
2217    /// The left portion of the bottom vertical border.
2218    BottomVerticalLeftLn,
2219}
2220#[derive(Clone)]
2221/// Defines the alignment options for a title within a bordered area.
2222pub enum TitleAlignment {
2223    /// Centers the title within the border.
2224    Centered,
2225    /// Aligns the title to the left within the border.
2226    LeftAligned,
2227    /// Aligns the title to the right within the border.
2228    RightAligned,
2229}