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}