use crate::_private::NonExhaustive;
use format_num_pattern::NumberFmtError;
use pure_rust_locales::Locale;
use rat_focus::{FocusFlag, HasFocusFlag};
use rat_input::masked_input::MaskedInputStyle;
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::prelude::Style;
use ratatui::widgets::{Block, StatefulWidget, StatefulWidgetRef};
use std::fmt::{Debug, Display, LowerExp};
use std::ops::Range;
use std::str::FromStr;
use crate::event::{FocusKeys, HandleEvent, MouseOnly};
pub use rat_input::date_input::ConvenientKeys;
use rat_input::event::{ReadOnly, TextOutcome};
#[derive(Debug, Default, Clone)]
pub struct RNumberInput<'a> {
widget: rat_input::number_input::NumberInput<'a>,
}
#[derive(Debug, Clone)]
pub struct RNumberInputState {
pub widget: rat_input::number_input::NumberInputState,
pub non_exhaustive: NonExhaustive,
}
impl<'a> RNumberInput<'a> {
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn show_compact(mut self, show_compact: bool) -> Self {
self.widget = self.widget.show_compact(show_compact);
self
}
#[inline]
pub fn styles(mut self, style: MaskedInputStyle) -> Self {
self.widget = self.widget.styles(style);
self
}
#[inline]
pub fn style(mut self, style: impl Into<Style>) -> Self {
self.widget = self.widget.style(style);
self
}
#[inline]
pub fn focus_style(mut self, style: impl Into<Style>) -> Self {
self.widget = self.widget.focus_style(style);
self
}
#[inline]
pub fn select_style(mut self, style: impl Into<Style>) -> Self {
self.widget = self.widget.select_style(style);
self
}
#[inline]
pub fn invalid_style(mut self, style: impl Into<Style>) -> Self {
self.widget = self.widget.invalid_style(style);
self
}
#[inline]
pub fn block(mut self, block: Block<'a>) -> Self {
self.widget = self.widget.block(block);
self
}
}
impl<'a> StatefulWidgetRef for RNumberInput<'a> {
type State = RNumberInputState;
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
self.widget.render_ref(area, buf, &mut state.widget);
}
}
impl<'a> StatefulWidget for RNumberInput<'a> {
type State = RNumberInputState;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
self.widget.render(area, buf, &mut state.widget)
}
}
impl Default for RNumberInputState {
fn default() -> Self {
Self {
widget: Default::default(),
non_exhaustive: NonExhaustive,
}
}
}
impl RNumberInputState {
pub fn new<S: AsRef<str>>(pattern: S) -> Result<Self, NumberFmtError> {
Ok(Self {
widget: rat_input::number_input::NumberInputState::new(pattern)?,
..Default::default()
})
}
#[inline]
pub fn new_loc<S: AsRef<str>>(pattern: S, locale: Locale) -> Result<Self, NumberFmtError> {
Ok(Self {
widget: rat_input::number_input::NumberInputState::new_loc(pattern, locale)?,
..Default::default()
})
}
#[inline]
pub fn format(&self) -> &str {
self.widget.format()
}
#[inline]
pub fn locale(&self) -> Locale {
self.widget.locale()
}
#[inline]
pub fn set_format<S: AsRef<str>>(&mut self, pattern: S) -> Result<(), NumberFmtError> {
self.widget.set_format(pattern)
}
#[inline]
pub fn set_format_loc<S: AsRef<str>>(
&mut self,
pattern: S,
locale: Locale,
) -> Result<(), NumberFmtError> {
self.widget.set_format_loc(pattern, locale)
}
#[inline]
pub fn set_invalid(&mut self, invalid: bool) {
self.widget.set_invalid(invalid);
}
#[inline]
pub fn get_invalid(&self) -> bool {
self.widget.get_invalid()
}
#[inline]
pub fn clear(&mut self) {
self.widget.clear();
}
#[inline]
pub fn offset(&self) -> usize {
self.widget.offset()
}
#[inline]
pub fn set_offset(&mut self, offset: usize) {
self.widget.set_offset(offset)
}
#[inline]
pub fn cursor(&self) -> usize {
self.widget.cursor()
}
#[inline]
pub fn set_cursor(&mut self, cursor: usize, extend_selection: bool) -> bool {
self.widget.set_cursor(cursor, extend_selection)
}
#[inline]
pub fn set_default_cursor(&mut self) {
self.widget.set_default_cursor()
}
#[inline]
pub fn anchor(&self) -> usize {
self.widget.anchor()
}
#[inline]
pub fn default_value(&self) -> String {
self.widget.default_value()
}
#[inline]
pub fn value<T: FromStr>(&self) -> Result<T, NumberFmtError> {
self.widget.value()
}
#[inline]
pub fn set_value<T: LowerExp + Display + Debug>(
&mut self,
number: T,
) -> Result<(), NumberFmtError> {
self.widget.set_value(number)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.widget.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.widget.len()
}
#[inline]
pub fn has_selection(&self) -> bool {
self.widget.has_selection()
}
#[inline]
pub fn selection(&self) -> Range<usize> {
self.widget.selection()
}
#[inline]
pub fn set_selection(&mut self, anchor: usize, cursor: usize) -> bool {
self.widget.set_selection(anchor, cursor)
}
#[inline]
pub fn select_all(&mut self) {
self.widget.select_all();
}
#[inline]
pub fn selected_value(&self) -> &str {
self.widget.selected_value()
}
#[inline]
pub fn insert_char(&mut self, c: char) -> bool {
self.widget.insert_char(c)
}
#[inline]
pub fn delete_range(&mut self, range: Range<usize>) -> bool {
self.widget.delete_range(range)
}
#[inline]
pub fn delete_next_word(&mut self) -> bool {
self.widget.delete_next_word()
}
#[inline]
pub fn delete_prev_word(&mut self) -> bool {
self.widget.delete_prev_word()
}
#[inline]
pub fn delete_prev_char(&mut self) -> bool {
self.widget.delete_prev_char()
}
#[inline]
pub fn delete_next_char(&mut self) -> bool {
self.widget.delete_next_char()
}
#[inline]
pub fn move_to_next_word(&mut self, extend_selection: bool) -> bool {
self.widget.move_to_next_word(extend_selection)
}
#[inline]
pub fn move_to_prev_word(&mut self, extend_selection: bool) -> bool {
self.widget.move_to_next_word(extend_selection)
}
#[inline]
pub fn move_to_next(&mut self, extend_selection: bool) -> bool {
self.widget.move_to_next(extend_selection)
}
#[inline]
pub fn move_to_prev(&mut self, extend_selection: bool) -> bool {
self.widget.move_to_prev(extend_selection)
}
#[inline]
pub fn move_to_line_start(&mut self, extend_selection: bool) -> bool {
self.widget.move_to_line_start(extend_selection)
}
#[inline]
pub fn move_to_line_end(&mut self, extend_selection: bool) -> bool {
self.widget.move_to_line_end(extend_selection)
}
pub fn to_screen_col(&self, pos: usize) -> Option<u16> {
self.widget.to_screen_col(pos)
}
pub fn from_screen_col(&self, x: usize) -> Option<usize> {
self.widget.from_screen_col(x)
}
#[inline]
pub fn set_screen_cursor(&mut self, cursor: isize, extend_selection: bool) -> bool {
self.widget.set_screen_cursor(cursor, extend_selection)
}
#[inline]
pub fn screen_cursor(&self) -> Option<(u16, u16)> {
if self.is_focused() {
self.widget.screen_cursor()
} else {
None
}
}
}
impl HasFocusFlag for RNumberInputState {
#[inline]
fn focus(&self) -> &FocusFlag {
&self.widget.widget.focus
}
#[inline]
fn area(&self) -> Rect {
self.widget.widget.area
}
}
impl HandleEvent<crossterm::event::Event, FocusKeys, TextOutcome> for RNumberInputState {
fn handle(&mut self, event: &crossterm::event::Event, _keymap: FocusKeys) -> TextOutcome {
if self.is_focused() {
self.widget.handle(event, FocusKeys)
} else {
self.widget.handle(event, MouseOnly)
}
}
}
impl HandleEvent<crossterm::event::Event, ReadOnly, TextOutcome> for RNumberInputState {
fn handle(&mut self, event: &crossterm::event::Event, _keymap: ReadOnly) -> TextOutcome {
if self.is_focused() {
self.widget.handle(event, ReadOnly)
} else {
self.widget.handle(event, MouseOnly)
}
}
}
impl HandleEvent<crossterm::event::Event, MouseOnly, TextOutcome> for RNumberInputState {
fn handle(&mut self, event: &crossterm::event::Event, _keymap: MouseOnly) -> TextOutcome {
self.widget.handle(event, MouseOnly)
}
}