use ratatui::layout::Position;
use crate::widgets::InputState;
use crate::widgets::ListState;
use super::InputSelectOption;
#[derive(Debug)]
pub struct InputSelectState
{
pub(crate) label: Option<String>,
pub(crate) input: InputState,
pub(crate) input_options: ListState<InputSelectOption>,
pub(crate) options: Vec<String>,
pub(crate) items_shown: u16,
pub(crate) filter: String,
pub(crate) allow_new_option: bool,
}
impl std::default::Default for InputSelectState
{
fn default() -> Self
{
Self::new()
}
}
impl InputSelectState
{
pub fn new() -> Self
{
Self {
label: None,
input: InputState::new(),
input_options: ListState::new().with_scrollbar(),
options: Vec::new(),
items_shown: 3,
filter: String::new(),
allow_new_option: false,
}
}
pub fn is_valid(&self) -> bool
{
self.options
.contains(
&self
.input
.input(),
)
|| self.allow_new_option
}
pub fn allow_new_option(mut self) -> Self
{
self.allow_new_option = true;
self
}
pub fn with_items_shown(
mut self,
count: u16,
) -> Self
{
self.items_shown = count;
self
}
pub fn with_option<S>(
mut self,
option: S,
) -> Self
where
S: AsRef<str>,
{
self.options
.push(
option
.as_ref()
.to_string(),
);
self.set_filter("");
self
}
pub fn with_options<S>(
mut self,
options: &[S],
) -> Self
where
S: AsRef<str>,
{
let mut options = options
.iter()
.map(
|s| {
s.as_ref()
.to_string()
},
)
.collect::<Vec<_>>();
self.options
.append(&mut options);
self.set_filter("");
self
}
pub fn input(&self) -> Option<String>
{
let value = self
.input
.input();
Some(value.clone())
}
pub fn set_label<S>(
&mut self,
label: S,
) where
S: AsRef<str>,
{
self.label = Some(
label
.as_ref()
.to_string(),
);
}
pub fn remove_label(&mut self)
{
self.label
.take();
}
pub fn with_label<S>(
mut self,
label: S,
) -> Self
where
S: AsRef<str>,
{
self.set_label(label);
self
}
pub fn set<S>(
&mut self,
value: S,
) where
S: AsRef<str>,
{
self.input
.set(value);
self.set_filter("");
}
pub fn reset_cursor(&mut self)
{
self.input
.reset_cursor();
}
pub fn with_default<S>(
mut self,
value: S,
) -> Self
where
S: AsRef<str>,
{
self.set(value);
self
}
pub fn cursor(&self) -> Position
{
self.input
.cursor()
}
pub fn clear(&mut self)
{
self.input
.clear();
}
pub fn set_filter<S>(
&mut self,
filter: S,
) where
S: AsRef<str>,
{
self.filter = filter
.as_ref()
.to_string();
self.input_options
.clear();
let filtered = self
.options
.iter()
.filter(|o| o.starts_with(filter.as_ref()));
for item in filtered
{
self.input_options
.add_item(InputSelectOption::new(item));
}
}
}