tui_gradient_block/
setter_functions.rs

1use crate::{
2    enums,
3    gradient_block::{self, SS},
4    structs::flags,
5    text::Line,
6    types::G,
7    widgets::{self, block::title::Position},
8};
9use tui_rule::{create_raw_spans, generate_gradient_text};
10impl<'a> gradient_block::GradientBlock<'a> {
11    pub fn with_gradient(
12        mut self,
13        gradient: crate::structs::gradient::GradientVariation,
14    ) -> Self {
15        self = self
16            .right_gradient(gradient.right)
17            .left_gradient(gradient.left)
18            .top_gradient(gradient.top)
19            .bottom_gradient(gradient.bottom);
20        self
21    }
22    /// sets the right segment
23    pub fn right(mut self, seg: tui_rule::Rule) -> Self {
24        self.border_segments.right.seg = seg;
25        self
26    }
27    /// sets the left segment
28    pub fn left(mut self, seg: tui_rule::Rule) -> Self {
29        self.border_segments.left.seg = seg;
30        self
31    }
32    /// sets the top segment
33    pub fn top(mut self, seg: tui_rule::Rule) -> Self {
34        self.border_segments.top.seg = seg;
35        self
36    }
37    /// sets bottom segment
38    pub fn bottom(mut self, seg: tui_rule::Rule) -> Self {
39        self.border_segments.bottom.seg = seg;
40        self
41    }
42    /// Sets gradient of the right segment of the border.
43    pub fn right_gradient(mut self, gradient: G) -> Self {
44        self.border_segments.right.seg.gradient = Some(gradient);
45        self
46    }
47    /// Sets gradient of the left segment of the border.
48    pub fn left_gradient(mut self, gradient: G) -> Self {
49        self.border_segments.left.seg.gradient = Some(gradient);
50        self
51    }
52    /// Sets gradient of the top segment of the border.
53    pub fn top_gradient(mut self, gradient: G) -> Self {
54        self.border_segments.top.seg.gradient = Some(gradient);
55        self
56    }
57    /// Sets gradient of the bottom segment of the border.
58    pub fn bottom_gradient(mut self, gradient: G) -> Self {
59        self.border_segments.bottom.seg.gradient = Some(gradient);
60        self
61    }
62    pub fn margin(mut self, horizontal: u16, vertical: u16) -> Self {
63        let marg = ratatui::prelude::layout::Margin::new(
64            horizontal, vertical,
65        );
66        let segs = &mut self.border_segments;
67        segs.bottom.seg.area_margin = marg;
68        segs.top.seg.area_margin = marg;
69        segs.right.seg.area_margin = marg;
70        segs.left.seg.area_margin = marg;
71        self
72    }
73    pub fn horizontal_margin(mut self, margin: u16) -> Self {
74        let segs = &mut self.border_segments;
75        segs.bottom.seg.area_margin.horizontal = margin;
76        segs.top.seg.area_margin.horizontal = margin;
77        segs.right.seg.area_margin.horizontal = margin;
78        segs.left.seg.area_margin.horizontal = margin;
79        self
80    }
81    pub fn vertical_margin(mut self, margin: u16) -> Self {
82        let segs = &mut self.border_segments;
83        segs.bottom.seg.area_margin.vertical = margin;
84        segs.top.seg.area_margin.vertical = margin;
85        segs.right.seg.area_margin.vertical = margin;
86        segs.left.seg.area_margin.vertical = margin;
87        self
88    }
89    pub fn right_padding(mut self, padding: u16) -> Self {
90        let segs = &mut self.border_segments;
91        segs.top.seg.padding.right = padding;
92        segs.bottom.seg.padding.right = padding;
93        segs.right.seg.padding.right = padding;
94        self
95    }
96    pub fn left_padding(mut self, padding: u16) -> Self {
97        let segs = &mut self.border_segments;
98        segs.top.seg.padding.left = padding;
99        segs.bottom.seg.padding.left = padding;
100        segs.left.seg.padding.left = padding;
101        self
102    }
103
104    pub fn top_padding(mut self, padding: u16) -> Self {
105        let segs = &mut self.border_segments;
106        segs.top.seg.padding.top = padding;
107        segs.left.seg.padding.top = padding;
108        segs.right.seg.padding.top = padding;
109        self
110    }
111
112    pub fn bottom_padding(mut self, padding: u16) -> Self {
113        let segs = &mut self.border_segments;
114        segs.bottom.seg.padding.bottom = padding;
115        segs.left.seg.padding.bottom = padding;
116        segs.right.seg.padding.bottom = padding;
117        self
118    }
119
120    pub fn borders(
121        mut self,
122        borders: widgets::Borders,
123        corners: bool,
124    ) -> Self {
125        use widgets::Borders as B;
126        macro_rules! set_seg_state {
127            ($seg:ident, $state:expr) => {
128                self.border_segments.$seg.should_be_rendered = $state;
129            };
130        }
131        macro_rules! set_corner {
132            ($seg:ident, $val:ident) => {
133                self.border_segments.$seg.seg.symbol_set.$val = ' '
134            };
135        }
136        if !borders.contains(B::RIGHT) {
137            set_seg_state!(right, false);
138            if corners {
139                set_corner!(top, end);
140                set_corner!(bottom, end);
141            }
142        }
143        if !borders.contains(B::LEFT) {
144            set_seg_state!(left, false);
145            if corners {
146                set_corner!(top, start);
147                set_corner!(bottom, start);
148            }
149        }
150        if !borders.contains(B::TOP) {
151            set_seg_state!(top, false);
152            if corners {
153                set_corner!(left, start);
154                set_corner!(right, start);
155            }
156        }
157        if !borders.contains(B::BOTTOM) {
158            set_seg_state!(bottom, false);
159            if corners {
160                set_corner!(right, end);
161                set_corner!(left, end);
162            }
163        }
164        if borders == B::NONE {
165            set_seg_state!(bottom, false);
166            set_seg_state!(left, false);
167            set_seg_state!(right, false);
168            set_seg_state!(top, false);
169        }
170        self
171    }
172
173    pub fn corners(mut self, corners: flags::Corners) -> Self {
174        use flags::Corners as C;
175        macro_rules! set_corner {
176            ($seg:ident, $corner:ident) => {
177                self.border_segments.$seg.seg.symbol_set.$corner = ' '
178            };
179        }
180        if !corners.contains(C::TOP_RIGHT) {
181            set_corner!(right, start);
182            set_corner!(top, end);
183        }
184        if !corners.contains(C::TOP_LEFT) {
185            set_corner!(left, start);
186            set_corner!(top, start);
187        }
188        if !corners.contains(C::BOTTOM_LEFT) {
189            set_corner!(left, end);
190            set_corner!(bottom, start);
191        }
192        if !corners.contains(C::BOTTOM_RIGHT) {
193            set_corner!(bottom, end);
194            set_corner!(right, end);
195        }
196        if corners == C::NONE {
197            set_corner!(bottom, end);
198            set_corner!(right, end);
199            set_corner!(left, end);
200            set_corner!(bottom, start);
201            set_corner!(left, start);
202            set_corner!(top, start);
203            set_corner!(right, start);
204            set_corner!(top, end);
205        }
206        self
207    }
208    pub fn center_symbols(
209        mut self,
210        symbols: flags::CenterSymbols,
211    ) -> Self {
212        use flags::CenterSymbols as S;
213        macro_rules! set_symb {
214            ($seg:ident) => {
215                self.border_segments.$seg.seg.symbol_set.center = ' '
216            };
217        }
218        if !symbols.contains(S::LEFT_CENTER) {
219            set_symb!(left);
220        }
221        if !symbols.contains(S::RIGHT_CENTER) {
222            set_symb!(right);
223        }
224        if !symbols.contains(S::BOTTOM_CENTER) {
225            set_symb!(bottom);
226        }
227        if !symbols.contains(S::TOP_CENTER) {
228            set_symb!(top);
229        }
230        if symbols == S::NONE {
231            set_symb!(top);
232            set_symb!(right);
233            set_symb!(left);
234            set_symb!(bottom);
235        }
236        self
237    }
238    pub fn title_top<I: Into<Line<'a>>>(mut self, title: I) -> Self {
239        self.titles.push((title.into(), Position::Top));
240        self
241    }
242    pub fn title_bottom<I: Into<Line<'a>>>(
243        mut self,
244        title: I,
245    ) -> Self {
246        self.titles.push((title.into(), Position::Bottom));
247        self
248    }
249    /// Sets the border style for the block.
250    ///
251    /// If this function is not called, the border will be plain by default.
252    ///
253    /// # Parameters
254    /// - `style`: A `BorderStyle` enum value that determines the appearance of the border.
255    ///   - `BorderStyle::New`: Empty to be set manually.
256    ///   - `BorderStyle::Custom`: Custom border from `SegmentSet` struct
257    ///
258    /// # Example 1: Using a standard border style
259    /// ```
260    /// let border = GradientBlock::new().border_style(BorderStyle::Double);
261    /// ```
262    ///
263    /// # Example 2: Using a miscellaneous border style
264    /// ```
265    /// let border = GradientBlock::new().with_border_style(BorderStyle::Custom(preset::MISC3));
266    /// ```
267    ///
268    /// # Example 3: Using a custom border type
269    /// ```
270    /// let border = GradientBlock::new()
271    ///     .with_border_style(BorderStyle::New)
272    ///     .top_left('╔')
273    ///     .top_right('╗')
274    ///     .bottom_left('╚')
275    ///     .bottom_right('╝');
276    /// ```
277    /// Sets the border style of the block.
278    ///
279    /// This function allows setting a predefined border style or a custom one.
280    ///
281    /// # Parameters
282    /// - `style`: A `BorderStyle` enum variant specifying the desired border style.
283    ///
284    /// # Behavior
285    /// - `BorderStyle::CustomBorderType`: Does not set predefined symbols, allowing manual customization.
286    /// - `BorderStyle::MiscBorder(MiscBorderTypes)`: Uses a predefined miscellaneous border style.
287    /// - `BorderStyle::Plain`, `BorderStyle::Double`, `BorderStyle::Thick`, `BorderStyle::Rounded`:
288    ///   Sets the block's borders to one of these predefined styles.
289    ///
290    /// # Example
291    /// ```let
292    /// let block = GradientBlock::new().border_style(BorderStyle::Double);
293    /// ```
294    pub fn with_border_style(
295        mut self,
296        style: enums::BorderStyle,
297    ) -> Self {
298        match style {
299            enums::BorderStyle::CustomSet(t) => {
300                self.border_segments =
301                    self.border_segments.from_segment_set(t);
302            }
303            enums::BorderStyle::NewSet => {
304                self.border_segments = self
305                    .border_segments
306                    .from_segment_set(crate::preset::EMPTY);
307            }
308            enums::BorderStyle::RatatuiSet(t) => {
309                self.border_segments = self
310                    .border_segments
311                    .from_segment_set(SS::from_ratatui_set(t));
312            }
313        };
314        self
315    }
316
317    /// Sets the titles that appear at the bottom of the border.
318    ///
319    /// # Parameters
320    /// - `titles`: A vector of tuples where each tuple contains:
321    ///   - A `String` representing the title text.
322    ///   - A `Alignment` indicating how the title should be aligned (e.g., left, center, right).
323    ///   - An optional tuple containing a vector of RGB colors and a gradient factor (f32).
324    ///
325    /// # Example
326    /// ```
327    /// let border = Border::new().bottom_titles(vec![
328    ///     ("Footer", Alignment::Center, Some((vec![(255, 0, 0), (190, 3, 252)], 0.5))),
329    /// ]);
330    /// ```
331    pub fn titles(mut self, titles: &'a [(Line, Position)]) -> Self {
332        self.titles = titles.to_vec();
333        self
334    }
335    pub fn title(mut self, title: Line<'a>, pos: Position) -> Self {
336        self.titles.push((title, pos));
337        self
338    }
339    /// Sets the symbol for the top-right corner of the border.
340    /// # Parameters
341    /// - `symb`: A `char` representing the symbol to be used in the top-right corner.
342    ///
343    /// # Example
344    /// ```
345    /// let border = GradientBlock::new().top_right('#');
346    /// ```
347    pub const fn top_right(mut self, symb: char) -> Self {
348        self.border_segments.right.seg.symbol_set.start = symb;
349        self.border_segments.top.seg.symbol_set.end = symb;
350        self
351    }
352
353    /// Sets the symbol for the top-left corner of the border.
354    ///
355    /// # Parameters
356    /// - `symb`: A `char` representing the symbol to be used in the top-left corner.
357    ///
358    /// # Example
359    /// ```
360    /// let border = GradientBlock::new().top_left('*');
361    /// ```
362    pub const fn top_left(mut self, symb: char) -> Self {
363        self.border_segments.left.seg.symbol_set.start = symb;
364        self.border_segments.top.seg.symbol_set.start = symb;
365        self
366    }
367
368    /// Sets the symbol for the bottom-right corner of the border.
369    ///
370    /// # Parameters
371    /// - `symb`: A `char` representing the symbol to be used in the bottom-right corner.
372    ///
373    /// # Example
374    /// ```
375    /// let border = GradientBlock::new().bottom_right('%');
376    /// ```
377    pub const fn bottom_right(mut self, symb: char) -> Self {
378        self.border_segments.bottom.seg.symbol_set.end = symb;
379        self.border_segments.right.seg.symbol_set.end = symb;
380        self
381    }
382
383    /// Sets the symbol for the bottom-left corner of the border.
384    ///
385    /// # Parameters
386    /// - `symb`: A `char` representing the symbol to be used in the bottom-left corner.
387    ///
388    /// # Example
389    /// ```
390    /// let border = GradientBlock::new().bottom_left('@');
391    /// ```
392    pub const fn bottom_left(mut self, symb: char) -> Self {
393        self.border_segments.bottom.seg.symbol_set.start = symb;
394        self.border_segments.left.seg.symbol_set.end = symb;
395        self
396    }
397
398    /// Sets the symbol for the bottom horizontal segment.
399    ///
400    /// # Parameters
401    /// - `symb`: A `char` representing the symbol to be used for the bottom horizontal border.
402    ///
403    /// # Example
404    /// ```
405    /// let border = GradientBlockr::new().bottom_horizontal_symbol('-');
406    /// ```
407    pub const fn bottom_horizontal_symbol(
408        mut self,
409        symb: char,
410    ) -> Self {
411        self.border_segments.bottom.seg.symbol_set.rep_1 = symb;
412        self.border_segments.bottom.seg.symbol_set.rep_2 = symb;
413
414        self
415    }
416
417    /// Sets the symbol for the top horizontal border segment.
418    ///
419    /// # Parameters
420    /// - `symb`: A `char` representing the symbol to be used for the top horizontal border.
421    ///
422    /// # Example
423    /// ```
424    /// let border = Border::new().top_horizontal_symbol('=');
425    /// ```
426    pub const fn top_horizontal_symbol(mut self, symb: char) -> Self {
427        self.border_segments.top.seg.symbol_set.rep_1 = symb;
428        self.border_segments.top.seg.symbol_set.rep_2 = symb;
429        self
430    }
431
432    /// Sets the symbol for the right vertical border segment.
433    ///
434    /// # Parameters
435    /// - `symb`: A `char` representing the symbol to be used for the right vertical border.
436    ///
437    /// # Example
438    /// ```
439    /// let border = GradientBlock::new().right_vertical_symbol('|');
440    /// ```
441    pub const fn right_vertical_symbol(mut self, symb: char) -> Self {
442        self.border_segments.right.seg.symbol_set.rep_1 = symb;
443        self.border_segments.right.seg.symbol_set.rep_2 = symb;
444        self
445    }
446    /// Sets the left vertical border symbol.
447    ///
448    /// # Example
449    /// ```
450    /// let widget = GradientBlock::new().left_vertical_symbol('|');
451    /// ```
452    pub const fn left_vertical_symbol(mut self, symb: char) -> Self {
453        self.border_segments.left.seg.symbol_set.rep_1 = symb;
454        self.border_segments.left.seg.symbol_set.rep_2 = symb;
455        self
456    }
457
458    /// Sets the top center border symbol.
459    ///
460    /// # Example
461    /// ```
462    /// let widget = GradientBlock::new().top_center_symbol('─');
463    /// ```
464    pub const fn top_center_symbol(mut self, symb: char) -> Self {
465        self.border_segments.top.seg.symbol_set.center = symb;
466        self
467    }
468
469    /// Sets the bottom center border symbol.
470    ///
471    /// # Example
472    /// ```
473    /// let widget = GradientBlock::new().bottom_center_symbol('═');
474    /// ```
475    pub const fn bottom_center_symbol(mut self, symb: char) -> Self {
476        self.border_segments.bottom.seg.symbol_set.center = symb;
477        self
478    }
479
480    /// Sets the left center vertical border symbol.
481    ///
482    /// # Example
483    /// ```
484    /// let widget = GradientBlock::new().left_center_symbol('+');
485    /// ```
486    pub const fn left_center_symbol(mut self, symb: char) -> Self {
487        self.border_segments.left.seg.symbol_set.center = symb;
488        self
489    }
490
491    /// Sets the right center vertical border symbol.
492    ///
493    /// # Example
494    /// ```
495    /// let widget = GradientBlock::new().right_center_symbol('+');
496    /// ```
497    pub const fn right_center_symbol(mut self, symb: char) -> Self {
498        self.border_segments.right.seg.symbol_set.center = symb;
499        self
500    }
501
502    /// Sets the top right horizontal border symbol.
503    ///
504    /// # Example
505    /// ```
506    /// let widget = GradientBlock::new().top_horizontal_right_symbol('┐');
507    /// ```
508    pub fn top_horizontal_right_symbol(mut self, symb: char) -> Self {
509        self.border_segments.top.seg.symbol_set.rep_2 = symb;
510        self
511    }
512    /// Sets the symbol used for the repeated section of the bottom horizontal border (right side).
513    ///
514    /// # Example
515    /// ```
516    /// let block = GradientBlock::new().bottom_horizontal_right_symbol('*');
517    /// ```
518    pub const fn bottom_horizontal_right_symbol(
519        mut self,
520        symb: char,
521    ) -> Self {
522        self.border_segments.bottom.seg.symbol_set.rep_2 = symb;
523        self
524    }
525
526    /// Sets the symbol for the top horizontal left connector.
527    ///
528    /// # Example
529    /// ```
530    /// let block = GradientBlock::new().top_horizontal_left_symbol('=');
531    /// ```
532    pub const fn top_horizontal_left_symbol(
533        mut self,
534        symb: char,
535    ) -> Self {
536        self.border_segments.top.seg.symbol_set.rep_1 = symb;
537        self
538    }
539
540    /// Sets the symbol for the bottom horizontal left connector.
541    ///
542    /// # Example
543    /// ```
544    /// let block = GradientBlock::new().bottom_horizontal_left_symbol('=');
545    /// ```
546    pub const fn bottom_horizontal_left_symbol(
547        mut self,
548        symb: char,
549    ) -> Self {
550        self.border_segments.bottom.seg.symbol_set.rep_1 = symb;
551        self
552    }
553
554    /// Sets the symbol for the top vertical right connector.
555    ///
556    /// # Example
557    /// ```
558    /// let block = GradientBlock::new().top_vertical_right_symbol('|');
559    /// ```
560    pub const fn top_vertical_right_symbol(
561        mut self,
562        symb: char,
563    ) -> Self {
564        self.border_segments.right.seg.symbol_set.rep_1 = symb;
565        self
566    }
567
568    /// Sets the symbol for the bottom vertical right connector.
569    ///
570    /// # Example
571    /// ```
572    /// let block = GradientBlock::new().bottom_vertical_right_symbol('|');
573    /// ```
574    pub const fn bottom_vertical_right_symbol(
575        mut self,
576        symb: char,
577    ) -> Self {
578        self.border_segments.right.seg.symbol_set.rep_2 = symb;
579        self
580    }
581
582    /// Sets the symbol for the top vertical left connector.
583    ///
584    /// # Example
585    /// ```
586    /// let block = GradientBlock::new().top_vertical_left_symbol('|');
587    /// ```
588    pub const fn top_vertical_left_symbol(
589        mut self,
590        symb: char,
591    ) -> Self {
592        self.border_segments.left.seg.symbol_set.rep_1 = symb;
593        self
594    }
595    pub fn with_set(mut self, set: SS) -> Self {
596        self = self
597            .with_border_style(enums::BorderStyle::CustomSet(set));
598        self
599    }
600
601    /// Sets the symbol for the bottom vertical left connector.
602    ///
603    /// # Example
604    /// ```
605    /// let block = GradientBlock::new().bottom_vertical_left_symbol('|');
606    /// ```
607    pub const fn bottom_vertical_left_symbol(
608        mut self,
609        symb: char,
610    ) -> Self {
611        self.border_segments.left.seg.symbol_set.rep_2 = symb;
612        self
613    }
614    pub fn fill<L: Into<Line<'a>>>(mut self, fill: L) -> Self {
615        self.fill = fill.into();
616        self
617    }
618    /// Sets the fill gradient
619    /// # Example
620    /// ```
621    /// let block = GradientBlock::new().fill_gradient(colorgrad::preset::warm());
622    /// ```
623    pub fn fill_gradient<GR: colorgrad::Gradient>(
624        mut self,
625        gradient: GR,
626    ) -> Self {
627        self.fill =
628            Line::from(generate_gradient_text!(self.fill, gradient));
629        self
630    }
631}