Skip to content

Commit

Permalink
chore: style improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
ten3roberts committed Nov 17, 2024
1 parent 9f038b1 commit d4f8aa9
Show file tree
Hide file tree
Showing 19 changed files with 282 additions and 114 deletions.
2 changes: 1 addition & 1 deletion violet-core/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl Frame {
&mut self,
id: Entity,
component: Component<T>,
on_change: impl Fn(Option<&T>) + 'static,
mut on_change: impl FnMut(Option<&T>) + 'static,
) {
let (tx, rx) = flume::unbounded();

Expand Down
6 changes: 3 additions & 3 deletions violet-core/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl InputState {
self.focused.as_ref()
}

fn focused_entity<'a>(&self, world: &'a World) -> Option<EntityRef<'a>> {
pub fn focused_entity<'a>(&self, world: &'a World) -> Option<EntityRef<'a>> {
self.focused.as_ref().and_then(|v| world.entity(v.id).ok())
}

Expand All @@ -235,7 +235,7 @@ impl InputState {
on_focus(&s, true);
}

let sticky = entity.has(focus_sticky());
let sticky = entity.has(keep_focus());
self.focused = Some(FocusedEntity { id: new, sticky });
} else {
self.focused = None;
Expand Down Expand Up @@ -276,7 +276,7 @@ pub struct KeyboardInput {
pub type InputEventHandler<T> = Box<dyn Send + Sync + FnMut(&ScopeRef<'_>, T)>;

component! {
pub focus_sticky: (),
pub keep_focus: (),
pub focusable: (),
pub on_focus: InputEventHandler<bool>,
pub on_cursor_move: InputEventHandler<CursorMove>,
Expand Down
2 changes: 1 addition & 1 deletion violet-core/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ impl<'a> Scope<'a> {
pub fn monitor<T: ComponentValue>(
&mut self,
component: Component<T>,
on_change: impl Fn(Option<&T>) + 'static,
on_change: impl FnMut(Option<&T>) + 'static,
) {
self.frame.monitor(self.id, component, on_change);
}
Expand Down
36 changes: 36 additions & 0 deletions violet-core/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,42 @@ pub trait StateStream: State {
pub trait StateSink: State {
/// Send a value to the state
fn send(&self, value: Self::Item);

fn map_sink<F, T>(self, f: F) -> MapSink<Self, F, T>
where
F: FnMut(T) -> Self::Item,
Self: Sized,
{
MapSink {
sink: self,
func: f,
_marker: PhantomData,
}
}
}

pub struct MapSink<S, F, T> {
sink: S,
func: F,
_marker: PhantomData<T>,
}

impl<S, F, T> State for MapSink<S, F, T>
where
S: StateSink,
F: Fn(T) -> S::Item,
{
type Item = T;
}

impl<S, F, T> StateSink for MapSink<S, F, T>
where
S: StateSink,
F: Fn(T) -> S::Item,
{
fn send(&self, value: Self::Item) {
self.sink.send((self.func)(value))
}
}

/// Allows sending and receiving a value to a state
Expand Down
23 changes: 18 additions & 5 deletions violet-core/src/style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,12 @@ pub fn setup_stylesheet() -> EntityBuilder {
.set(primary_surface(), STONE_950)
.set(primary_element(), PLATINUM_100)
.set(secondary_surface(), STONE_900)
.set(accent_surface(), PLATINUM_800)
.set(accent_element(), EMERALD_500)
.set(success_surface(), EMERALD_800)
.set(success_element(), EMERALD_500)
.set(accent_element(), EMERALD_400)
.set(accent_surface(), PLATINUM_600)
.set(success_surface(), EMERALD_600)
.set(success_element(), EMERALD_400)
.set(info_surface(), TEAL_800)
.set(info_element(), TEAL_200)
.set(warning_surface(), AMBER_800)
.set(warning_element(), AMBER_500)
.set(danger_surface(), REDWOOD_800)
Expand All @@ -301,7 +303,11 @@ pub fn setup_stylesheet() -> EntityBuilder {
// spacing
.set(spacing_small(), 4.0.into())
.set(spacing_medium(), 8.0.into())
.set(spacing_large(), 16.0.into());
.set(spacing_large(), 16.0.into())
// text size
.set(text_small(), 16.0.into())

Check warning on line 308 in violet-core/src/style/mod.rs

View workflow job for this annotation

GitHub Actions / Clippy

useless conversion to the same type: `f32`
.set(text_medium(), 18.0.into())

Check warning on line 309 in violet-core/src/style/mod.rs

View workflow job for this annotation

GitHub Actions / Clippy

useless conversion to the same type: `f32`
.set(text_large(), 24.0.into());

Check warning on line 310 in violet-core/src/style/mod.rs

View workflow job for this annotation

GitHub Actions / Clippy

useless conversion to the same type: `f32`

builder
}
Expand All @@ -326,6 +332,9 @@ flax::component! {
pub success_surface: Srgba,
pub success_element: Srgba,

pub info_surface: Srgba,
pub info_element: Srgba,

pub warning_surface: Srgba,
pub warning_element: Srgba,

Expand All @@ -343,4 +352,8 @@ flax::component! {
pub spacing_small: Edges,
pub spacing_medium: Edges,
pub spacing_large: Edges,

pub text_small: f32,
pub text_medium: f32,
pub text_large: f32,
}
80 changes: 26 additions & 54 deletions violet-core/src/widget/basic.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use glam::Vec2;
use image::DynamicImage;

Check warning on line 2 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / check

unused import: `image::DynamicImage`

Check warning on line 2 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `image::DynamicImage`

Check warning on line 2 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / test_miri

unused import: `image::DynamicImage`

Check warning on line 2 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `image::DynamicImage`
use palette::Srgba;
use tracing::Value;

Check warning on line 4 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / check

unused import: `tracing::Value`

Check warning on line 4 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / Clippy

unused import: `tracing::Value`

Check warning on line 4 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / test_miri

unused import: `tracing::Value`

Check warning on line 4 in violet-core/src/widget/basic.rs

View workflow job for this annotation

GitHub Actions / test

unused import: `tracing::Value`

use crate::{
assets::AssetKey,

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

View workflow job for this annotation

GitHub Actions / check

unused imports: `assets::AssetKey`, `colors::REDWOOD_500`, and `font_size`

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

View workflow job for this annotation

GitHub Actions / Clippy

unused imports: `assets::AssetKey`, `colors::REDWOOD_500`, and `font_size`

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

View workflow job for this annotation

GitHub Actions / test_miri

unused imports: `assets::AssetKey`, `colors::REDWOOD_500`, and `font_size`

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

View workflow job for this annotation

GitHub Actions / test

unused imports: `assets::AssetKey`, `colors::REDWOOD_500`, and `font_size`
components::{self, color, draw_shape, font_size, text, text_wrap},
shape,
style::{colors::REDWOOD_500, spacing_small, SizeExt, StyleExt, ValueOrRef, WidgetSize},
style::{
colors::REDWOOD_500, spacing_small, text_large, text_medium, text_small, SizeExt, StyleExt,
ValueOrRef, WidgetSize,
},
text::{TextSegment, Wrap},
unit::Unit,
Scope, Widget,
Expand Down Expand Up @@ -46,65 +50,17 @@ impl SizeExt for Rectangle {
}
}

pub struct Image<K> {
image: K,
size: WidgetSize,
aspect_ratio: Option<f32>,
}

impl<K> Image<K> {
pub fn new(image: K) -> Self {
Self {
image,
size: Default::default(),
aspect_ratio: None,
}
}

pub fn with_aspect_ratio(mut self, aspect_ratio: f32) -> Self {
self.aspect_ratio = Some(aspect_ratio);
self
}
}

impl<K> Widget for Image<K>
where
K: AssetKey<DynamicImage>,
{
fn mount(self, scope: &mut Scope) {
let image = scope.assets_mut().try_load(&self.image).ok();
if let Some(image) = image {
self.size.mount(scope);
scope
.set(color(), Srgba::new(1.0, 1.0, 1.0, 1.0))
.set(draw_shape(shape::shape_rectangle()), ())
.set(components::image(), image)
.set_opt(components::aspect_ratio(), self.aspect_ratio);
} else {
label("Image not found")
.with_color(REDWOOD_500)
.mount(scope);
}
}
}

impl<K> SizeExt for Image<K> {
fn size_mut(&mut self) -> &mut WidgetSize {
&mut self.size
}
}

/// Style and decorate text
pub struct TextStyle {
font_size: f32,
font_size: ValueOrRef<f32>,
wrap: Wrap,
color: Option<Srgba>,
}

impl Default for TextStyle {
fn default() -> Self {
Self {
font_size: 16.0,
font_size: text_small().into(),
wrap: Wrap::Word,
color: None,
}
Expand All @@ -131,8 +87,8 @@ impl Text {
}

/// Set the font_size
pub fn with_font_size(mut self, font_size: f32) -> Self {
self.style.font_size = font_size;
pub fn with_font_size(mut self, font_size: impl Into<ValueOrRef<f32>>) -> Self {
self.style.font_size = font_size.into();
self
}

Expand Down Expand Up @@ -167,9 +123,12 @@ impl Widget for Text {
fn mount(self, scope: &mut Scope) {
self.size.mount(scope);

let stylesheet = scope.stylesheet();
let font_size = self.style.font_size.resolve(&stylesheet);

scope
.set(draw_shape(shape::shape_text()), ())
.set(font_size(), self.style.font_size)
.set(components::font_size(), font_size)
.set(text_wrap(), self.style.wrap)
.set(text(), self.text)
.set_opt(color(), self.style.color);
Expand All @@ -181,6 +140,19 @@ pub fn label(text: impl Into<String>) -> Text {
Text::new(text).with_margin(spacing_small())
}

/// A text with a margin
pub fn title(text: impl Into<String>) -> Text {
Text::new(text)
.with_font_size(text_large())
.with_margin(spacing_small())
}

pub fn subtitle(text: impl Into<String>) -> Text {
Text::new(text)
.with_font_size(text_medium())
.with_margin(spacing_small())
}

/// Allows a widget to be manually positioned and offset
pub struct Positioned<W> {
offset: Unit<Vec2>,
Expand Down
7 changes: 5 additions & 2 deletions violet-core/src/widget/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ pub struct Stack<W> {
}

impl<W> Stack<W> {
pub fn new(items: W) -> Self {
pub fn new(items: W) -> Self
where
W: WidgetCollection,
{
Self {
items,
layout: StackLayout::default(),
Expand Down Expand Up @@ -287,7 +290,7 @@ pub fn card<W: Widget>(widget: W) -> Stack<W> {
.with_margin(spacing_medium())
}

pub fn pill<W>(widget: W) -> Stack<W> {
pub fn pill<W: Widget>(widget: W) -> Stack<W> {
Stack::new(widget)
// TODO: semantic color and sizing increment
.with_background(Background::new(primary_surface()))
Expand Down
10 changes: 10 additions & 0 deletions violet-core/src/widget/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ where
S: Stream,
S::Item: Widget;

impl<S> StreamWidget<S>
where
S: 'static + Stream,
S::Item: Widget,
{
pub fn new(widget: S) -> Self {
Self(widget)
}
}

impl<S> Widget for StreamWidget<S>
where
S: 'static + Stream,
Expand Down
60 changes: 60 additions & 0 deletions violet-core/src/widget/image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use image::DynamicImage;
use palette::Srgba;

use crate::{
assets::AssetKey,
components::{self, color, draw_shape},
shape,
style::{colors::REDWOOD_500, SizeExt, WidgetSize},
Scope,
};

use super::{label, Widget};

pub struct Image<K> {
image: K,
size: WidgetSize,
aspect_ratio: Option<f32>,
}

impl<K> Image<K> {
pub fn new(image: K) -> Self {
Self {
image,
size: Default::default(),
aspect_ratio: None,
}
}

pub fn with_aspect_ratio(mut self, aspect_ratio: f32) -> Self {
self.aspect_ratio = Some(aspect_ratio);
self
}
}

impl<K> Widget for Image<K>
where
K: AssetKey<DynamicImage>,
{
fn mount(self, scope: &mut Scope) {
let image = scope.assets_mut().try_load(&self.image).ok();
if let Some(image) = image {
self.size.mount(scope);
scope
.set(color(), Srgba::new(1.0, 1.0, 1.0, 1.0))
.set(draw_shape(shape::shape_rectangle()), ())
.set(components::image(), image)
.set_opt(components::aspect_ratio(), self.aspect_ratio);
} else {
label("Image not found")
.with_color(REDWOOD_500)
.mount(scope);
}
}
}

impl<K> SizeExt for Image<K> {
fn size_mut(&mut self) -> &mut WidgetSize {
&mut self.size
}
}
Loading

0 comments on commit d4f8aa9

Please sign in to comment.