Skip to content

Commit

Permalink
wip: colorpicker
Browse files Browse the repository at this point in the history
  • Loading branch information
ten3roberts committed Dec 11, 2024
1 parent 9635ec3 commit a2dff69
Show file tree
Hide file tree
Showing 8 changed files with 410 additions and 146 deletions.
441 changes: 317 additions & 124 deletions examples/colorpicker.rs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions violet-core/src/widget/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use crate::{
Scope, Widget,
};

use super::Stack;

/// A rectangular widget
#[derive(Debug, Clone)]
pub struct Rectangle {
Expand Down Expand Up @@ -146,6 +148,10 @@ pub fn label(text: impl Into<String>) -> Text {
Text::new(text).with_margin(spacing_small())
}

pub fn header(text: impl Into<String>) -> Stack<Text> {
Stack::new(Text::new(text).with_margin(spacing_small())).with_padding(spacing_small())
}

/// A text with a margin
pub fn title(text: impl Into<String>) -> Text {
Text::new(text)
Expand Down
5 changes: 5 additions & 0 deletions violet-core/src/widget/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ impl<W> Stack<W> {
self
}

pub fn with_background_opt(mut self, background: impl Into<Option<Background>>) -> Self {
self.style.background = background.into();
self
}

/// Contain margins within the widget
pub fn with_contain_margins(mut self, contain_margins: bool) -> Self {
self.layout.contain_margins = contain_margins;
Expand Down
4 changes: 2 additions & 2 deletions violet-core/src/widget/interactive/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ impl<W> Button<W> {
style: Default::default(),
size: WidgetSize::default()
.with_padding(spacing_medium())
.with_margin(spacing_medium())
.with_min_size(Unit::px2(28.0, 28.0)),
.with_margin(spacing_medium()),
// .with_min_size(Unit::px2(28.0, 28.0)),
is_pressed: false,
}
}
Expand Down
17 changes: 14 additions & 3 deletions violet-core/src/widget/interactive/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
io,
state::{State, StateDuplex, StateSink, StateStream},
style::{
interactive_active, interactive_hover, interactive_passive, spacing_medium, Background,
interactive_active, interactive_hover, interactive_passive, spacing_small, Background,
SizeExt, StyleExt, ValueOrRef, WidgetSize,
},
text::{CursorLocation, LayoutGlyphs},
Expand Down Expand Up @@ -66,10 +66,21 @@ impl TextInput {
style: Default::default(),
size: WidgetSize::default()
.with_min_size(Unit::px2(16.0, 16.0))
.with_margin(spacing_medium())
.with_padding(spacing_medium()),
.with_margin(spacing_small())
.with_padding(spacing_small()),
}
}

pub fn new_parsed<T>(content: impl 'static + Send + Sync + StateDuplex<Item = T>) -> Self
where
T: 'static + Send + Sync + ToString + FromStr,
{
let content = content
.filter_map(|v| Some(v.to_string()), |v| v.parse().ok())
.prevent_feedback();

Self::new(content)
}
}

impl StyleExt for TextInput {
Expand Down
56 changes: 56 additions & 0 deletions violet-core/src/widget/interactive/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,59 @@
use winit::event::ElementState;

use crate::{
input::{focusable, on_mouse_input},
ScopeRef,
};

use super::Widget;

pub mod button;
pub mod input;
pub mod slider;

pub trait InteractiveExt {
fn on_press<F: 'static + Send + Sync + FnMut(&ScopeRef<'_>)>(
self,
on_press: F,
) -> OnPress<Self, F>
where
Self: Sized;
}

impl<W: Widget> InteractiveExt for W {
fn on_press<F: 'static + Send + Sync + FnMut(&ScopeRef<'_>)>(
self,
on_press: F,
) -> OnPress<Self, F>
where
Self: Sized,
{
OnPress {
widget: self,
func: on_press,
}
}
}

pub struct OnPress<W, F> {
widget: W,
func: F,
}

impl<W, F> Widget for OnPress<W, F>
where
W: Widget,
F: 'static + Send + Sync + FnMut(&ScopeRef<'_>),
{
fn mount(mut self, scope: &mut crate::Scope<'_>) {
self.widget.mount(scope);

scope
.set_default(focusable())
.on_event(on_mouse_input(), move |scope, input| {
if input.state == ElementState::Released {
(self.func)(scope)
}
});
}
}
25 changes: 9 additions & 16 deletions violet-core/src/widget/interactive/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use flax::{component, Component, Entity, EntityRef};
use futures::{stream::BoxStream, StreamExt};
use futures_signals::signal::Mutable;
use glam::Vec2;
use palette::Srgba;
use palette::{num::Clamp, Srgba};

Check warning on line 7 in violet-core/src/widget/interactive/slider.rs

View workflow job for this annotation

GitHub Actions / test_miri

unused import: `num::Clamp`

Check warning on line 7 in violet-core/src/widget/interactive/slider.rs

View workflow job for this annotation

GitHub Actions / check

unused import: `num::Clamp`

Check warning on line 7 in violet-core/src/widget/interactive/slider.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `num::Clamp`

Check warning on line 7 in violet-core/src/widget/interactive/slider.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `num::Clamp`
use winit::event::ElementState;

use super::input::TextInput;
Expand Down Expand Up @@ -131,14 +131,13 @@ impl<V: SliderValue> Widget for Slider<V> {
start_value: f32,
min: f32,
max: f32,
dst: &dyn StateDuplex<Item = V>,
) {
) -> V {
let rect = entity.get_copy(rect()).unwrap();
let padding = entity.get_copy(padding()).unwrap_or_default();

let value = (drag_distance / (rect.size().x - padding.size().x)) * (max - min) + min;

dst.send(V::from_progress(start_value + value));
V::from_progress((start_value + value).clamp(min, max))
}

let handle = SliderHandle {
Expand Down Expand Up @@ -186,19 +185,13 @@ impl<V: SliderValue> Widget for Slider<V> {
to_owned![value];
move |scope, input| {
let drag_start = &mut *drag_start.lock_mut();
if let Some((start, start_value)) = drag_start {
update_scrubbed(
scope,
input.local_pos.x - *start,
*start_value,
min,
max,
&*value,
)
let progress = if let Some((start, start_value)) = drag_start {
update_scrubbed(scope, input.local_pos.x - *start, *start_value, min, max)
} else {
let progress = get_progress_value(scope, input.local_pos.x, min, max);
value.send(progress);
}
get_progress_value(scope, input.local_pos.x, min, max)
};

value.send(progress);
}
});

Expand Down
2 changes: 1 addition & 1 deletion violet-core/src/widget/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use flax::{component::ComponentValue, components::name, Component};
pub use future::{SignalWidget, StreamWidget};
use futures_signals::signal::Mutable;
pub use image::*;
pub use interactive::{button::*, input::*, slider::*};
pub use interactive::{button::*, input::*, slider::*, InteractiveExt};
pub use scroll::ScrollArea;

/// A widget is a description of a part of the Ui with the capability to mount itself into the world.
Expand Down

0 comments on commit a2dff69

Please sign in to comment.