Skip to content

Commit

Permalink
Add on_create to handle and on_edit_end to textbox
Browse files Browse the repository at this point in the history
  • Loading branch information
geom3trik authored and robbert-vdh committed Mar 21, 2022
1 parent 13f554d commit 8a1b34b
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 3 deletions.
14 changes: 14 additions & 0 deletions core/src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ impl<'a, T> Handle<'a, T> {
self
}

pub fn on_create<F>(self, callback: F) -> Self
where
F: Fn(&mut Context),
{
let prev = self.cx.current;
self.cx.current = self.entity();
(callback)(self.cx);
self.cx.current = prev;

self
}

pub fn bind<L, F>(self, lens: L, closure: F) -> Self
where
L: Lens,
Expand Down Expand Up @@ -375,4 +387,6 @@ impl<'a, T> Handle<'a, T> {
set_style!(border_radius_top_right, Units);
set_style!(border_radius_bottom_left, Units);
set_style!(border_radius_bottom_right, Units);


}
3 changes: 3 additions & 0 deletions core/src/views/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ pub use self::image::*;

mod menu;
pub use menu::*;

mod value_slider;
pub use value_slider::*;
29 changes: 26 additions & 3 deletions core/src/views/textbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub struct TextboxData {
dragx: f32,
on_edit: Option<Arc<dyn Fn(&mut Context, String) + Send + Sync>>,
on_submit: Option<Arc<dyn Fn(&mut Context, String) + Send + Sync>>,
on_edit_end: Option<Arc<dyn Fn(&mut Context) + Send + Sync>>,
}

impl TextboxData {
Expand All @@ -43,6 +44,7 @@ impl TextboxData {
dragx: -1.0,
on_edit: None,
on_submit: None,
on_edit_end: None,
}
}

Expand Down Expand Up @@ -404,6 +406,7 @@ pub enum TextEvent {
SetCaretEntity(Entity),
SetOnEdit(Option<Arc<dyn Fn(&mut Context, String) + Send + Sync>>),
SetOnSubmit(Option<Arc<dyn Fn(&mut Context, String) + Send + Sync>>),
SetOnEditEnd(Option<Arc<dyn Fn(&mut Context) + Send + Sync>>),
}

impl Model for TextboxData {
Expand Down Expand Up @@ -446,6 +449,9 @@ impl Model for TextboxData {
TextEvent::StartEdit => {
if !cx.current.is_disabled(cx) {
self.edit = true;
cx.focused = cx.current;
cx.capture();
cx.current.set_checked(cx, true);
self.selection_entity.set_visibility(cx, Visibility::Visible);
self.caret_entity.set_visibility(cx, Visibility::Visible);
}
Expand All @@ -455,6 +461,9 @@ impl Model for TextboxData {
self.edit = false;
self.selection_entity.set_visibility(cx, Visibility::Invisible);
self.caret_entity.set_visibility(cx, Visibility::Invisible);
if let Some(callback) = &self.on_edit_end {
(callback)(cx);
}
}

TextEvent::Submit => {
Expand Down Expand Up @@ -523,6 +532,10 @@ impl Model for TextboxData {
TextEvent::SetOnSubmit(on_submit) => {
self.on_submit = on_submit.clone();
}

TextEvent::SetOnEditEnd(on_edit_end) => {
self.on_edit_end = on_edit_end.clone();
}
}
}
}
Expand Down Expand Up @@ -553,6 +566,7 @@ where
dragx: -1.0,
on_edit: text_data.on_edit.clone(),
on_submit: text_data.on_submit.clone(),
on_edit_end: text_data.on_edit_end.clone(),
};
let real_current = cx.current;
cx.current = cx.current.parent(&cx.tree).unwrap();
Expand Down Expand Up @@ -620,6 +634,15 @@ impl<'a, L: Lens> Handle<'a, Textbox<L>> {

self
}

pub fn on_edit_end<F>(self, callback: F) -> Self
where
F: 'static + Fn(&mut Context) + Send + Sync,
{
self.cx.emit_to(self.entity, TextEvent::SetOnEditEnd(Some(Arc::new(callback))));

self
}
}

impl<L: Lens> View for Textbox<L>
Expand All @@ -642,9 +665,9 @@ where
// self.edit = true;
cx.emit(TextEvent::StartEdit);

cx.focused = cx.current;
cx.capture();
cx.current.set_checked(cx, true);
// cx.focused = cx.current;
// cx.capture();
// cx.current.set_checked(cx, true);
//}

// Hit test
Expand Down
184 changes: 184 additions & 0 deletions core/src/views/value_slider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
use std::marker::PhantomData;

use crate::{
Binding, Context, Element, Handle, Lens, LensExt, Model, MouseButton,
Units::*, View, WindowEvent, ZStack, Color, Label, Modifiers, Event, Textbox, Actions
};

use super::textbox::TextEvent;

#[derive(Lens)]
pub struct VSDataInternal {
edit: bool,
}

pub enum ValueSliderEvent {
SetEdit(bool),
OnSubmit(f32),
}

impl Model for VSDataInternal {
fn event(&mut self, _cx: &mut Context, event: &mut Event) {
if let Some(value_slider_event) = event.message.downcast() {
match value_slider_event {
ValueSliderEvent::SetEdit(flag) => {
self.edit = *flag;
}

_=> {}
}
}
}
}

pub struct ValueSlider<L> {
p: PhantomData<L>,
is_dragging: bool,
on_changing: Option<Box<dyn Fn(&mut Context, f32)>>,
}

impl<L> ValueSlider<L>
where
L: Lens<Target = f32>,
{
pub fn new(cx: &mut Context, lens: L) -> Handle<Self> {
Self {
p: PhantomData::default(),
is_dragging: false,
on_changing: None,
}.build2(cx, |cx|{

VSDataInternal {
edit: false,
}.build(cx);

ZStack::new(cx, |cx|{
Element::new(cx)
.height(Stretch(1.0))
.width(Stretch(1.0))
.background_color(Color::rgb(200, 200, 200))
.bind(lens.clone(), move |handle, l|{
let val = *l.get(handle.cx);
handle.width(Percentage(val * 100.0));
});
Binding::new(cx, VSDataInternal::edit, move |cx, edit|{
if *edit.get(cx) {
Textbox::new(cx, lens.clone().map(|val| format!("{:.2}", val)))
.on_create(|cx|{
cx.emit(TextEvent::StartEdit);
cx.emit(TextEvent::SelectAll);
})
.on_submit(|cx, txt|{
if let Ok(val) = txt.parse::<f32>() {
let val = val.clamp(0.0, 1.0);
cx.emit(ValueSliderEvent::OnSubmit(val));
}
})
.on_edit_end(|cx|{
cx.emit(ValueSliderEvent::SetEdit(false));
})
.child_space(Stretch(1.0))
.height(Stretch(1.0))
.width(Stretch(1.0));
} else {
Label::new(cx, lens.clone().map(|val| format!("{:.2}", val)))
.child_space(Stretch(1.0))
.height(Stretch(1.0))
.width(Stretch(1.0))
.hoverable(false);
};
});
});
})
}
}

impl<L> View for ValueSlider<L>
where
L: Lens<Target = f32>,
{
fn event(&mut self, cx: &mut Context, event: &mut Event) {

if let Some(value_slider_event) = event.message.downcast() {
match value_slider_event {
ValueSliderEvent::OnSubmit(val) => {

if let Some(callback) = &self.on_changing {
(callback)(cx, *val);
}
}

_=> {}
}
}

if let Some(window_event) = event.message.downcast() {
match window_event {
WindowEvent::MouseDown(button) if *button == MouseButton::Left => {

if cx.modifiers.contains(Modifiers::ALT) {
cx.emit(ValueSliderEvent::SetEdit(true));
} else {
if let Some(vs_data) = cx.data::<VSDataInternal>() {
if !vs_data.edit {
self.is_dragging = true;
cx.capture();

let mut dx = (cx.mouse.left.pos_down.0
- cx.cache.get_posx(cx.current))
/ cx.cache.get_width(cx.current);

dx = dx.clamp(0.0, 1.0);

if let Some(callback) = self.on_changing.take() {
(callback)(cx, dx);

self.on_changing = Some(callback);
}
}
}
}
}

WindowEvent::MouseUp(button) if *button == MouseButton::Left => {
self.is_dragging = false;
cx.release();
}

WindowEvent::MouseMove(x, _) => {
if self.is_dragging {

let mut dx = (*x - cx.cache.get_posx(cx.current))
/ cx.cache.get_width(cx.current);

dx = dx.clamp(0.0, 1.0);

if let Some(callback) = &self.on_changing {
(callback)(cx, dx);
}
}
}

_=> {}
}
}
}
}

impl<'a, L> Handle<'a, ValueSlider<L>>
where
L: Lens<Target = f32>,
{
pub fn on_changing<F>(self, callback: F) -> Self
where
F: 'static + Fn(&mut Context, f32),
{
if let Some(slider) =
self.cx.views.get_mut(&self.entity).and_then(|f| f.downcast_mut::<ValueSlider<L>>())
{
slider.on_changing = Some(Box::new(callback));
}

self
}
}
37 changes: 37 additions & 0 deletions examples/value_slider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use vizia::*;

#[derive(Lens)]
pub struct AppData {
val: f32,
}

pub enum AppEvent {
SetValue(f32),
}

impl Model for AppData {
fn event(&mut self, _cx: &mut Context, event: &mut Event) {
if let Some(app_event) = event.message.downcast() {
match app_event {
AppEvent::SetValue(val) => {
self.val = *val;
}
}
}
}
}

fn main() {
let mut window_description = WindowDescription::new();
Application::new(window_description, |cx| {
AppData { val: 0.5 }.build(cx);


ValueSlider::new(cx, AppData::val)
.on_changing(|cx, val| cx.emit(AppEvent::SetValue(val)))
.width(Pixels(300.0))
.height(Pixels(50.0))
.space(Stretch(1.0));
})
.run();
}

0 comments on commit 8a1b34b

Please sign in to comment.