Enables to add an optional placeholder value to `NumericEditView`, which will be displayed in a different (darker) color and not returned by `.get_content*()`.
Can be used for having default values in the TUI, but with different handling in the back. Signed-off-by: Christoph Heiss <c.he...@proxmox.com> --- Changes v3 -> v4: * no changes Changes v2 -> v3: * when empty & focused, do not show the placeholder value at all Changes v1 -> v2: * new patch Signed-off-by: Christoph Heiss <c.he...@proxmox.com> --- proxmox-tui-installer/src/views/mod.rs | 66 ++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/proxmox-tui-installer/src/views/mod.rs b/proxmox-tui-installer/src/views/mod.rs index 3244e76..5e5f4fb 100644 --- a/proxmox-tui-installer/src/views/mod.rs +++ b/proxmox-tui-installer/src/views/mod.rs @@ -2,9 +2,10 @@ use std::{net::IpAddr, rc::Rc, str::FromStr}; use cursive::{ event::{Event, EventResult}, + theme::BaseColor, view::{Resizable, ViewWrapper}, views::{EditView, LinearLayout, NamedView, ResizedView, SelectView, TextView}, - Rect, Vec2, View, + Printer, Rect, Vec2, View, }; use proxmox_installer_common::utils::CidrAddress; @@ -24,6 +25,7 @@ pub use timezone::*; pub struct NumericEditView<T> { view: LinearLayout, max_value: Option<T>, + placeholder: Option<T>, max_content_width: Option<usize>, allow_empty: bool, } @@ -36,6 +38,7 @@ impl<T: Copy + ToString + FromStr + PartialOrd> NumericEditView<T> { Self { view, max_value: None, + placeholder: None, max_content_width: None, allow_empty: false, } @@ -54,6 +57,7 @@ impl<T: Copy + ToString + FromStr + PartialOrd> NumericEditView<T> { Self { view, max_value: None, + placeholder: None, max_content_width: None, allow_empty: false, } @@ -84,15 +88,42 @@ impl<T: Copy + ToString + FromStr + PartialOrd> NumericEditView<T> { self } + /// Sets a placeholder value for this view. Implies `allow_empty(true)`. + /// Implies `allow_empty(true)`. + /// + /// # Arguments + /// `placeholder` - The placeholder value to set for this view. + #[allow(unused)] + pub fn placeholder(mut self, placeholder: T) -> Self { + self.placeholder = Some(placeholder); + self.allow_empty(true) + } + + /// Returns the current value of the view. If a placeholder is defined and + /// no value is currently set, the placeholder value is returned. + /// + /// **This should only be called when `allow_empty = false` or a placeholder + /// is set.** pub fn get_content(&self) -> Result<T, <T as FromStr>::Err> { - assert!(!self.allow_empty); - self.inner().get_content().parse() + let content = self.inner().get_content(); + + if content.is_empty() { + if let Some(placeholder) = self.placeholder { + return Ok(placeholder); + } + } + + assert!(!(self.allow_empty && self.placeholder.is_none())); + content.parse() } + /// Returns the current value of the view, or [`None`] if the view is + /// currently empty. pub fn get_content_maybe(&self) -> Option<Result<T, <T as FromStr>::Err>> { let content = self.inner().get_content(); + if !content.is_empty() { - Some(self.inner().get_content().parse()) + Some(content.parse()) } else { None } @@ -157,6 +188,25 @@ impl<T: Copy + ToString + FromStr + PartialOrd> NumericEditView<T> { std::mem::swap(self.inner_mut(), &mut inner); self } + + /// Generic `wrap_draw()` implementation for [`ViewWrapper`]. + /// + /// # Arguments + /// * `printer` - The [`Printer`] to draw to the base view. + fn wrap_draw_inner(&self, printer: &Printer) { + self.view.draw(printer); + + if self.inner().get_content().is_empty() && !printer.focused { + if let Some(placeholder) = self.placeholder { + let placeholder = placeholder.to_string(); + + printer.with_color( + (BaseColor::Blue.light(), BaseColor::Blue.dark()).into(), + |printer| printer.print((0, 0), &placeholder), + ); + } + } + } } pub type FloatEditView = NumericEditView<f64>; @@ -165,6 +215,10 @@ pub type IntegerEditView = NumericEditView<usize>; impl ViewWrapper for FloatEditView { cursive::wrap_impl!(self.view: LinearLayout); + fn wrap_draw(&self, printer: &Printer) { + self.wrap_draw_inner(printer); + } + fn wrap_on_event(&mut self, event: Event) -> EventResult { let original = self.inner_mut().get_content(); @@ -204,6 +258,10 @@ impl FloatEditView { impl ViewWrapper for IntegerEditView { cursive::wrap_impl!(self.view: LinearLayout); + fn wrap_draw(&self, printer: &Printer) { + self.wrap_draw_inner(printer); + } + fn wrap_on_event(&mut self, event: Event) -> EventResult { let original = self.inner_mut().get_content(); -- 2.44.0 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel