mirror of
https://github.com/danbulant/cushy
synced 2026-06-18 22:11:34 +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`
|
||||
count
|
||||
.clone()
|
||||
.into_label()
|
||||
.to_label()
|
||||
// Use the label as the contents of a button
|
||||
.into_button()
|
||||
// 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::text` is now named `display` and `Label::new()` now accepts an
|
||||
`IntoReadOnly<T>` instead of `IntoValue<String>`.
|
||||
- `Dynamic<Children>::wrap` has been renamed to `into_wrap` for consistency.
|
||||
|
||||
### 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>`.
|
||||
- `GenerationalValue<T>` now implements `Default` when `T` does.
|
||||
- `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
|
||||
[120]: https://github.com/khonsulabs/cushy/issues/120
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@ fn main() -> cushy::Result {
|
|||
|
||||
// Create a new label displaying `count`
|
||||
count
|
||||
.clone()
|
||||
.into_label()
|
||||
.to_label()
|
||||
// Use the label as the contents of a button
|
||||
.into_button()
|
||||
// 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`
|
||||
count
|
||||
.clone()
|
||||
.into_label()
|
||||
.to_label()
|
||||
// Use the label as the contents of a button
|
||||
.into_button()
|
||||
// Set the `on_click` callback to a closure that increments the counter.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ fn main() -> cushy::Result {
|
|||
|
||||
checkbox_state
|
||||
.clone()
|
||||
.into_checkbox(label)
|
||||
.to_checkbox(label)
|
||||
.and("Maybe".into_button().on_click(move |()| {
|
||||
checkbox_state.set(CheckboxState::Indeterminant);
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ fn main() -> cushy::Result {
|
|||
let collapse = Dynamic::new(false);
|
||||
|
||||
collapse
|
||||
.clone()
|
||||
.into_checkbox("Collapse")
|
||||
.to_checkbox("Collapse")
|
||||
.and(
|
||||
"Content Above"
|
||||
.contain()
|
||||
|
|
|
|||
|
|
@ -76,11 +76,11 @@ fn edit_contact_form(contact: &Contact, db: &Dynamic<HashMap<u64, Contact>>) ->
|
|||
let title = Dynamic::new(contact.title.clone());
|
||||
|
||||
"First Name"
|
||||
.and(first.clone().into_input())
|
||||
.and(first.to_input())
|
||||
.and("Last Name")
|
||||
.and(last.clone().into_input())
|
||||
.and(last.to_input())
|
||||
.and("Title")
|
||||
.and(title.clone().into_input())
|
||||
.and(title.to_input())
|
||||
.and(
|
||||
"Save"
|
||||
.into_button()
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ fn main() -> cushy::Result {
|
|||
let counter = Dynamic::new(0i32);
|
||||
|
||||
counter
|
||||
.clone()
|
||||
.into_label()
|
||||
.to_label()
|
||||
.width(Lp::points(100))
|
||||
.and("+".into_button().on_click(counter.with_clone(|counter| {
|
||||
move |_| {
|
||||
|
|
|
|||
|
|
@ -22,15 +22,9 @@ fn main() -> cushy::Result {
|
|||
let (cancel_tag, cancel_id) = WidgetTag::new();
|
||||
let (username_tag, username_id) = WidgetTag::new();
|
||||
|
||||
let username_row = (
|
||||
"Username",
|
||||
username.clone().into_input().make_with_tag(username_tag),
|
||||
);
|
||||
let username_row = ("Username", username.to_input().make_with_tag(username_tag));
|
||||
|
||||
let password_row = (
|
||||
"Password",
|
||||
password.clone().into_input().with_next_focus(login_id),
|
||||
);
|
||||
let password_row = ("Password", password.to_input().with_next_focus(login_id));
|
||||
|
||||
let buttons = "Cancel"
|
||||
.into_button()
|
||||
|
|
|
|||
|
|
@ -17,19 +17,21 @@ fn main() -> cushy::Result {
|
|||
.and(Color::RED.expand_weighted(2))
|
||||
.into_columns()
|
||||
.expand()
|
||||
.and(chat_message.clone().into_input().on_key(move |input| {
|
||||
match (input.state, input.logical_key) {
|
||||
(ElementState::Pressed, Key::Named(NamedKey::Enter)) => {
|
||||
let new_message = chat_message.take();
|
||||
chat_log.map_mut(|mut chat_log| {
|
||||
chat_log.push_str(&new_message);
|
||||
chat_log.push('\n');
|
||||
});
|
||||
HANDLED
|
||||
}
|
||||
_ => IGNORED,
|
||||
}
|
||||
}))
|
||||
.and(
|
||||
chat_message
|
||||
.to_input()
|
||||
.on_key(move |input| match (input.state, input.logical_key) {
|
||||
(ElementState::Pressed, Key::Named(NamedKey::Enter)) => {
|
||||
let new_message = chat_message.take();
|
||||
chat_log.map_mut(|mut chat_log| {
|
||||
chat_log.push_str(&new_message);
|
||||
chat_log.push('\n');
|
||||
});
|
||||
HANDLED
|
||||
}
|
||||
_ => IGNORED,
|
||||
}),
|
||||
)
|
||||
.into_rows()
|
||||
.expand()
|
||||
.run()
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ fn main() -> cushy::Result {
|
|||
.align_left()
|
||||
.and(
|
||||
username
|
||||
.clone()
|
||||
.into_input()
|
||||
.to_input()
|
||||
.placeholder("Username")
|
||||
.validation(validations.validate(&username, |u: &String| {
|
||||
if u.is_empty() {
|
||||
|
|
@ -40,8 +39,7 @@ fn main() -> cushy::Result {
|
|||
.align_left()
|
||||
.and(
|
||||
password
|
||||
.clone()
|
||||
.into_input()
|
||||
.to_input()
|
||||
.placeholder("Password")
|
||||
.validation(
|
||||
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()
|
||||
.into_checkbox(swatch_label(label, color))
|
||||
.to_checkbox(swatch_label(label, color))
|
||||
.and(color_editor(color).collapse_vertically(hide_editor))
|
||||
.into_rows(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ fn square(row: usize, column: usize, game: &Dynamic<GameState>) -> impl MakeWidg
|
|||
});
|
||||
|
||||
label
|
||||
.clone()
|
||||
.into_button()
|
||||
.kind(ButtonKind::Outline)
|
||||
.on_click(move |_| game.lock().play(row, column))
|
||||
|
|
|
|||
|
|
@ -10,15 +10,13 @@ fn main() -> cushy::Result {
|
|||
|
||||
"Hinted"
|
||||
.and(
|
||||
text.clone()
|
||||
.into_input()
|
||||
text.to_input()
|
||||
.validation(validations.validate(&text, validate_input))
|
||||
.hint("* required"),
|
||||
)
|
||||
.and("Not Hinted")
|
||||
.and(
|
||||
text.clone()
|
||||
.into_input()
|
||||
text.to_input()
|
||||
.validation(validations.validate(&text, validate_input)),
|
||||
)
|
||||
.and(
|
||||
|
|
|
|||
|
|
@ -345,6 +345,14 @@ pub trait IntoAnimate: Sized + Send + Sync {
|
|||
/// Return this change as a running animation.
|
||||
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
|
||||
/// sequence.
|
||||
fn and_then<Other: IntoAnimate>(self, other: Other) -> Chain<Self, Other> {
|
||||
|
|
@ -674,7 +682,7 @@ where
|
|||
}
|
||||
|
||||
if self.keep_cycling() {
|
||||
self.running = Some(self.animation.clone().into_animate());
|
||||
self.running = Some(self.animation.to_animate());
|
||||
} else {
|
||||
self.running = None;
|
||||
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
|
||||
/// dynamic.
|
||||
#[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 {
|
||||
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> {
|
||||
|
|
@ -2261,6 +2284,15 @@ pub trait IntoReader<T> {
|
|||
{
|
||||
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> {
|
||||
|
|
|
|||
|
|
@ -2074,12 +2074,24 @@ impl Dynamic<Children> {
|
|||
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.
|
||||
#[must_use]
|
||||
pub fn into_columns(self) -> Stack {
|
||||
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
|
||||
/// direction.
|
||||
#[must_use]
|
||||
|
|
@ -2087,12 +2099,26 @@ impl Dynamic<Children> {
|
|||
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
|
||||
/// into additional rows as needed.
|
||||
#[must_use]
|
||||
pub fn wrap(self) -> Wrap {
|
||||
pub fn into_wrap(self) -> Wrap {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -257,6 +257,14 @@ pub trait Checkable: IntoDynamic<CheckboxState> + Sized {
|
|||
fn into_checkbox(self, label: impl MakeWidget) -> Checkbox {
|
||||
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> {}
|
||||
|
|
|
|||
|
|
@ -1351,6 +1351,13 @@ where
|
|||
fn into_input(self) -> Input<Storage> {
|
||||
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> {}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::fmt::Debug;
|
|||
use figures::Size;
|
||||
|
||||
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::ConstraintLimit;
|
||||
|
||||
|
|
@ -36,8 +36,8 @@ impl Switcher {
|
|||
/// Returns a new widget that replaces its contents with the result of
|
||||
/// `widget_factory` each time `value` changes.
|
||||
#[must_use]
|
||||
pub fn new(source: impl IntoDynamic<WidgetInstance>) -> Self {
|
||||
let source = source.into_dynamic().into_reader();
|
||||
pub fn new(source: impl IntoReader<WidgetInstance>) -> Self {
|
||||
let source = source.into_reader();
|
||||
let child = WidgetRef::new(source.get());
|
||||
Self { source, child }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue