libnotcurses_sys/visual/options/
builder.rs

1//!
2
3use crate::{NcAlign, NcBlitter, NcPlane, NcRgba, NcScale, NcVisualFlag, NcVisualOptions};
4
5/// Builder object for [`NcVisualOptions`].
6///
7/// Can be constructed by calling [`NcVisualOptions::builder()`].
8///
9/// [`NcVisualOptions::builder()`]: NcVisualOptions#method.builder
10#[derive(Debug, Default)]
11pub struct NcVisualOptionsBuilder<'ncplane> {
12    plane: Option<&'ncplane mut NcPlane>,
13    scale: NcScale,
14    y: i32,
15    x: i32,
16    region_yx_lenyx: Option<(u32, u32, u32, u32)>,
17    cell_offset_yx: Option<(u32, u32)>,
18    blitter: NcBlitter,
19    flags: NcVisualFlag,
20    transcolor: NcRgba,
21}
22
23mod core_impls {
24    use super::{NcVisualOptions, NcVisualOptionsBuilder};
25
26    impl<'a> From<NcVisualOptionsBuilder<'a>> for NcVisualOptions {
27        fn from(builder: NcVisualOptionsBuilder<'a>) -> NcVisualOptions {
28            builder.build()
29        }
30    }
31
32    impl<'a> From<NcVisualOptions> for NcVisualOptionsBuilder<'a> {
33        fn from(options: NcVisualOptions) -> NcVisualOptionsBuilder<'a> {
34            Self::from_options(&options)
35        }
36    }
37}
38
39/// # Constructors
40impl<'ncplane> NcVisualOptionsBuilder<'ncplane> {
41    /// New default `NcVisualOptionsBuilder`.
42    pub fn new() -> Self {
43        Self::default()
44    }
45
46    /// New builder from pre-existing options.
47    pub fn from_options(o: &NcVisualOptions) -> Self {
48        let mut builder = Self::default();
49
50        builder = builder.scale(o.scaling);
51        builder = builder.blitter(o.blitter);
52        builder = builder.cell_offset(o.pxoffy, o.pxoffx);
53        builder = builder.region(o.begy, o.begx, o.leny, o.lenx);
54
55        if o.does_plane() {
56            builder = builder.plane(unsafe { &mut *o.n });
57
58            if o.does_child_plane() {
59                builder = builder.child(true);
60            }
61        }
62
63        if o.does_alpha() {
64            builder = builder.transcolor(Some(o.transcolor))
65        }
66        if o.does_blend() {
67            builder = builder.blend(true);
68        }
69        if o.does_degrade() {
70            builder = builder.degrade(true);
71        }
72        if o.does_interpolate() {
73            builder = builder.interpolate(true);
74        }
75
76        if o.is_veraligned() {
77            builder = builder.valign(o.y);
78        } else {
79            builder = builder.y(o.y);
80        }
81        if o.is_horaligned() {
82            builder = builder.halign(o.x);
83        } else {
84            builder = builder.x(o.x);
85        }
86
87        builder
88    }
89}
90
91/// # Methods (chainable)
92impl<'ncplane> NcVisualOptionsBuilder<'ncplane> {
93    /// Sets the `NcPlane` where the blitting will be done.
94    ///
95    /// This `NcPlane` could also be considered the parent of a new plane where
96    /// the blitting will occur by utilizing the [`child`] method.
97    ///
98    /// When no `NcPlane` is provided, one will be created using the exact size
99    /// necessary to render the source with perfect fidelity (this might be
100    /// smaller or larger than the rendering area).
101    ///
102    /// Default: *`None`* (no plane).
103    ///
104    /// See also: *[`parent`]*, *[`child`]*, *[`no_plane`]*.
105    ///
106    /// [`child`]: NcVisualOptionsBuilder#method.child
107    /// [`parent`]: NcVisualOptionsBuilder#method.parent
108    /// [`no_plane`]: NcVisualOptionsBuilder#method.no_plane
109    pub fn plane(mut self, plane: &'ncplane mut NcPlane) -> Self {
110        self.plane = Some(plane);
111        self
112    }
113
114    /// If true, a [`plane`] must also be provided, which will be the parent
115    /// of a new child `NcPlane` into which the blitting will be done.
116    ///
117    /// If false, the blitting will occur in the provided [`plane`], if any,
118    /// or in a newly created `NcPlane` otherwise.
119    ///
120    /// Default: *false* (no child plaane).
121    ///
122    /// Effect: Sets the [`CHILDPLANE`] flag.
123    ///
124    /// See also: *[`plane`]*, *[`parent`]*.
125    ///
126    /// [`CHILDPLANE`]: NcVisualOptions#associatedconstant.CHILDPLANE
127    /// [`plane`]: NcVisualOptionsBuilder#method.plane
128    /// [`parent`]: NcVisualOptionsBuilder#method.parent
129    pub fn child(mut self, child: bool) -> Self {
130        if child {
131            self.flags |= NcVisualFlag::ChildPlane;
132        } else {
133            self.flags &= !NcVisualFlag::ChildPlane;
134        }
135        self
136    }
137
138    /// Sets the `NcPlane` that will be the parent of a new `NcPlane` where
139    /// the blitting will be done.
140    ///
141    /// This is the same as calling both [`plane`] and [`child`].
142    ///
143    /// See also: *[`plane`]*, *[`child`]*.
144    ///
145    /// [`plane`]: NcVisualOptionsBuilder#method.plane
146    /// [`child`]: NcVisualOptionsBuilder#method.child
147    pub fn parent(mut self, plane: &'ncplane mut NcPlane) -> Self {
148        self.plane = Some(plane);
149        self.flags |= NcVisualFlag::ChildPlane;
150        self
151    }
152
153    /// Unsets the `NcPlane`.
154    ///
155    /// Effect: unsets the plane & the [`CHILDPLANE`] flag.
156    ///
157    /// Default: *`None`* (no plane).
158    ///
159    /// [`CHILDPLANE`]: NcVisualOptions#associatedconstant.CHILDPLANE
160    pub fn no_plane(mut self) -> Self {
161        self.plane = None;
162        self.flags &= !NcVisualFlag::ChildPlane;
163        self
164    }
165
166    /// Sets the `NcScale`.
167    ///
168    /// Default: *[`NcScale::NOSCALE`][crate::NcScale#associatedconstant.NOSCALE]*.
169    pub fn scale(mut self, scale: impl Into<NcScale>) -> Self {
170        self.scale = scale.into();
171        self
172    }
173
174    /// Sets the vertical placement.
175    ///
176    /// Default: *`0`*.
177    ///
178    /// Effect: Sets the *y* coordinate, and unsets the [`VerAligned`] flag.
179    ///
180    /// [`VerAligned`]: NcVisualOptions#associatedconstant.VerAligned
181    pub fn y(mut self, y: i32) -> Self {
182        self.y = y;
183        self.flags &= !NcVisualFlag::VerAligned;
184        self
185    }
186
187    /// Sets the horizontal placement.
188    ///
189    /// Default: *`0`*.
190    ///
191    /// Effect: Sets the *x* coordinate, and unsets the [`HorAligned`] flag.
192    ///
193    /// [`HorAligned`]: NcVisualOptions#associatedconstant.HorAligned
194    pub fn x(mut self, x: i32) -> Self {
195        self.x = x;
196        self.flags &= !NcVisualFlag::HorAligned;
197        self
198    }
199
200    /// Sets the vertical & horizontal placement.
201    ///
202    /// Default: *`(0, 0)`*.
203    ///
204    /// Effect: Sets the *`y` & `x`* coordinates and unsets the [`VerAligned`]
205    /// & [`HorAligned`] flags.
206    ///
207    /// [`VerAligned`]: NcVisualOptions#associatedconstant.VerAligned
208    /// [`HorAligned`]: NcVisualOptions#associatedconstant.HorAligned
209    pub fn yx(mut self, y: i32, x: i32) -> Self {
210        self.y = y;
211        self.x = x;
212        self.flags &= !NcVisualFlag::VerAligned;
213        self.flags &= !NcVisualFlag::HorAligned;
214        self
215    }
216
217    /// Sets the vertical alignment.
218    ///
219    /// Default: *[`NcAlign::Top`]*.
220    ///
221    /// Effect: Sets the *y* alignment and the [`VerAligned`] flag.
222    ///
223    /// [`VerAligned`]: NcVisualFlag#associatedconstant.VerAligned
224    pub fn valign(mut self, valign: impl Into<NcAlign>) -> Self {
225        self.y = valign.into().into();
226        self.flags |= NcVisualFlag::VerAligned;
227        self
228    }
229
230    /// Sets the horizontal alignment.
231    ///
232    /// Default: *[`NcAlign::Left`]*.
233    ///
234    /// Effect: Sets the *`x`* alignment and the [`HorAligned`] flag.
235    ///
236    /// [`HorAligned`]: NcVisualFlag#associatedconstant.HorAligned
237    pub fn halign(mut self, halign: impl Into<NcAlign>) -> Self {
238        self.x = halign.into().into();
239        self.flags |= NcVisualFlag::HorAligned;
240        self
241    }
242
243    /// Sets the vertical & horizontal alignments.
244    ///
245    /// Default: *`(`[`NcAlign::Top`]*`, `*[`NcAlign::Left`]`)`*.
246    ///
247    /// Effect: Sets the *`y` & `x`* alignments and the [`VerAligned`] and
248    /// [`HorAligned`] flags.
249    ///
250    /// [`VerAligned`]: NcVisualFlag#associatedconstant.VerAligned
251    /// [`HorAligned`]: NcVisualFlag#associatedconstant.HorAligned
252    pub fn align(mut self, valign: impl Into<NcAlign>, halign: impl Into<NcAlign>) -> Self {
253        self.y = valign.into().into();
254        self.x = halign.into().into();
255        self.flags |= NcVisualFlag::VerAligned;
256        self.flags |= NcVisualFlag::HorAligned;
257        self
258    }
259
260    /// Choose the `NcBlitter`.
261    ///
262    /// Default: *[`NcBlitter::Default`]*.
263    pub fn blitter(mut self, blitter: impl Into<NcBlitter>) -> Self {
264        self.blitter = blitter.into();
265        self
266    }
267
268    /// Choose [`NcBlitter::Pixel`] for the blitter.
269    pub fn pixel(mut self) -> Self {
270        self.blitter = NcBlitter::Pixel;
271        self
272    }
273
274    /// Choose the color to be considered transparent, or `None`.
275    ///
276    /// Default: *none*.
277    ///
278    /// Efect: (Un)Sets the transparent color, and the [`AddAlpha`] flag.
279    ///
280    /// [`AddAlpha`]: NcVisualFlag#associatedconstant.AddAlpha
281    pub fn transcolor(mut self, color: Option<impl Into<NcRgba>>) -> Self {
282        // if color.is_none() {
283        if let Some(color) = color {
284            self.transcolor = color.into();
285            self.flags |= NcVisualFlag::AddAlpha;
286        } else {
287            self.flags &= !NcVisualFlag::AddAlpha;
288        }
289        self
290    }
291
292    /// Choose whether to use [`NcAlpha::Blend`] with the [`NcVisual`], so that
293    /// the foreground or background colors can be a composite between
294    /// a color and the corresponding colors underneath it.
295    ///
296    /// Default: *false* (blends not).
297    ///
298    /// Effect: Sets the [`Blend`] flag.
299    ///
300    /// [`Blend`]: NcVisualFlag#associatedconstant.Blend
301    /// [`NcAlpha::Blend`]: crate::NcAlpha#associatedconstant.Blend
302    /// [`NcVisual`]: crate::NcVisual
303    pub fn blend(mut self, blend: bool) -> Self {
304        if blend {
305            self.flags |= NcVisualFlag::Blend;
306        } else {
307            self.flags &= !NcVisualFlag::Blend;
308        }
309        self
310    }
311
312    /// Choose between gracefully degrading the blitter, or fail if the choosen
313    /// `NcBlitter` is not supported by the terminal.
314    ///
315    /// Default: *true* (degrades).
316    ///
317    /// Effect: Sets the [`NoDegrade`] flag.
318    ///
319    /// See also: the [*rules of degradation*].
320    ///
321    /// [`NoDegrade`]: NcVisualFlag#associatedconstant.NoDegrade
322    /// [*rules of degradation*]: NcBlitter#degradation
323    pub fn degrade(mut self, degrade: bool) -> Self {
324        if degrade {
325            self.flags &= !NcVisualFlag::NoDegrade;
326        } else {
327            self.flags |= NcVisualFlag::NoDegrade;
328        }
329        self
330    }
331
332    /// Sets the `NoInterpolate` flag.
333    ///
334    /// Default: *true* (interpolates).
335    ///
336    /// [`NoInterpolate`]: NcVisualFlag#associatedconstant.NoInterpolate
337    pub fn interpolate(mut self, interpolate: bool) -> Self {
338        if interpolate {
339            self.flags &= !NcVisualFlag::NoInterpolate;
340        } else {
341            self.flags |= NcVisualFlag::NoInterpolate;
342        }
343        self
344    }
345
346    /// Sets the region to be rendered.
347    ///
348    /// (start_y, start_x, len_y, len_x)
349    pub fn region(mut self, beg_y: u32, beg_x: u32, len_y: u32, len_x: u32) -> Self {
350        self.region_yx_lenyx = Some((beg_y, beg_x, len_y, len_x));
351        self
352    }
353
354    /// Sets the pixel offset within the [`NcCell`][crate::NcCell].
355    ///
356    pub fn cell_offset(mut self, y: u32, x: u32) -> Self {
357        self.cell_offset_yx = Some((y, x));
358        self
359    }
360
361    /// Finishes the building and returns [`NcVisualOptions`].
362    pub fn build(self) -> NcVisualOptions {
363        NcVisualOptions::new(
364            self.plane,
365            self.scale,
366            self.y,
367            self.x,
368            self.region_yx_lenyx,
369            self.cell_offset_yx,
370            self.blitter,
371            self.flags,
372            self.transcolor,
373        )
374    }
375}