use crate::component::{Action, Component, ComponentId, Message, MessageExt};
use crate::key::{Key, KeyWithModifiers};
use crate::node::Node;
use crate::node::{DivStyles, RichText, Text};
use crate::style::{
Border, BorderEdges, BorderStyle, Color, Dimension, Overflow, Position, Spacing, Style,
TextStyle, TextWrap,
};
use crate::{Context, Div};
use std::any::Any;
#[derive(Debug, Clone)]
pub enum TextInputMsg {
Focused,
Blurred,
CharInput(char),
Backspace,
Delete,
DeleteWordBackward,
DeleteWordForward,
DeleteToLineStart,
DeleteToLineEnd,
CursorLeft,
CursorRight,
CursorHome,
CursorEnd,
CursorWordLeft,
CursorWordRight,
SelectLeft,
SelectRight,
SelectAll,
SelectWord,
ClearSelection,
Cut,
Copy,
Paste(String),
}
#[derive(Debug, Clone, Default)]
pub struct TextInputState {
pub focused: bool,
pub content: String,
pub cursor_position: usize,
pub selection_start: Option<usize>,
pub selection_end: Option<usize>,
}
#[derive(Clone)]
pub struct TextInput {
id: Option<ComponentId>,
placeholder: Option<String>,
placeholder_style: Option<TextStyle>,
content_style: Option<TextStyle>,
cursor_style: Option<TextStyle>,
selection_style: Option<TextStyle>,
styles: DivStyles,
focusable: bool,
wrap: Option<TextWrap>,
password_mode: bool,
}
impl TextInput {
fn delete_selection(&self, state: &mut TextInputState) {
if let (Some(start), Some(end)) = (state.selection_start, state.selection_end) {
let (start, end) = if start < end {
(start, end)
} else {
(end, start)
};
let mut chars: Vec<char> = state.content.chars().collect();
chars.drain(start..end);
state.content = chars.into_iter().collect();
state.cursor_position = start;
state.selection_start = None;
state.selection_end = None;
}
}
fn find_word_boundary_left(&self, text: &str, pos: usize) -> usize {
let chars: Vec<char> = text.chars().collect();
if pos == 0 {
return 0;
}
let mut new_pos = pos - 1;
while new_pos > 0 && chars[new_pos].is_whitespace() {
new_pos -= 1;
}
while new_pos > 0
&& !chars[new_pos - 1].is_whitespace()
&& !chars[new_pos - 1].is_ascii_punctuation()
{
new_pos -= 1;
}
new_pos
}
fn find_word_boundary_right(&self, text: &str, pos: usize) -> usize {
let chars: Vec<char> = text.chars().collect();
let len = chars.len();
if pos >= len {
return len;
}
let mut new_pos = pos;
while new_pos < len
&& !chars[new_pos].is_whitespace()
&& !chars[new_pos].is_ascii_punctuation()
{
new_pos += 1;
}
while new_pos < len
&& (chars[new_pos].is_whitespace() || chars[new_pos].is_ascii_punctuation())
{
new_pos += 1;
}
new_pos
}
fn delete_word_backward(&self, state: &mut TextInputState) {
if state.cursor_position == 0 {
return;
}
let new_pos = self.find_word_boundary_left(&state.content, state.cursor_position);
let mut chars: Vec<char> = state.content.chars().collect();
chars.drain(new_pos..state.cursor_position);
state.content = chars.into_iter().collect();
state.cursor_position = new_pos;
}
fn delete_word_forward(&self, state: &mut TextInputState) {
let char_count = state.content.chars().count();
if state.cursor_position >= char_count {
return;
}
let new_pos = self.find_word_boundary_right(&state.content, state.cursor_position);
let mut chars: Vec<char> = state.content.chars().collect();
chars.drain(state.cursor_position..new_pos);
state.content = chars.into_iter().collect();
}
fn delete_to_line_start(&self, state: &mut TextInputState) {
if state.cursor_position == 0 {
return;
}
let mut chars: Vec<char> = state.content.chars().collect();
chars.drain(0..state.cursor_position);
state.content = chars.into_iter().collect();
state.cursor_position = 0;
}
fn delete_to_line_end(&self, state: &mut TextInputState) {
let char_count = state.content.chars().count();
if state.cursor_position >= char_count {
return;
}
let mut chars: Vec<char> = state.content.chars().collect();
chars.drain(state.cursor_position..);
state.content = chars.into_iter().collect();
}
fn default_style() -> Style {
Style {
padding: Some(Spacing::horizontal(1)),
width: Some(Dimension::Fixed(30)),
height: Some(Dimension::Fixed(3)),
border: Some(Border {
enabled: true,
style: BorderStyle::Single,
color: Color::Cyan,
edges: BorderEdges::ALL,
}),
overflow: Some(Overflow::Hidden),
..Default::default()
}
}
fn default_placeholder_style() -> TextStyle {
TextStyle {
color: Some(Color::BrightBlack), background: None,
bold: None,
italic: Some(true), underline: None,
strikethrough: None,
wrap: None,
}
}
fn default_content_style() -> TextStyle {
TextStyle {
color: Some(Color::White), background: None,
bold: None,
italic: None,
underline: None,
strikethrough: None,
wrap: None,
}
}
fn default_cursor_style() -> TextStyle {
TextStyle {
color: Some(Color::Black),
background: Some(Color::White),
bold: None,
italic: None,
underline: None,
strikethrough: None,
wrap: None,
}
}
fn default_selection_style() -> TextStyle {
TextStyle {
color: Some(Color::White),
background: Some(Color::Blue),
bold: None,
italic: None,
underline: None,
strikethrough: None,
wrap: None,
}
}
pub fn new() -> Self {
Self {
id: None,
placeholder: None,
placeholder_style: Some(Self::default_placeholder_style()),
content_style: Some(Self::default_content_style()),
cursor_style: Some(Self::default_cursor_style()),
selection_style: Some(Self::default_selection_style()),
styles: DivStyles {
base: Some(Self::default_style()),
focus: None,
hover: None,
},
focusable: true, wrap: Some(TextWrap::WordBreak), password_mode: false, }
}
pub fn placeholder(mut self, text: impl Into<String>) -> Self {
self.placeholder = Some(text.into());
self
}
pub fn focusable(mut self, focusable: bool) -> Self {
self.focusable = focusable;
self
}
pub fn password(mut self, password: bool) -> Self {
self.password_mode = password;
self
}
fn update(&self, ctx: &Context, msg: Box<dyn Message>, _topic: Option<&str>) -> Action {
if let Some(msg) = msg.downcast::<TextInputMsg>() {
let mut state = ctx.get_state::<TextInputState>();
match msg {
TextInputMsg::Focused => {
state.focused = true;
state.cursor_position = state.content.chars().count();
}
TextInputMsg::Blurred => {
state.focused = false;
state.selection_start = None;
state.selection_end = None;
}
TextInputMsg::CharInput(ch) => {
if state.focused {
if state.selection_start.is_some() {
self.delete_selection(&mut state);
}
let char_pos = state.cursor_position;
let mut chars: Vec<char> = state.content.chars().collect();
if char_pos <= chars.len() {
chars.insert(char_pos, *ch);
state.content = chars.into_iter().collect();
state.cursor_position += 1;
}
}
}
TextInputMsg::Backspace => {
if state.focused {
if state.selection_start.is_some() {
self.delete_selection(&mut state);
} else if state.cursor_position > 0 {
let mut chars: Vec<char> = state.content.chars().collect();
chars.remove(state.cursor_position - 1);
state.content = chars.into_iter().collect();
state.cursor_position -= 1;
}
}
}
TextInputMsg::Delete => {
if state.focused {
if state.selection_start.is_some() {
self.delete_selection(&mut state);
} else {
let mut chars: Vec<char> = state.content.chars().collect();
if state.cursor_position < chars.len() {
chars.remove(state.cursor_position);
state.content = chars.into_iter().collect();
}
}
}
}
TextInputMsg::DeleteWordBackward => {
if state.focused {
if state.selection_start.is_some() {
self.delete_selection(&mut state);
} else {
self.delete_word_backward(&mut state);
}
}
}
TextInputMsg::DeleteWordForward => {
if state.focused {
if state.selection_start.is_some() {
self.delete_selection(&mut state);
} else {
self.delete_word_forward(&mut state);
}
}
}
TextInputMsg::DeleteToLineStart => {
if state.focused {
if state.selection_start.is_some() {
self.delete_selection(&mut state);
} else {
self.delete_to_line_start(&mut state);
}
}
}
TextInputMsg::DeleteToLineEnd => {
if state.focused {
if state.selection_start.is_some() {
self.delete_selection(&mut state);
} else {
self.delete_to_line_end(&mut state);
}
}
}
TextInputMsg::CursorLeft => {
if state.focused && state.cursor_position > 0 {
state.cursor_position -= 1;
state.selection_start = None;
state.selection_end = None;
}
}
TextInputMsg::CursorRight => {
if state.focused {
let char_count = state.content.chars().count();
if state.cursor_position < char_count {
state.cursor_position += 1;
}
state.selection_start = None;
state.selection_end = None;
}
}
TextInputMsg::CursorHome => {
if state.focused {
state.cursor_position = 0;
state.selection_start = None;
state.selection_end = None;
}
}
TextInputMsg::CursorEnd => {
if state.focused {
state.cursor_position = state.content.chars().count();
state.selection_start = None;
state.selection_end = None;
}
}
TextInputMsg::CursorWordLeft => {
if state.focused {
state.cursor_position =
self.find_word_boundary_left(&state.content, state.cursor_position);
state.selection_start = None;
state.selection_end = None;
}
}
TextInputMsg::CursorWordRight => {
if state.focused {
state.cursor_position =
self.find_word_boundary_right(&state.content, state.cursor_position);
state.selection_start = None;
state.selection_end = None;
}
}
TextInputMsg::SelectLeft
| TextInputMsg::SelectRight
| TextInputMsg::SelectAll
| TextInputMsg::SelectWord
| TextInputMsg::ClearSelection => {
}
TextInputMsg::Cut | TextInputMsg::Copy | TextInputMsg::Paste(_) => {
}
}
return Action::Update(Box::new(state));
}
Action::None
}
fn view(&self, ctx: &Context) -> Node {
let state = ctx.get_state::<TextInputState>();
let mut container = Div::new();
if let Some(base) = &self.styles.base {
container = container.style(base.clone());
}
if let Some(focus) = &self.styles.focus {
container = container.focus_style(focus.clone());
}
if self.focusable {
container = container.focusable(true);
}
container = container
.on_focus(ctx.handler(TextInputMsg::Focused))
.on_blur(ctx.handler(TextInputMsg::Blurred))
.on_key(Key::Backspace, ctx.handler(TextInputMsg::Backspace))
.on_key(Key::Delete, ctx.handler(TextInputMsg::Delete))
.on_key(Key::Left, ctx.handler(TextInputMsg::CursorLeft))
.on_key(Key::Right, ctx.handler(TextInputMsg::CursorRight))
.on_key(Key::Home, ctx.handler(TextInputMsg::CursorHome))
.on_key(Key::End, ctx.handler(TextInputMsg::CursorEnd))
.on_key_with_modifiers(
KeyWithModifiers::with_alt(Key::Char('b')),
ctx.handler(TextInputMsg::CursorWordLeft),
)
.on_key_with_modifiers(
KeyWithModifiers::with_alt(Key::Char('f')),
ctx.handler(TextInputMsg::CursorWordRight),
)
.on_key_with_modifiers(
KeyWithModifiers::with_ctrl(Key::Char('a')),
ctx.handler(TextInputMsg::CursorHome),
)
.on_key_with_modifiers(
KeyWithModifiers::with_ctrl(Key::Char('e')),
ctx.handler(TextInputMsg::CursorEnd),
)
.on_key_with_modifiers(
KeyWithModifiers::with_ctrl(Key::Char('b')),
ctx.handler(TextInputMsg::CursorLeft),
)
.on_key_with_modifiers(
KeyWithModifiers::with_ctrl(Key::Char('f')),
ctx.handler(TextInputMsg::CursorRight),
)
.on_key_with_modifiers(
KeyWithModifiers::with_ctrl(Key::Char('w')),
ctx.handler(TextInputMsg::DeleteWordBackward),
)
.on_key_with_modifiers(
KeyWithModifiers::with_alt(Key::Char('d')),
ctx.handler(TextInputMsg::DeleteWordForward),
)
.on_key_with_modifiers(
KeyWithModifiers::with_alt(Key::Backspace),
ctx.handler(TextInputMsg::DeleteWordBackward),
)
.on_key_with_modifiers(
KeyWithModifiers::with_alt(Key::Delete),
ctx.handler(TextInputMsg::DeleteWordForward),
)
.on_key_with_modifiers(
KeyWithModifiers {
key: Key::Backspace,
ctrl: false,
alt: false,
shift: false,
meta: true,
},
ctx.handler(TextInputMsg::DeleteToLineStart),
)
.on_key_with_modifiers(
KeyWithModifiers::with_ctrl(Key::Char('u')),
ctx.handler(TextInputMsg::DeleteToLineStart),
)
.on_key_with_modifiers(
KeyWithModifiers::with_ctrl(Key::Char('k')),
ctx.handler(TextInputMsg::DeleteToLineEnd),
)
.on_any_char(ctx.handler_with_value(|ch| {
Box::new(TextInputMsg::CharInput(ch))
}));
if !state.content.is_empty() || state.focused {
let display_content = if self.password_mode {
"•".repeat(state.content.chars().count())
} else {
state.content.clone()
};
let node = if state.focused {
let cursor_style = self
.cursor_style
.clone()
.unwrap_or_else(Self::default_cursor_style);
let mut rich_text =
RichText::with_cursor(&display_content, state.cursor_position, cursor_style);
if let Some(wrap) = self.wrap {
rich_text = rich_text.wrap(wrap);
}
if let Some(content_style) = &self.content_style {
for span in &mut rich_text.spans {
if span.style.is_none() || span.style.as_ref().unwrap().background.is_none()
{
span.style = Some(content_style.clone());
}
}
}
rich_text.into()
} else if !state.content.is_empty() {
let mut text = Text::new(display_content.clone());
let default_style = Self::default_content_style();
let final_style = TextStyle::merge(Some(default_style), self.content_style.clone());
if let Some(style) = final_style {
text.style = Some(style.clone());
}
if let Some(wrap) = self.wrap {
text.style.get_or_insert(TextStyle::default()).wrap = Some(wrap);
}
text.into()
} else {
let cursor_style = self
.cursor_style
.clone()
.unwrap_or_else(Self::default_cursor_style);
let rich_text = RichText::with_cursor("", 0, cursor_style);
rich_text.into()
};
container = container.children(vec![node]);
} else if let Some(placeholder) = &self.placeholder {
let mut text = Text::new(placeholder.clone());
let default_style = Self::default_placeholder_style();
let final_style = TextStyle::merge(Some(default_style), self.placeholder_style.clone());
if let Some(style) = final_style {
text.style = Some(style.clone());
}
container = container.children(vec![text.into()]);
}
container.into()
}
}
impl TextInput {
pub fn background(mut self, color: Color) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.background = Some(color);
self.styles.base = Some(style);
self
}
pub fn border(mut self, color: Color) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
if style.border.is_none() {
style.border = Some(Border::new(color));
}
if let Some(ref mut border) = style.border {
border.color = color;
border.enabled = true;
}
self.styles.base = Some(style);
self
}
pub fn border_style(mut self, border_style: BorderStyle, color: Color) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.border = Some(Border {
enabled: true,
style: border_style,
color,
edges: BorderEdges::ALL,
});
self.styles.base = Some(style);
self
}
pub fn border_edges(mut self, edges: BorderEdges) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
if style.border.is_none() {
style.border = Some(Border::new(Color::White));
}
if let Some(ref mut border) = style.border {
border.edges = edges;
}
self.styles.base = Some(style);
self
}
pub fn border_full(
mut self,
border_style: BorderStyle,
color: Color,
edges: BorderEdges,
) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.border = Some(Border {
enabled: true,
style: border_style,
color,
edges,
});
self.styles.base = Some(style);
self
}
pub fn padding(mut self, padding: Spacing) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.padding = Some(padding);
self.styles.base = Some(style);
self
}
pub fn width(mut self, width: u16) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.width = Some(Dimension::Fixed(width));
self.styles.base = Some(style);
self
}
pub fn width_percent(mut self, percent: f32) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.width = Some(Dimension::Percentage(percent));
self.styles.base = Some(style);
self
}
pub fn width_auto(mut self) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.width = Some(Dimension::Auto);
self.styles.base = Some(style);
self
}
pub fn width_content(mut self) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.width = Some(Dimension::Content);
self.styles.base = Some(style);
self
}
pub fn height(mut self, height: u16) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.height = Some(Dimension::Fixed(height));
self.styles.base = Some(style);
self
}
pub fn height_percent(mut self, percent: f32) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.height = Some(Dimension::Percentage(percent));
self.styles.base = Some(style);
self
}
pub fn height_auto(mut self) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.height = Some(Dimension::Auto);
self.styles.base = Some(style);
self
}
pub fn height_content(mut self) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.height = Some(Dimension::Content);
self.styles.base = Some(style);
self
}
pub fn focus_style(mut self, style: Style) -> Self {
self.styles.focus = Some(style);
self
}
pub fn focus_border(mut self, color: Color) -> Self {
let mut style = self.styles.focus.clone().unwrap_or_default();
if style.border.is_none() {
style.border = Some(Border::new(color));
}
if let Some(ref mut border) = style.border {
border.color = color;
border.enabled = true;
}
self.styles.focus = Some(style);
self
}
pub fn focus_border_style(mut self, border_style: BorderStyle, color: Color) -> Self {
let mut style = self.styles.focus.clone().unwrap_or_default();
style.border = Some(Border {
enabled: true,
style: border_style,
color,
edges: BorderEdges::ALL,
});
self.styles.focus = Some(style);
self
}
pub fn focus_background(mut self, color: Color) -> Self {
let mut style = self.styles.focus.clone().unwrap_or_default();
style.background = Some(color);
self.styles.focus = Some(style);
self
}
pub fn focus_padding(mut self, padding: Spacing) -> Self {
let mut style = self.styles.focus.clone().unwrap_or_default();
style.padding = Some(padding);
self.styles.focus = Some(style);
self
}
pub fn position(mut self, position: Position) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.position = Some(position);
self.styles.base = Some(style);
self
}
pub fn absolute(self) -> Self {
self.position(Position::Absolute)
}
pub fn top(mut self, top: i16) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.top = Some(top);
self.styles.base = Some(style);
self
}
pub fn right(mut self, right: i16) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.right = Some(right);
self.styles.base = Some(style);
self
}
pub fn bottom(mut self, bottom: i16) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.bottom = Some(bottom);
self.styles.base = Some(style);
self
}
pub fn left(mut self, left: i16) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.left = Some(left);
self.styles.base = Some(style);
self
}
pub fn z_index(mut self, z_index: i32) -> Self {
let mut style = self.styles.base.clone().unwrap_or_else(Self::default_style);
style.z_index = Some(z_index);
self.styles.base = Some(style);
self
}
pub fn placeholder_style(mut self, style: TextStyle) -> Self {
self.placeholder_style = Some(style);
self
}
pub fn placeholder_color(mut self, color: Color) -> Self {
let mut style = self
.placeholder_style
.clone()
.unwrap_or_else(Self::default_placeholder_style);
style.color = Some(color);
self.placeholder_style = Some(style);
self
}
pub fn placeholder_background(mut self, color: Color) -> Self {
let mut style = self
.placeholder_style
.clone()
.unwrap_or_else(Self::default_placeholder_style);
style.background = Some(color);
self.placeholder_style = Some(style);
self
}
pub fn placeholder_bold(mut self, bold: bool) -> Self {
let mut style = self
.placeholder_style
.clone()
.unwrap_or_else(Self::default_placeholder_style);
style.bold = Some(bold);
self.placeholder_style = Some(style);
self
}
pub fn placeholder_italic(mut self, italic: bool) -> Self {
let mut style = self
.placeholder_style
.clone()
.unwrap_or_else(Self::default_placeholder_style);
style.italic = Some(italic);
self.placeholder_style = Some(style);
self
}
pub fn placeholder_underline(mut self, underline: bool) -> Self {
let mut style = self
.placeholder_style
.clone()
.unwrap_or_else(Self::default_placeholder_style);
style.underline = Some(underline);
self.placeholder_style = Some(style);
self
}
pub fn content_style(mut self, style: TextStyle) -> Self {
self.content_style = Some(style);
self
}
pub fn content_color(mut self, color: Color) -> Self {
let mut style = self
.content_style
.clone()
.unwrap_or_else(Self::default_content_style);
style.color = Some(color);
self.content_style = Some(style);
self
}
pub fn content_background(mut self, color: Color) -> Self {
let mut style = self
.content_style
.clone()
.unwrap_or_else(Self::default_content_style);
style.background = Some(color);
self.content_style = Some(style);
self
}
pub fn content_bold(mut self, bold: bool) -> Self {
let mut style = self
.content_style
.clone()
.unwrap_or_else(Self::default_content_style);
style.bold = Some(bold);
self.content_style = Some(style);
self
}
pub fn content_italic(mut self, italic: bool) -> Self {
let mut style = self
.content_style
.clone()
.unwrap_or_else(Self::default_content_style);
style.italic = Some(italic);
self.content_style = Some(style);
self
}
pub fn content_underline(mut self, underline: bool) -> Self {
let mut style = self
.content_style
.clone()
.unwrap_or_else(Self::default_content_style);
style.underline = Some(underline);
self.content_style = Some(style);
self
}
pub fn cursor_style(mut self, style: TextStyle) -> Self {
self.cursor_style = Some(style);
self
}
pub fn cursor_color(mut self, color: Color) -> Self {
let mut style = self
.cursor_style
.clone()
.unwrap_or_else(Self::default_cursor_style);
style.background = Some(color);
style.color = Some(match color {
Color::Black | Color::Blue | Color::Red | Color::Magenta => Color::White,
_ => Color::Black,
});
self.cursor_style = Some(style);
self
}
pub fn selection_style(mut self, style: TextStyle) -> Self {
self.selection_style = Some(style);
self
}
pub fn selection_color(mut self, color: Color) -> Self {
let mut style = self
.selection_style
.clone()
.unwrap_or_else(Self::default_selection_style);
style.background = Some(color);
self.selection_style = Some(style);
self
}
pub fn wrap(mut self, wrap: TextWrap) -> Self {
self.wrap = Some(wrap);
self
}
}
impl Component for TextInput {
fn update(&self, ctx: &Context, msg: Box<dyn Message>, topic: Option<&str>) -> Action {
TextInput::update(self, ctx, msg, topic)
}
fn view(&self, ctx: &Context) -> Node {
TextInput::view(self, ctx)
}
fn get_id(&self) -> Option<ComponentId> {
self.id.clone()
}
fn set_id(&mut self, id: ComponentId) {
self.id = Some(id);
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn clone_box(&self) -> Box<dyn Component> {
Box::new(self.clone())
}
}
impl Default for TextInput {
fn default() -> Self {
Self::new()
}
}