Skip to content

Commit

Permalink
Switcher, h/v expand
Browse files Browse the repository at this point in the history
  • Loading branch information
ecton committed Nov 13, 2023
1 parent 07b9339 commit ee3813f
Show file tree
Hide file tree
Showing 12 changed files with 364 additions and 87 deletions.
22 changes: 6 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions examples/switcher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use gooey::value::Dynamic;
use gooey::widget::{MakeWidget, WidgetInstance};
use gooey::widgets::{Button, Label, Switcher};
use gooey::Run;

#[derive(Debug)]
enum ActiveContent {
Intro,
Success,
}

fn main() -> gooey::Result {
let active = Dynamic::new(ActiveContent::Intro);

Switcher::new(active.clone(), move |content| match content {
ActiveContent::Intro => intro(active.clone()),
ActiveContent::Success => success(active.clone()),
})
.contain()
.centered()
.expand()
.run()
}

fn intro(active: Dynamic<ActiveContent>) -> WidgetInstance {
const INTRO: &str = "This example demonstrates the Switcher<T> widget, which uses a mapping function to convert from a generic type to the widget it uses for its contents.";
Label::new(INTRO)
.and(
Button::new("Switch!")
.on_click(move |_| active.set(ActiveContent::Success))
.centered(),
)
.into_rows()
.make_widget()
}

fn success(active: Dynamic<ActiveContent>) -> WidgetInstance {
Label::new("The value changed to `ActiveContent::Success`!")
.and(
Button::new("Start Over")
.on_click(move |_| active.set(ActiveContent::Intro))
// .centered(),
)
.into_rows()
.make_widget()
}
36 changes: 28 additions & 8 deletions examples/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ use gooey::styles::components::{TextColor, WidgetBackground};
use gooey::styles::{ColorSource, ColorTheme, FixedTheme, SurfaceTheme, Theme, ThemePair};
use gooey::value::{Dynamic, MapEach};
use gooey::widget::MakeWidget;
use gooey::widgets::{Input, Label, Scroll, Slider, Stack, Themed};
use gooey::widgets::{Input, Label, ModeSwitch, Scroll, Slider, Stack, Themed};
use gooey::window::ThemeMode;
use gooey::Run;
use kludgine::figures::units::Lp;
use kludgine::Color;

const PRIMARY_HUE: f32 = 240.;
Expand Down Expand Up @@ -59,16 +58,22 @@ fn main() -> gooey::Result {
.and(neutral_editor)
.and(neutral_variant_editor),
))
.and(theme(default_theme.map_each(|theme| theme.dark), "Dark"))
.and(theme(default_theme.map_each(|theme| theme.light), "Light"))
.and(fixed_themes(
default_theme.map_each(|theme| theme.primary_fixed),
default_theme.map_each(|theme| theme.secondary_fixed),
default_theme.map_each(|theme| theme.tertiary_fixed),
))
.and(theme(
default_theme.map_each(|theme| theme.dark),
ThemeMode::Dark,
))
.and(theme(
default_theme.map_each(|theme| theme.light),
ThemeMode::Light,
)),
),
)
.pad_by(Lp::points(16))
.pad()
.expand()
.into_window()
.with_theme_mode(theme_mode)
Expand Down Expand Up @@ -132,6 +137,7 @@ fn fixed_themes(
.and(fixed_theme(secondary, "Secondary"))
.and(fixed_theme(tertiary, "Tertiary")),
)
.contain()
.expand()
}

Expand All @@ -156,12 +162,18 @@ fn fixed_theme(theme: Dynamic<FixedTheme>, label: &str) -> impl MakeWidget {
color,
)),
)
.contain()
.expand()
}

fn theme(theme: Dynamic<Theme>, label: &str) -> impl MakeWidget {
Stack::rows(
Label::new(label)
fn theme(theme: Dynamic<Theme>, mode: ThemeMode) -> impl MakeWidget {
ModeSwitch::new(
mode,
Stack::rows(
Label::new(match mode {
ThemeMode::Light => "Light",
ThemeMode::Dark => "Dark",
})
.and(
Stack::columns(
color_theme(theme.map_each(|theme| theme.primary), "Primary")
Expand All @@ -175,9 +187,12 @@ fn theme(theme: Dynamic<Theme>, label: &str) -> impl MakeWidget {
))
.and(color_theme(theme.map_each(|theme| theme.error), "Error")),
)
.contain()
.expand(),
)
.and(surface_theme(theme.map_each(|theme| theme.surface))),
)
.contain(),
)
.expand()
}
Expand All @@ -199,6 +214,7 @@ fn surface_theme(theme: Dynamic<SurfaceTheme>) -> impl MakeWidget {
on_color.clone(),
)),
)
.contain()
.expand()
.and(
Stack::columns(
Expand Down Expand Up @@ -228,6 +244,7 @@ fn surface_theme(theme: Dynamic<SurfaceTheme>) -> impl MakeWidget {
on_color.clone(),
)),
)
.contain()
.expand(),
)
.and(
Expand All @@ -254,9 +271,11 @@ fn surface_theme(theme: Dynamic<SurfaceTheme>) -> impl MakeWidget {
on_color,
)),
)
.contain()
.expand(),
),
)
.contain()
.expand()
}

Expand Down Expand Up @@ -289,6 +308,7 @@ fn color_theme(theme: Dynamic<ColorTheme>, label: &str) -> impl MakeWidget {
container,
)),
)
.contain()
.expand()
}

Expand Down
46 changes: 44 additions & 2 deletions src/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
//! use gooey::value::Dynamic;
//!
//! let value = Dynamic::new(0);
//!
//! let mut reader = value.create_reader();
//! value
//! .transition_to(100)
//! .over(Duration::from_millis(100))
//! .with_easing(EaseInOutElastic)
//! .launch();
//! drop(value);
//!
//! let mut reader = value.into_reader();
//! while reader.block_until_updated() {
//! println!("{}", reader.get());
//! }
Expand Down Expand Up @@ -726,6 +726,48 @@ impl LinearInterpolate for Color {
}
}

/// A wrapper that implements [`LinearInterpolate`] such that the value switches
/// after 50%.
///
/// This wrapper can be used to add [`LinearInterpolate`] to types that normally
/// don't support interpolation.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct BinaryLerp<T>(T);

impl<T> LinearInterpolate for BinaryLerp<T>
where
T: Clone + PartialEq,
{
fn lerp(&self, target: &Self, percent: f32) -> Self {
if false.lerp(&true, percent) {
target.clone()
} else {
self.clone()
}
}
}

/// A wrapper that implements [`LinearInterpolate`] such that the target value
/// is immediately returned as long as percent is > 0.
///
/// This wrapper can be used to add [`LinearInterpolate`] to types that normally
/// don't support interpolation.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct ImmediateLerp<T>(T);

impl<T> LinearInterpolate for ImmediateLerp<T>
where
T: Clone + PartialEq,
{
fn lerp(&self, target: &Self, percent: f32) -> Self {
if percent > 0. {
target.clone()
} else {
self.clone()
}
}
}

/// Calculates the ratio of one value against a minimum and maximum.
pub trait PercentBetween {
/// Return the percentage that `self` is between `min` and `max`.
Expand Down
2 changes: 1 addition & 1 deletion src/styles/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::styles::{Dimension, FocusableWidgets, VisualOrder};
/// /// This component defaults to picking a contrasting color between `TextColor` and `SurfaceColor`
/// ContrastingColor(Color, "contrasting_color", contrasting!(ThemedComponent, TextColor, SurfaceColor))
/// /// This component shows how to use a closure for nearly infinite flexibility in computing the default value.
/// ClosureDefaultComponent(Color, "closure_component", |context| context.query_style(&TextColor))
/// ClosureDefaultComponent(Color, "closure_component", |context| context.get(&TextColor))
/// }
/// }
/// ```
Expand Down
1 change: 1 addition & 0 deletions src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ impl TreeData {

while let Some(node) = detached_nodes.pop() {
let mut node = self.nodes.remove(node).expect("detached node missing");
self.nodes_by_id.remove(&node.widget.id());
detached_nodes.append(&mut node.children);
}
}
Expand Down
24 changes: 20 additions & 4 deletions src/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ pub trait Widget: Send + UnwindSafe + Debug + 'static {
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx>;

/// Return true if this widget should expand to fill the window when it is
/// the root widget.
fn expand_if_at_root(&self) -> Option<bool> {
Some(false)
}

/// The widget has been mounted into a parent widget.
#[allow(unused_variables)]
fn mounted(&mut self, context: &mut EventContext<'_, '_>) {}
Expand Down Expand Up @@ -227,9 +233,8 @@ pub trait WrapperWidget: Debug + Send + UnwindSafe + 'static {
available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> WrappedLayout {
let child = self.child_mut().mounted(&mut context.as_event_context());

let adjusted_space = self.adjust_child_constraint(available_space, context);
let child = self.child_mut().mounted(&mut context.as_event_context());
let size = context
.for_other(&child)
.layout(adjusted_space)
Expand Down Expand Up @@ -420,9 +425,8 @@ where
available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> {
let child = self.child_mut().mounted(&mut context.as_event_context());

let layout = self.layout_child(available_space, context);
let child = self.child_mut().mounted(&mut context.as_event_context());
context.set_child_layout(&child, layout.child);
layout.size
}
Expand Down Expand Up @@ -606,6 +610,18 @@ pub trait MakeWidget: Sized {
Expand::weighted(weight, self)
}

/// Expands `self` to grow to fill its parent horizontally.
#[must_use]
fn expand_horizontally(self) -> Expand {
Expand::horizontal(self)
}

/// Expands `self` to grow to fill its parent vertically.
#[must_use]
fn expand_vertically(self) -> Expand {
Expand::horizontal(self)
}

/// Aligns `self` to the center vertically and horizontally.
#[must_use]
fn centered(self) -> Align {
Expand Down
2 changes: 2 additions & 0 deletions src/widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod slider;
mod space;
pub mod stack;
mod style;
mod switcher;
mod themed;
mod tilemap;

Expand All @@ -31,5 +32,6 @@ pub use slider::Slider;
pub use space::Space;
pub use stack::Stack;
pub use style::Style;
pub use switcher::Switcher;
pub use themed::Themed;
pub use tilemap::TileMap;
Loading

0 comments on commit ee3813f

Please sign in to comment.