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}