Skip to content

Commit

Permalink
Merge pull request #267 from Ultraxime/main
Browse files Browse the repository at this point in the history
Adding support for dots in number_input
  • Loading branch information
genusistimelord authored Jul 23, 2024
2 parents 8fdab86 + 02ac8b5 commit e8f03ed
Show file tree
Hide file tree
Showing 8 changed files with 457 additions and 45 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ tab_bar = []
tabs = ["tab_bar"]
time_picker = ["chrono", "icons", "iced/canvas"]
wrap = []
number_input = ["num-format", "num-traits"]
number_input = ["num-format", "num-traits", "typed_input"]
typed_input = []
selection_list = []
menu = []
quad = []
Expand Down Expand Up @@ -82,6 +83,7 @@ members = [
"examples/badge",
"examples/card",
"examples/number_input",
"examples/typed_input",
"examples/date_picker",
"examples/color_picker",
"examples/grid",
Expand Down
3 changes: 2 additions & 1 deletion examples/number_input/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ fn main() -> iced::Result {
impl NumberInputDemo {
fn update(&mut self, message: self::Message) {
let Message::NumInpChanged(val) = message;
println!("Value changed to {:?}", val);
self.value = val;
}

fn view(&self) -> Element<Message> {
let lb_minute = Text::new("Number Input:");
let txt_minute = number_input(self.value, 0.0..250.0, Message::NumInpChanged)
let txt_minute = number_input(self.value, -10.0..250.0, Message::NumInpChanged)
.style(number_input::number_input::primary)
.step(0.5);

Expand Down
15 changes: 15 additions & 0 deletions examples/typed_input/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "typed_input"
version = "0.1.0"
authors = ["Ultraxime <36888699+Ultraxime@users.noreply.github.com>"]
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
iced_aw = { workspace = true, features = [
"typed_input",
"icons",
] }

iced.workspace=true
55 changes: 55 additions & 0 deletions examples/typed_input/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use iced::{
widget::{Container, Row, Text},
Alignment, Element, Length,
};
use iced_aw::widgets::typed_input;

#[derive(Default, Debug)]
pub struct TypedInputDemo {
value: f32,
}

#[derive(Debug, Clone)]
pub enum Message {
TypedInpChanged(f32),
}

fn main() -> iced::Result {
iced::application(
"Typed Input example",
TypedInputDemo::update,
TypedInputDemo::view,
)
.window_size(iced::Size {
width: 250.0,
height: 200.0,
})
.font(iced_aw::BOOTSTRAP_FONT_BYTES)
.run()
}

impl TypedInputDemo {
fn update(&mut self, message: self::Message) {
let Message::TypedInpChanged(val) = message;
println!("Value changed to {:?}", val);
self.value = val;
}

fn view(&self) -> Element<Message> {
let lb_minute = Text::new("Typed Input:");
let txt_minute = typed_input::TypedInput::new(&self.value, Message::TypedInpChanged);

Container::new(
Row::new()
.spacing(10)
.align_y(Alignment::Center)
.push(lb_minute)
.push(txt_minute),
)
.width(Length::Fill)
.height(Length::Fill)
.center_x(Length::Fill)
.center_y(Length::Fill)
.into()
}
}
3 changes: 3 additions & 0 deletions src/widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub mod number_input;
pub type NumberInput<'a, T, Message, Theme, Renderer> =
number_input::NumberInput<'a, T, Message, Theme, Renderer>;

#[cfg(feature = "typed_input")]
pub mod typed_input;

#[cfg(feature = "card")]
pub mod card;
#[cfg(feature = "card")]
Expand Down
90 changes: 47 additions & 43 deletions src/widgets/number_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use iced::{
widget::{
text::LineHeight,
text_input::{self, cursor, Value},
Column, Container, Row, Text, TextInput,
Column, Container, Row, Text,
},
Alignment, Background, Border, Color, Element, Event, Length, Padding, Pixels, Point,
Rectangle, Shadow, Size,
Expand All @@ -30,6 +30,7 @@ use std::{
};

use crate::style::{self, Status};
use crate::widgets::typed_input::TypedInput;
pub use crate::{
core::icons::{bootstrap::icon_to_string, Bootstrap, BOOTSTRAP_FONT},
style::{
Expand Down Expand Up @@ -81,7 +82,7 @@ where
/// The text size of the [`NumberInput`].
size: Option<f32>,
/// The underlying element of the [`NumberInput`].
content: TextInput<'a, Message, Theme, Renderer>,
content: TypedInput<'a, T, Message, Theme, Renderer>,
/// The ``on_change`` event of the [`NumberInput`].
on_change: Box<dyn Fn(T) -> Message>,
/// The style of the [`NumberInput`].
Expand Down Expand Up @@ -116,9 +117,6 @@ where
T: 'static,
{
let padding = DEFAULT_PADDING;
let convert_to_num = move |s: String| {
on_changed(T::from_str(&s).unwrap_or(if s.is_empty() { T::zero() } else { value }))
};

Self {
value,
Expand All @@ -127,8 +125,7 @@ where
max: Self::set_max(bounds.end_bound()),
padding,
size: None,
content: TextInput::new("", format!("{value}").as_str())
.on_input(convert_to_num)
content: TypedInput::new(&value, on_changed)
.padding(padding)
.width(Length::Fixed(127.0))
.class(Theme::default_input()),
Expand Down Expand Up @@ -346,7 +343,7 @@ where
.shrink(padding);
let content = self
.content
.layout(&mut tree.children[0], renderer, &limits, None);
.layout(&mut tree.children[0], renderer, &limits);
let limits2 = Limits::new(Size::new(0.0, 0.0), content.size());
let txt_size = self.size.unwrap_or_else(|| renderer.default_size().0);

Expand Down Expand Up @@ -460,6 +457,8 @@ where
.downcast_mut::<text_input::State<Renderer::Paragraph>>();
let modifiers = state.state.downcast_mut::<ModifierState>();

let current_text = self.content.text().to_owned();

let mut forward_to_text = |event, shell, child, clipboard| {
self.content.on_event(
child, event, content, cursor, renderer, clipboard, shell, viewport,
Expand All @@ -485,39 +484,38 @@ where
forward_to_text(event, shell, child, clipboard)
} else if text == "\u{8}" {
// Backspace
if T::zero().eq(&self.value) {
event::Status::Ignored
} else {
let mut new_val = self.value.to_string();
match text_input.cursor().state(&Value::new(&new_val)) {
cursor::State::Index(idx)
if idx >= 1 && idx <= new_val.len() =>
{
_ = new_val.remove(idx - 1);
}
cursor::State::Selection { start, end }
if start <= new_val.len() && end <= new_val.len() =>
{
new_val.replace_range(start.min(end)..start.max(end), "");
}
_ => return event::Status::Ignored,
if current_text == T::zero().to_string() {
return event::Status::Ignored;
}
let mut new_val = current_text;
match text_input.cursor().state(&Value::new(&new_val)) {
cursor::State::Index(idx) if idx >= 1 && idx <= new_val.len() => {
_ = new_val.remove(idx - 1);
}

if new_val.is_empty() {
new_val = T::zero().to_string();
cursor::State::Selection { start, end }
if start <= new_val.len() && end <= new_val.len() =>
{
new_val.replace_range(start.min(end)..start.max(end), "");
}
_ => return event::Status::Ignored,
}

match T::from_str(&new_val) {
Ok(val)
if (self.min..self.max).contains(&val)
&& val != self.value =>
{
self.value = val;
forward_to_text(event, shell, child, clipboard)
}
Ok(_) => event::Status::Captured,
_ => event::Status::Ignored,
if new_val.is_empty() {
new_val = T::zero().to_string();
}

match T::from_str(&new_val) {
Ok(val)
if val >= self.min && val <= self.max && val != self.value =>
{
self.value = val;
forward_to_text(event, shell, child, clipboard)
}
Ok(val) if val >= self.min && val <= self.max => {
forward_to_text(event, shell, child, clipboard)
}
Ok(_) => event::Status::Captured,
_ => event::Status::Ignored,
}
} else {
let input = if text == "\u{16}" {
Expand All @@ -526,15 +524,15 @@ where
Some(paste) => paste,
None => return event::Status::Ignored,
}
} else if text.parse::<i64>().is_err() && text != "-" {
} else if text.parse::<i64>().is_err() && text != "-" && text != "." {
return event::Status::Ignored;
} else {
text.to_string()
};

let input = input.trim();

let mut new_val = self.value.to_string();
let mut new_val = current_text;
match text_input.cursor().state(&Value::new(&new_val)) {
cursor::State::Index(idx) if idx <= new_val.len() => {
new_val.insert_str(idx, input);
Expand All @@ -549,11 +547,14 @@ where

match T::from_str(&new_val) {
Ok(val)
if (self.min..self.max).contains(&val) && val != self.value =>
if val >= self.min && val <= self.max && val != self.value =>
{
self.value = val;
forward_to_text(event, shell, child, clipboard)
}
Ok(val) if val >= self.min && val <= self.max => {
forward_to_text(event, shell, child, clipboard)
}
Ok(_) => event::Status::Captured,
_ => event::Status::Ignored,
}
Expand All @@ -569,7 +570,10 @@ where
event::Status::Captured
}
keyboard::Key::Named(
keyboard::key::Named::ArrowLeft | keyboard::key::Named::ArrowRight,
keyboard::key::Named::ArrowLeft
| keyboard::key::Named::ArrowRight
| keyboard::key::Named::Home
| keyboard::key::Named::End,
) => forward_to_text(event, shell, child, clipboard),
_ => event::Status::Ignored,
},
Expand Down Expand Up @@ -661,7 +665,7 @@ where
state: &Tree,
renderer: &mut Renderer,
theme: &Theme,
_style: &renderer::Style,
style: &renderer::Style,
layout: Layout<'_>,
cursor: Cursor,
viewport: &Rectangle,
Expand All @@ -684,9 +688,9 @@ where
&state.children[0],
renderer,
theme,
style,
content_layout,
cursor,
None,
viewport,
);
let is_decrease_disabled = self.value <= self.min || self.min == self.max;
Expand Down
Loading

0 comments on commit e8f03ed

Please sign in to comment.