mirror of
https://github.com/danbulant/cushy
synced 2026-07-06 03:30:38 +00:00
Added to_ variants for into_ functions
This commit is contained in:
parent
8bcbad959b
commit
244797110e
20 changed files with 122 additions and 51 deletions
|
|
@ -36,8 +36,7 @@ fn main() -> cushy::Result {
|
||||||
|
|
||||||
// Create a new label displaying `count`
|
// Create a new label displaying `count`
|
||||||
count
|
count
|
||||||
.clone()
|
.to_label()
|
||||||
.into_label()
|
|
||||||
// Use the label as the contents of a button
|
// Use the label as the contents of a button
|
||||||
.into_button()
|
.into_button()
|
||||||
// Set the `on_click` callback to a closure that increments the counter.
|
// Set the `on_click` callback to a closure that increments the counter.
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `Label` has been refactored to accept any `Display` type. As a result of this,
|
- `Label` has been refactored to accept any `Display` type. As a result of this,
|
||||||
`Label::text` is now named `display` and `Label::new()` now accepts an
|
`Label::text` is now named `display` and `Label::new()` now accepts an
|
||||||
`IntoReadOnly<T>` instead of `IntoValue<String>`.
|
`IntoReadOnly<T>` instead of `IntoValue<String>`.
|
||||||
|
- `Dynamic<Children>::wrap` has been renamed to `into_wrap` for consistency.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
@ -110,6 +111,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
`Mutex`. `Owned<T>` implements `Source<T>` and `Destination<T>`.
|
`Mutex`. `Owned<T>` implements `Source<T>` and `Destination<T>`.
|
||||||
- `GenerationalValue<T>` now implements `Default` when `T` does.
|
- `GenerationalValue<T>` now implements `Default` when `T` does.
|
||||||
- `Value<T>` now implements `From<Dynamic<T>>`.
|
- `Value<T>` now implements `From<Dynamic<T>>`.
|
||||||
|
- Most `into_` functions that create widgets now have `to_` variations that
|
||||||
|
clone `self` before calling the `into_` function. This has only been done in
|
||||||
|
situations where it is known or likely that the clone being performed is
|
||||||
|
cheap.
|
||||||
|
|
||||||
[99]: https://github.com/khonsulabs/cushy/issues/99
|
[99]: https://github.com/khonsulabs/cushy/issues/99
|
||||||
[120]: https://github.com/khonsulabs/cushy/issues/120
|
[120]: https://github.com/khonsulabs/cushy/issues/120
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ fn main() -> cushy::Result {
|
||||||
|
|
||||||
// Create a new label displaying `count`
|
// Create a new label displaying `count`
|
||||||
count
|
count
|
||||||
.clone()
|
.to_label()
|
||||||
.into_label()
|
|
||||||
// Use the label as the contents of a button
|
// Use the label as the contents of a button
|
||||||
.into_button()
|
.into_button()
|
||||||
// Set the `on_click` callback to a closure that increments the counter.
|
// Set the `on_click` callback to a closure that increments the counter.
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ fn main() -> cushy::Result {
|
||||||
|
|
||||||
// Create a new label displaying `count`
|
// Create a new label displaying `count`
|
||||||
count
|
count
|
||||||
.clone()
|
.to_label()
|
||||||
.into_label()
|
|
||||||
// Use the label as the contents of a button
|
// Use the label as the contents of a button
|
||||||
.into_button()
|
.into_button()
|
||||||
// Set the `on_click` callback to a closure that increments the counter.
|
// Set the `on_click` callback to a closure that increments the counter.
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ fn main() -> cushy::Result {
|
||||||
|
|
||||||
checkbox_state
|
checkbox_state
|
||||||
.clone()
|
.clone()
|
||||||
.into_checkbox(label)
|
.to_checkbox(label)
|
||||||
.and("Maybe".into_button().on_click(move |()| {
|
.and("Maybe".into_button().on_click(move |()| {
|
||||||
checkbox_state.set(CheckboxState::Indeterminant);
|
checkbox_state.set(CheckboxState::Indeterminant);
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ fn main() -> cushy::Result {
|
||||||
let collapse = Dynamic::new(false);
|
let collapse = Dynamic::new(false);
|
||||||
|
|
||||||
collapse
|
collapse
|
||||||
.clone()
|
.to_checkbox("Collapse")
|
||||||
.into_checkbox("Collapse")
|
|
||||||
.and(
|
.and(
|
||||||
"Content Above"
|
"Content Above"
|
||||||
.contain()
|
.contain()
|
||||||
|
|
|
||||||
|
|
@ -76,11 +76,11 @@ fn edit_contact_form(contact: &Contact, db: &Dynamic<HashMap<u64, Contact>>) ->
|
||||||
let title = Dynamic::new(contact.title.clone());
|
let title = Dynamic::new(contact.title.clone());
|
||||||
|
|
||||||
"First Name"
|
"First Name"
|
||||||
.and(first.clone().into_input())
|
.and(first.to_input())
|
||||||
.and("Last Name")
|
.and("Last Name")
|
||||||
.and(last.clone().into_input())
|
.and(last.to_input())
|
||||||
.and("Title")
|
.and("Title")
|
||||||
.and(title.clone().into_input())
|
.and(title.to_input())
|
||||||
.and(
|
.and(
|
||||||
"Save"
|
"Save"
|
||||||
.into_button()
|
.into_button()
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,7 @@ fn main() -> cushy::Result {
|
||||||
let counter = Dynamic::new(0i32);
|
let counter = Dynamic::new(0i32);
|
||||||
|
|
||||||
counter
|
counter
|
||||||
.clone()
|
.to_label()
|
||||||
.into_label()
|
|
||||||
.width(Lp::points(100))
|
.width(Lp::points(100))
|
||||||
.and("+".into_button().on_click(counter.with_clone(|counter| {
|
.and("+".into_button().on_click(counter.with_clone(|counter| {
|
||||||
move |_| {
|
move |_| {
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,9 @@ fn main() -> cushy::Result {
|
||||||
let (cancel_tag, cancel_id) = WidgetTag::new();
|
let (cancel_tag, cancel_id) = WidgetTag::new();
|
||||||
let (username_tag, username_id) = WidgetTag::new();
|
let (username_tag, username_id) = WidgetTag::new();
|
||||||
|
|
||||||
let username_row = (
|
let username_row = ("Username", username.to_input().make_with_tag(username_tag));
|
||||||
"Username",
|
|
||||||
username.clone().into_input().make_with_tag(username_tag),
|
|
||||||
);
|
|
||||||
|
|
||||||
let password_row = (
|
let password_row = ("Password", password.to_input().with_next_focus(login_id));
|
||||||
"Password",
|
|
||||||
password.clone().into_input().with_next_focus(login_id),
|
|
||||||
);
|
|
||||||
|
|
||||||
let buttons = "Cancel"
|
let buttons = "Cancel"
|
||||||
.into_button()
|
.into_button()
|
||||||
|
|
|
||||||
|
|
@ -17,19 +17,21 @@ fn main() -> cushy::Result {
|
||||||
.and(Color::RED.expand_weighted(2))
|
.and(Color::RED.expand_weighted(2))
|
||||||
.into_columns()
|
.into_columns()
|
||||||
.expand()
|
.expand()
|
||||||
.and(chat_message.clone().into_input().on_key(move |input| {
|
.and(
|
||||||
match (input.state, input.logical_key) {
|
chat_message
|
||||||
(ElementState::Pressed, Key::Named(NamedKey::Enter)) => {
|
.to_input()
|
||||||
let new_message = chat_message.take();
|
.on_key(move |input| match (input.state, input.logical_key) {
|
||||||
chat_log.map_mut(|mut chat_log| {
|
(ElementState::Pressed, Key::Named(NamedKey::Enter)) => {
|
||||||
chat_log.push_str(&new_message);
|
let new_message = chat_message.take();
|
||||||
chat_log.push('\n');
|
chat_log.map_mut(|mut chat_log| {
|
||||||
});
|
chat_log.push_str(&new_message);
|
||||||
HANDLED
|
chat_log.push('\n');
|
||||||
}
|
});
|
||||||
_ => IGNORED,
|
HANDLED
|
||||||
}
|
}
|
||||||
}))
|
_ => IGNORED,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.into_rows()
|
.into_rows()
|
||||||
.expand()
|
.expand()
|
||||||
.run()
|
.run()
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,7 @@ fn main() -> cushy::Result {
|
||||||
.align_left()
|
.align_left()
|
||||||
.and(
|
.and(
|
||||||
username
|
username
|
||||||
.clone()
|
.to_input()
|
||||||
.into_input()
|
|
||||||
.placeholder("Username")
|
.placeholder("Username")
|
||||||
.validation(validations.validate(&username, |u: &String| {
|
.validation(validations.validate(&username, |u: &String| {
|
||||||
if u.is_empty() {
|
if u.is_empty() {
|
||||||
|
|
@ -40,8 +39,7 @@ fn main() -> cushy::Result {
|
||||||
.align_left()
|
.align_left()
|
||||||
.and(
|
.and(
|
||||||
password
|
password
|
||||||
.clone()
|
.to_input()
|
||||||
.into_input()
|
|
||||||
.placeholder("Password")
|
.placeholder("Password")
|
||||||
.validation(
|
.validation(
|
||||||
validations.validate(&password, |u: &MaskedString| match u.len() {
|
validations.validate(&password, |u: &MaskedString| match u.len() {
|
||||||
|
|
|
||||||
|
|
@ -206,8 +206,7 @@ fn optional_editor(label: &str, color: &Dynamic<ColorSource>) -> (Dynamic<bool>,
|
||||||
(
|
(
|
||||||
enabled.clone(),
|
enabled.clone(),
|
||||||
enabled
|
enabled
|
||||||
.clone()
|
.to_checkbox(swatch_label(label, color))
|
||||||
.into_checkbox(swatch_label(label, color))
|
|
||||||
.and(color_editor(color).collapse_vertically(hide_editor))
|
.and(color_editor(color).collapse_vertically(hide_editor))
|
||||||
.into_rows(),
|
.into_rows(),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,6 @@ fn square(row: usize, column: usize, game: &Dynamic<GameState>) -> impl MakeWidg
|
||||||
});
|
});
|
||||||
|
|
||||||
label
|
label
|
||||||
.clone()
|
|
||||||
.into_button()
|
.into_button()
|
||||||
.kind(ButtonKind::Outline)
|
.kind(ButtonKind::Outline)
|
||||||
.on_click(move |_| game.lock().play(row, column))
|
.on_click(move |_| game.lock().play(row, column))
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,13 @@ fn main() -> cushy::Result {
|
||||||
|
|
||||||
"Hinted"
|
"Hinted"
|
||||||
.and(
|
.and(
|
||||||
text.clone()
|
text.to_input()
|
||||||
.into_input()
|
|
||||||
.validation(validations.validate(&text, validate_input))
|
.validation(validations.validate(&text, validate_input))
|
||||||
.hint("* required"),
|
.hint("* required"),
|
||||||
)
|
)
|
||||||
.and("Not Hinted")
|
.and("Not Hinted")
|
||||||
.and(
|
.and(
|
||||||
text.clone()
|
text.to_input()
|
||||||
.into_input()
|
|
||||||
.validation(validations.validate(&text, validate_input)),
|
.validation(validations.validate(&text, validate_input)),
|
||||||
)
|
)
|
||||||
.and(
|
.and(
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,14 @@ pub trait IntoAnimate: Sized + Send + Sync {
|
||||||
/// Return this change as a running animation.
|
/// Return this change as a running animation.
|
||||||
fn into_animate(self) -> Self::Animate;
|
fn into_animate(self) -> Self::Animate;
|
||||||
|
|
||||||
|
/// Returns a clone of this change as a running animation.
|
||||||
|
fn to_animate(&self) -> Self::Animate
|
||||||
|
where
|
||||||
|
Self: Clone,
|
||||||
|
{
|
||||||
|
self.clone().into_animate()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an combined animation that performs `self` and `other` in
|
/// Returns an combined animation that performs `self` and `other` in
|
||||||
/// sequence.
|
/// sequence.
|
||||||
fn and_then<Other: IntoAnimate>(self, other: Other) -> Chain<Self, Other> {
|
fn and_then<Other: IntoAnimate>(self, other: Other) -> Chain<Self, Other> {
|
||||||
|
|
@ -674,7 +682,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.keep_cycling() {
|
if self.keep_cycling() {
|
||||||
self.running = Some(self.animation.clone().into_animate());
|
self.running = Some(self.animation.to_animate());
|
||||||
} else {
|
} else {
|
||||||
self.running = None;
|
self.running = None;
|
||||||
return ControlFlow::Break(elapsed);
|
return ControlFlow::Break(elapsed);
|
||||||
|
|
|
||||||
32
src/value.rs
32
src/value.rs
|
|
@ -1164,9 +1164,32 @@ impl Dynamic<WidgetInstance> {
|
||||||
/// Returns a new [`Switcher`] widget whose contents is the value of this
|
/// Returns a new [`Switcher`] widget whose contents is the value of this
|
||||||
/// dynamic.
|
/// dynamic.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
pub fn into_switcher(self) -> Switcher {
|
||||||
|
self.into_reader().into_switcher()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [`Switcher`] widget whose contents is the value of this
|
||||||
|
/// dynamic.
|
||||||
|
#[must_use]
|
||||||
|
pub fn to_switcher(&self) -> Switcher {
|
||||||
|
self.create_reader().into_switcher()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynamicReader<WidgetInstance> {
|
||||||
|
/// Returns a new [`Switcher`] widget whose contents is the value of this
|
||||||
|
/// dynamic reader.
|
||||||
|
#[must_use]
|
||||||
pub fn into_switcher(self) -> Switcher {
|
pub fn into_switcher(self) -> Switcher {
|
||||||
Switcher::new(self)
|
Switcher::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a new [`Switcher`] widget whose contents is the value of this
|
||||||
|
/// dynamic reader.
|
||||||
|
#[must_use]
|
||||||
|
pub fn to_switcher(&self) -> Switcher {
|
||||||
|
Switcher::new(self.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MakeWidgetWithTag for Dynamic<WidgetInstance> {
|
impl MakeWidgetWithTag for Dynamic<WidgetInstance> {
|
||||||
|
|
@ -2261,6 +2284,15 @@ pub trait IntoReader<T> {
|
||||||
{
|
{
|
||||||
Label::new(self.into_reader())
|
Label::new(self.into_reader())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `self` being `Display`ed in a [`Label`] widget.
|
||||||
|
fn to_label(&self) -> Label<T>
|
||||||
|
where
|
||||||
|
Self: Clone,
|
||||||
|
T: Debug + Display + Send + 'static,
|
||||||
|
{
|
||||||
|
self.clone().into_label()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IntoReader<T> for Dynamic<T> {
|
impl<T> IntoReader<T> for Dynamic<T> {
|
||||||
|
|
|
||||||
|
|
@ -2074,12 +2074,24 @@ impl Dynamic<Children> {
|
||||||
Stack::rows(self)
|
Stack::rows(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `self` as a vertical [`Stack`] of rows.
|
||||||
|
#[must_use]
|
||||||
|
pub fn to_rows(&self) -> Stack {
|
||||||
|
self.clone().into_rows()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `self` as a horizontal [`Stack`] of columns.
|
/// Returns `self` as a horizontal [`Stack`] of columns.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn into_columns(self) -> Stack {
|
pub fn into_columns(self) -> Stack {
|
||||||
Stack::columns(self)
|
Stack::columns(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `self` as a horizontal [`Stack`] of columns.
|
||||||
|
#[must_use]
|
||||||
|
pub fn to_columns(&self) -> Stack {
|
||||||
|
self.clone().into_columns()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `self` as [`Layers`], with the widgets being stacked in the Z
|
/// Returns `self` as [`Layers`], with the widgets being stacked in the Z
|
||||||
/// direction.
|
/// direction.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
@ -2087,12 +2099,26 @@ impl Dynamic<Children> {
|
||||||
Layers::new(self)
|
Layers::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `self` as [`Layers`], with the widgets being stacked in the Z
|
||||||
|
/// direction.
|
||||||
|
#[must_use]
|
||||||
|
pub fn to_layers(&self) -> Layers {
|
||||||
|
self.clone().into_layers()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a [`Wrap`] that lays the children out horizontally, wrapping
|
/// Returns a [`Wrap`] that lays the children out horizontally, wrapping
|
||||||
/// into additional rows as needed.
|
/// into additional rows as needed.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn wrap(self) -> Wrap {
|
pub fn into_wrap(self) -> Wrap {
|
||||||
Wrap::new(self)
|
Wrap::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a [`Wrap`] that lays the children out horizontally, wrapping
|
||||||
|
/// into additional rows as needed.
|
||||||
|
#[must_use]
|
||||||
|
pub fn to_wrap(&self) -> Wrap {
|
||||||
|
self.clone().into_wrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W> FromIterator<W> for Children
|
impl<W> FromIterator<W> for Children
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,14 @@ pub trait Checkable: IntoDynamic<CheckboxState> + Sized {
|
||||||
fn into_checkbox(self, label: impl MakeWidget) -> Checkbox {
|
fn into_checkbox(self, label: impl MakeWidget) -> Checkbox {
|
||||||
Checkbox::new(self.into_dynamic(), label)
|
Checkbox::new(self.into_dynamic(), label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a new checkbox using `self` as the value and `label`.
|
||||||
|
fn to_checkbox(&self, label: impl MakeWidget) -> Checkbox
|
||||||
|
where
|
||||||
|
Self: Clone,
|
||||||
|
{
|
||||||
|
self.clone().into_checkbox(label)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Checkable for T where T: IntoDynamic<CheckboxState> {}
|
impl<T> Checkable for T where T: IntoDynamic<CheckboxState> {}
|
||||||
|
|
|
||||||
|
|
@ -1351,6 +1351,13 @@ where
|
||||||
fn into_input(self) -> Input<Storage> {
|
fn into_input(self) -> Input<Storage> {
|
||||||
Input::new(self.into_dynamic())
|
Input::new(self.into_dynamic())
|
||||||
}
|
}
|
||||||
|
/// Returns this string as a text input widget.
|
||||||
|
fn to_input(&self) -> Input<Storage>
|
||||||
|
where
|
||||||
|
Self: Clone,
|
||||||
|
{
|
||||||
|
self.clone().into_input()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> InputValue<String> for T where T: IntoDynamic<String> {}
|
impl<T> InputValue<String> for T where T: IntoDynamic<String> {}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::fmt::Debug;
|
||||||
use figures::Size;
|
use figures::Size;
|
||||||
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::value::{Dynamic, DynamicReader, IntoDynamic, Source};
|
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoReader, Source};
|
||||||
use crate::widget::{WidgetInstance, WidgetRef, WrapperWidget};
|
use crate::widget::{WidgetInstance, WidgetRef, WrapperWidget};
|
||||||
use crate::ConstraintLimit;
|
use crate::ConstraintLimit;
|
||||||
|
|
||||||
|
|
@ -36,8 +36,8 @@ impl Switcher {
|
||||||
/// Returns a new widget that replaces its contents with the result of
|
/// Returns a new widget that replaces its contents with the result of
|
||||||
/// `widget_factory` each time `value` changes.
|
/// `widget_factory` each time `value` changes.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(source: impl IntoDynamic<WidgetInstance>) -> Self {
|
pub fn new(source: impl IntoReader<WidgetInstance>) -> Self {
|
||||||
let source = source.into_dynamic().into_reader();
|
let source = source.into_reader();
|
||||||
let child = WidgetRef::new(source.get());
|
let child = WidgetRef::new(source.get());
|
||||||
Self { source, child }
|
Self { source, child }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue