libnotcurses_sys/plane/options/
builder.rs

1//!
2
3use core::ptr::{null, null_mut};
4
5use crate::{c_api, NcAlign, NcPlaneFlag, NcPlaneOptions, NcResizeCb};
6
7/// Builder object for [`NcPlaneOptions`].
8///
9/// Can be constructed by calling [`NcPlaneOptions::builder()`].
10///
11/// By [*default*] it has the [`Marginalized`] flag already set, alongside `(0, 0)`
12/// margins, so that it automatically fills the parent plane.
13///
14/// [*default*]: NcPlaneOptionsBuilder#method.default
15/// [`NcPlaneOptions::builder()`]: NcPlaneOptions#method.builder
16/// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
17#[derive(Clone)]
18pub struct NcPlaneOptionsBuilder {
19    pub(crate) y: i32,
20    pub(crate) x: i32,
21    pub(crate) rows: u32,
22    pub(crate) cols: u32,
23    // TODO:
24    // The void* ‘userptr’ can be retrieved (and reset) later.
25    // pub(crate) userptr: mut* c_void,
26    //
27    // A ‘name’ can be set, used in debugging.
28    // pub(crate) name: String,
29    pub(crate) resizecb: Option<NcResizeCb>,
30    pub(crate) flags: u64,
31    pub(crate) margin_b: u32,
32    pub(crate) margin_r: u32,
33}
34
35mod core_impls {
36    use core::fmt;
37
38    #[cfg(not(feature = "std"))]
39    use alloc::string::String;
40
41    use super::{NcPlaneFlag, NcPlaneOptions, NcPlaneOptionsBuilder};
42
43    //
44    impl From<NcPlaneOptionsBuilder> for NcPlaneOptions {
45        fn from(builder: NcPlaneOptionsBuilder) -> NcPlaneOptions {
46            builder.build()
47        }
48    }
49    impl From<&NcPlaneOptionsBuilder> for NcPlaneOptions {
50        fn from(builder: &NcPlaneOptionsBuilder) -> Self {
51            builder.clone().build()
52        }
53    }
54    impl From<&mut NcPlaneOptionsBuilder> for NcPlaneOptions {
55        fn from(builder: &mut NcPlaneOptionsBuilder) -> Self {
56            builder.clone().build()
57        }
58    }
59    //
60    impl From<NcPlaneOptions> for NcPlaneOptionsBuilder {
61        fn from(options: NcPlaneOptions) -> NcPlaneOptionsBuilder {
62            Self::from_options(&options)
63        }
64    }
65    impl From<&NcPlaneOptions> for NcPlaneOptionsBuilder {
66        fn from(options: &NcPlaneOptions) -> Self {
67            Self::from_options(options)
68        }
69    }
70    impl From<&mut NcPlaneOptions> for NcPlaneOptionsBuilder {
71        fn from(options: &mut NcPlaneOptions) -> Self {
72            Self::from_options(options)
73        }
74    }
75
76    impl Default for NcPlaneOptionsBuilder {
77        /// New `NcPlaneOptionsBuilder` with the [`Marginalized`] flag set.
78        ///
79        /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
80        fn default() -> Self {
81            Self {
82                y: 0,
83                x: 0,
84                rows: 0,
85                cols: 0,
86                resizecb: None,
87                flags: NcPlaneFlag::Marginalized.into(),
88                margin_b: 0,
89                margin_r: 0,
90            }
91        }
92    }
93
94    impl fmt::Debug for NcPlaneOptionsBuilder {
95        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96            let resizecb_str =
97                if self.resizecb.is_some() { String::from("Some") } else { String::from("None") };
98            f.debug_struct("NcPlaneOptionsBuilder")
99                .field("y", &self.y)
100                .field("x", &self.x)
101                .field("rows", &self.rows)
102                .field("cols", &self.cols)
103                .field("resizecb", &resizecb_str)
104                .field("flags", &self.flags)
105                .field("margin_b", &self.margin_b)
106                .field("margin_r", &self.margin_r)
107                .finish()
108        }
109    }
110}
111
112/// # Constructors
113impl NcPlaneOptionsBuilder {
114    /// New `NcPlaneOptionsBuilder` with the [`Marginalized`] flag set.
115    ///
116    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
117    pub fn new() -> Self {
118        Self::default()
119    }
120
121    /// New builder from pre-existing options.
122    pub fn from_options(options: &NcPlaneOptions) -> Self {
123        let mut builder = Self::default(); // Marginalized by default
124
125        if options.is_marginalized() {
126            builder = builder.margins(options.margin_b, options.margin_r);
127        } else {
128            builder = builder.rows_cols(options.rows, options.cols);
129        }
130
131        if options.is_fixed() {
132            builder = builder.fixed(true);
133        }
134
135        if options.resizecb.is_some() {
136            builder = builder.resizecb(c_api::ncresizecb_to_rust(options.resizecb));
137        }
138
139        if options.is_autogrow() {
140            builder = builder.autogrow(true);
141        }
142        if options.is_vscroll() {
143            builder = builder.vscroll(true);
144        }
145
146        if options.is_veraligned() {
147            builder = builder.valign(options.y);
148        } else {
149            builder = builder.y(options.y);
150        }
151        if options.is_horaligned() {
152            builder = builder.halign(options.x);
153        } else {
154            builder = builder.x(options.x);
155        }
156
157        // TODO: name, userptr
158
159        builder
160    }
161
162    /// Finishes the building and returns [`NcPlaneOptions`].
163    pub fn build(self) -> NcPlaneOptions {
164        NcPlaneOptions {
165            y: self.y,
166            x: self.x,
167            rows: self.rows,
168            cols: self.cols,
169            userptr: null_mut(), // TODO
170            name: null(),        // TODO
171            resizecb: c_api::ncresizecb_to_c(self.resizecb),
172            flags: self.flags,
173            margin_b: self.margin_b,
174            margin_r: self.margin_r,
175        }
176    }
177}
178
179/// # Methods (chainable)
180impl NcPlaneOptionsBuilder {
181    /// Sets the vertical placement relative to parent plane.
182    ///
183    /// Default: *`0`*.
184    ///
185    /// Effect: Sets the *y* coordinate and unsets the [`VerAligned`] flag.
186    ///
187    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
188    pub fn y(mut self, y: i32) -> Self {
189        self.y = y;
190        self.flags &= !NcPlaneFlag::VerAligned;
191        self
192    }
193
194    /// Sets the horizontal placement relative to parent plane.
195    ///
196    /// Default: *`0`*.
197    ///
198    /// Effect: Sets the *x* coordinate and unsets the [`HorAligned`] flag.
199    ///
200    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
201    pub fn x(mut self, x: i32) -> Self {
202        self.x = x;
203        self.flags &= !NcPlaneFlag::HorAligned;
204        self
205    }
206
207    /// Sets the vertical & horizontal placement relative to parent plane.
208    ///
209    /// Effect: Sets the *`x`* & *`y`* coordinates and unsets the [`VERALIGNED`]
210    /// and [`HORALIGNED`] flags.
211    ///
212    /// Default: *`(0, 0)`*.
213    ///
214    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
215    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
216    pub fn yx(mut self, y: i32, x: i32) -> Self {
217        self.y = y;
218        self.x = x;
219        self.flags &= !NcPlaneFlag::VerAligned;
220        self.flags &= !NcPlaneFlag::HorAligned;
221        self
222    }
223
224    /// Sets the vertical alignment.
225    ///
226    /// Default: *[`NcAlign::Top`]*.
227    ///
228    /// Effect: Sets the *`v`* alignment and the [`VerAligned`] flag.
229    ///
230    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
231    pub fn valign(mut self, v: impl Into<NcAlign>) -> Self {
232        self.y = v.into().into();
233        self.flags |= NcPlaneFlag::VerAligned;
234        self
235    }
236
237    /// Sets the horizontal alignment.
238    ///
239    /// Default: *[`NcAlign::Left`]*.
240    ///
241    /// Effect: Sets the *`h`* alignment and the [`HorAligned`] flag.
242    ///
243    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
244    pub fn halign(mut self, h: impl Into<NcAlign>) -> Self {
245        self.x = h.into().into();
246        self.flags |= NcPlaneFlag::HorAligned;
247        self
248    }
249
250    /// Sets the vertical & horizontal alignment.
251    ///
252    /// Default: *`(`[`NcAlign::Top`], [`NcAlign::Left`]`)`*.
253    ///
254    /// Effect: Sets the *`v` & `h`* alignments and the [`VerAligned`]
255    /// & [`HorAligned`] flags.
256    ///
257    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
258    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
259    pub fn align(mut self, v: impl Into<NcAlign>, h: impl Into<NcAlign>) -> Self {
260        self.y = v.into().into();
261        self.x = h.into().into();
262        self.flags |= NcPlaneFlag::VerAligned;
263        self.flags |= NcPlaneFlag::HorAligned;
264        self
265    }
266
267    /// Sets the number of rows for the plane.
268    ///
269    /// Must be >0 when not using `margins`.
270    ///
271    /// Default: *`0`*.
272    ///
273    /// Effect: sets the *rows* field and unsets the [`Marginalized`] flag.
274    ///
275    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
276    pub fn rows(mut self, rows: u32) -> Self {
277        self.rows = rows;
278        self.flags &= !NcPlaneFlag::Marginalized;
279        self
280    }
281
282    /// Sets the number of columns for the plane.
283    ///
284    /// Must be >0 when not using `margins`.
285    ///
286    /// Default: *`0`*.
287    ///
288    /// Effect: sets the *cols* field and unsets the [`Marginalized`] flag.
289    ///
290    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
291    pub fn cols(mut self, cols: u32) -> Self {
292        self.cols = cols;
293        self.flags &= !NcPlaneFlag::Marginalized;
294        self
295    }
296
297    /// Sets the number of rows & columns for the plane.
298    ///
299    /// Must be >0 when not using `margins`.
300    ///
301    /// Default: *`(0, 0)`*.
302    ///
303    /// Effect: sets the *rows* & *cols* fields and unsets the [`Marginalized`]
304    /// flag.
305    ///
306    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
307    pub fn rows_cols(mut self, rows: u32, cols: u32) -> Self {
308        self.rows = rows;
309        self.cols = cols;
310        self.flags &= !NcPlaneFlag::Marginalized;
311        self
312    }
313
314    /// Sets the bottom & right margins.
315    ///
316    /// Default: *`(0, 0)`*.
317    ///
318    /// Effect: sets the `margin_b` & `margin_r` fields and the [`Marginalized`]
319    /// flag.
320    ///
321    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
322    pub fn margins(mut self, bottom: u32, right: u32) -> Self {
323        self.margin_b = bottom;
324        self.margin_r = right;
325        self.flags |= NcPlaneFlag::Marginalized;
326        self
327    }
328
329    /// If `true`, the plane will **not** scroll with the parent.
330    ///
331    /// Default: *false* (scrolls with the parent).
332    ///
333    /// Effect: (un)sets the [`Fixed`] flag.
334    ///
335    /// [`Fixed`]: NcPlaneFlag#associatedconstant.Fixed
336    pub fn fixed(mut self, fixed: bool) -> Self {
337        if fixed {
338            self.flags |= NcPlaneFlag::Fixed;
339        } else {
340            self.flags &= !NcPlaneFlag::Fixed;
341        }
342        self
343    }
344
345    /// If `true`, the plane will scroll vertically to accommodate output.
346    ///
347    /// Setting this flag is equivalent to immediately calling
348    /// [`set_scrolling(true)`] following `NcPlane` creation.
349    ///
350    /// Default: *false*.
351    ///
352    /// Effect: (un)sets the [`VScroll`] flag.
353    ///
354    /// See also: [`AutoGrow`].
355    ///
356    /// [`set_scrolling(true)`]: crate::NcPlane#method.set_scrolling
357    /// [`AutoGrow`]: NcPlaneFlag#associatedconstant.AutoGrow
358    /// [`VScroll`]: NcPlaneFlag#associatedconstant.VScroll
359    pub fn vscroll(mut self, vscroll: bool) -> Self {
360        if vscroll {
361            self.flags |= NcPlaneFlag::VScroll;
362        } else {
363            self.flags &= !NcPlaneFlag::VScroll;
364        }
365        self
366    }
367
368    /// If `true`, the plane will grow automatically.
369    ///
370    /// Default: *false*.
371    ///
372    /// Effect: (un)sets the [`AutoGrow`] flag.
373    ///
374    /// Note that just setting `AutoGrow` makes the `NcPlane` grow to the right,
375    /// and setting `AutoGrow` + [`VScroll`] makes the `NcPlane` grow down.
376    ///
377    /// [`AutoGrow`]: NcPlaneFlag#associatedconstant.AutoGrow
378    /// [`VScroll`]: NcPlaneFlag#associatedconstant.VScroll
379    pub fn autogrow(mut self, autogrow: bool) -> Self {
380        if autogrow {
381            self.flags |= NcPlaneFlag::AutoGrow;
382        } else {
383            self.flags &= !NcPlaneFlag::AutoGrow;
384        }
385        self
386    }
387
388    /// (Un)Sets the resize callback.
389    ///
390    /// Default: *None*.
391    pub fn resizecb(mut self, callback: Option<NcResizeCb>) -> Self {
392        self.resizecb = callback;
393        self
394    }
395}
396
397/// # Methods (setable)
398impl NcPlaneOptionsBuilder {
399    /// Sets the vertical placement relative to parent plane.
400    ///
401    /// Default: *`0`*.
402    ///
403    /// Effect: Sets the *`y`* coordinate and unsets the [`VerAligned`] flag.
404    ///
405    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
406    pub fn set_y(&mut self, y: i32) {
407        self.y = y;
408        self.flags &= !NcPlaneFlag::VerAligned;
409    }
410
411    /// Sets the horizontal placement relative to parent plane.
412    ///
413    /// Default: *`0`*.
414    ///
415    /// Effect: Sets the *`x`* coordinate and unsets the [`HorAligned`] flag.
416    ///
417    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
418    pub fn set_x(&mut self, x: i32) {
419        self.x = x;
420        self.flags &= !NcPlaneFlag::HorAligned;
421    }
422
423    /// Sets the vertical & horizontal placement relative to parent plane.
424    ///
425    /// Effect: Sets the *`x`* & *`y`* coordinates and unsets the [`VERALIGNED`]
426    /// and [`HORALIGNED`] flags.
427    ///
428    /// Default: *`(0, 0)`*.
429    ///
430    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
431    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
432    pub fn set_yx(&mut self, y: i32, x: i32) {
433        self.y = y;
434        self.x = x;
435        self.flags &= !NcPlaneFlag::VerAligned;
436        self.flags &= !NcPlaneFlag::HorAligned;
437    }
438
439    /// Sets the vertical alignment.
440    ///
441    /// Default: *[`NcAlign::Top`]*.
442    ///
443    /// Effect: Sets the *`y`* alignment and the [`VerAligned`] flag.
444    ///
445    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
446    pub fn set_valign(&mut self, v: impl Into<NcAlign>) {
447        self.y = v.into().into();
448        self.flags |= NcPlaneFlag::VerAligned;
449    }
450
451    /// Sets the horizontal alignment.
452    ///
453    /// Default: *[`NcAlign::Left`]*.
454    ///
455    /// Effect: Sets the *`h`* alignment and the [`HorAligned`] flag.
456    ///
457    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
458    pub fn set_halign(&mut self, h: impl Into<NcAlign>) {
459        self.x = h.into().into();
460        self.flags |= NcPlaneFlag::HorAligned;
461    }
462
463    /// Sets the vertical & horizontal alignment.
464    ///
465    /// Default: *`(`[`NcAlign::Top`], [`NcAlign::Left`]`)`*.
466    ///
467    /// Effect: Sets the *`v` & `h`* alignments and the [`VerAligned`]
468    /// & [`HorAligned`] flags.
469    ///
470    /// [`VerAligned`]: NcPlaneFlag#associatedconstant.VerAligned
471    /// [`HorAligned`]: NcPlaneFlag#associatedconstant.HorAligned
472    pub fn set_align(&mut self, v: impl Into<NcAlign>, h: impl Into<NcAlign>) {
473        self.y = v.into().into();
474        self.x = h.into().into();
475        self.flags |= NcPlaneFlag::VerAligned;
476        self.flags |= NcPlaneFlag::HorAligned;
477    }
478
479    /// Sets the number of rows for the plane.
480    ///
481    /// Must be >0 when not using `margins`.
482    ///
483    /// Default: *`0`*.
484    ///
485    /// Effect: sets the *rows* field and unsets the [`Marginalized`] flag.
486    ///
487    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
488    pub fn set_rows(&mut self, rows: u32) {
489        self.rows = rows;
490        self.flags &= !NcPlaneFlag::Marginalized;
491    }
492
493    /// Sets the number of columns for the plane.
494    ///
495    /// Must be >0 when not using `margins`.
496    ///
497    /// Default: *`0`*.
498    ///
499    /// Effect: sets the *cols* field and unsets the [`Marginalized`] flag.
500    ///
501    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
502    pub fn set_cols(&mut self, cols: u32) {
503        self.cols = cols;
504        self.flags &= !NcPlaneFlag::Marginalized;
505    }
506
507    /// Sets the number of rows & columns for the plane.
508    ///
509    /// Must be >0 when not using `margins`.
510    ///
511    /// Default: *`(0, 0)`*.
512    ///
513    /// Effect: sets the *rows* & *cols* fields and unsets the [`Marginalized`]
514    /// flag.
515    ///
516    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
517    pub fn set_rows_cols(&mut self, rows: u32, cols: u32) {
518        self.rows = rows;
519        self.cols = cols;
520        self.flags &= !NcPlaneFlag::Marginalized;
521    }
522
523    /// Sets the bottom & right margins.
524    ///
525    /// Default: *`(0, 0)`*.
526    ///
527    /// Effect: sets the `margin_b` & `margin_r` fields and the [`Marginalized`]
528    /// flag.
529    ///
530    /// [`Marginalized`]: NcPlaneFlag#associatedconstant.Marginalized
531    pub fn set_margins(&mut self, bottom: u32, right: u32) {
532        self.margin_b = bottom;
533        self.margin_r = right;
534        self.flags |= NcPlaneFlag::Marginalized;
535    }
536
537    /// If `true`, the plane will **not** scroll with the parent.
538    ///
539    /// Default: *false* (scrolls with the parent).
540    ///
541    /// Effect: (un)sets the [`Fixed`] flag.
542    ///
543    /// [`Fixed`]: NcPlaneFlag#associatedconstant.Fixed
544    pub fn set_fixed(&mut self, fixed: bool) {
545        if fixed {
546            self.flags |= NcPlaneFlag::Fixed;
547        } else {
548            self.flags &= !NcPlaneFlag::Fixed;
549        }
550    }
551
552    /// If `true`, the plane will scroll vertically to accommodate output.
553    ///
554    /// Setting this flag is equivalent to immediately calling
555    /// [`set_scrolling(true)`] following `NcPlane` creation.
556    ///
557    /// Default: *false*.
558    ///
559    /// Effect: (un)sets the [`VScroll`] flag.
560    ///
561    /// See also: [`AutoGrow`].
562    ///
563    /// [`set_scrolling(true)`]: crate::NcPlane#method.set_scrolling
564    /// [`AutoGrow`]: NcPlaneFlag#associatedconstant.AutoGrow
565    /// [`VScroll`]: NcPlaneFlag#associatedconstant.VScroll
566    pub fn set_vscroll(&mut self, vscroll: bool) {
567        if vscroll {
568            self.flags |= NcPlaneFlag::VScroll;
569        } else {
570            self.flags &= !NcPlaneFlag::VScroll;
571        }
572    }
573
574    /// If `true`, the plane will grow automatically.
575    ///
576    /// Default: *false*.
577    ///
578    /// Effect: (un)sets the [`AutoGrow`] flag.
579    ///
580    /// Note that just setting `AutoGrow` makes the `NcPlane` grow to the right,
581    /// and setting `AutoGrow` + [`VScroll`] makes the `NcPlane` grow down.
582    ///
583    /// [`AutoGrow`]: NcPlaneFlag#associatedconstant.AutoGrow
584    /// [`VScroll`]: NcPlaneFlag#associatedconstant.VScroll
585    pub fn set_autogrow(&mut self, autogrow: bool) {
586        if autogrow {
587            self.flags |= NcPlaneFlag::AutoGrow;
588        } else {
589            self.flags &= !NcPlaneFlag::AutoGrow;
590        }
591    }
592
593    /// (Un)Sets the resize callback.
594    ///
595    /// Default: *None*.
596    pub fn set_resizecb(&mut self, callback: Option<NcResizeCb>) {
597        self.resizecb = callback;
598    }
599}