Skip to content

Commit

Permalink
Moved example generation into cushy
Browse files Browse the repository at this point in the history
Undocumented and unsupported, but this allows generating example images.

This push is testing that the image makes it through CI.

Refs #125
  • Loading branch information
ecton committed May 12, 2024
1 parent be7145a commit 15b8b3e
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 156 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ jobs:
cargo install mdbook-variables
- name: Regenerate Example Images
run: |
CAPTURE=1 cargo test -p cushy --examples
- name: Regenerate Guide Example Images
run: |
CAPTURE=1 cargo test -p guide-examples --examples
Expand Down
21 changes: 14 additions & 7 deletions examples/theme.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::fmt::Write;

use cushy::styles::components::{TextColor, WidgetBackground};
use cushy::styles::components::{TextColor, TextSize, WidgetBackground};
use cushy::styles::{
ColorScheme, ColorSchemeBuilder, ColorSource, ColorTheme, FixedTheme, SurfaceTheme, Theme,
ThemePair,
ColorScheme, ColorSchemeBuilder, ColorSource, ColorTheme, Dimension, FixedTheme, SurfaceTheme,
Theme, ThemePair,
};
use cushy::value::{Destination, Dynamic, MapEachCloned, Source};
use cushy::widget::MakeWidget;
Expand All @@ -13,14 +13,17 @@ use cushy::widgets::input::InputValue;
use cushy::widgets::slider::Slidable;
use cushy::widgets::Space;
use cushy::window::ThemeMode;
use cushy::{Open, PendingApp};
use cushy::{Cushy, Open, PendingApp};
use figures::units::Lp;
use kludgine::Color;
use palette::OklabHue;

fn main() -> cushy::Result {
let app = PendingApp::default();
theme_editor(app.cushy().clone()).into_window().run_in(app)
}

fn theme_editor(cushy: Cushy) -> impl MakeWidget {
let (theme_mode, theme_switcher) = dark_mode_picker();

let scheme = Scheme::from(ColorScheme::default());
Expand Down Expand Up @@ -79,7 +82,6 @@ fn main() -> cushy::Result {
.and(editors.neutral.1)
.and(editors.neutral_variant.1)
.and("Copy to Clipboard".into_button().on_click({
let cushy = app.cushy().clone();
move |_| {
if let Some(mut clipboard) = cushy.clipboard_guard() {
let builder = color_scheme_builder.get();
Expand Down Expand Up @@ -115,9 +117,7 @@ fn main() -> cushy::Result {
.themed(theme)
.pad()
.expand()
.into_window()
.themed_mode(theme_mode)
.run_in(app)
}

struct Scheme<Primary, Other = Primary> {
Expand Down Expand Up @@ -436,6 +436,7 @@ fn color_theme(theme: Dynamic<ColorTheme>, label: &str) -> impl MakeWidget {
fn swatch(background: Dynamic<Color>, label: &str, text: Dynamic<Color>) -> impl MakeWidget {
label
.with(&TextColor, text)
.with(&TextSize, Dimension::Lp(Lp::points(8)))
.with(&WidgetBackground, background)
.fit_horizontally()
.fit_vertically()
Expand Down Expand Up @@ -492,3 +493,9 @@ impl FormatRust for ColorSchemeBuilder {
}
}
}

#[test]
fn runs() {
let theme_editor = || theme_editor(Cushy::default());
cushy::example!(theme_editor, 1600, 900).untested_still_frame();
}
3 changes: 1 addition & 2 deletions guide/guide-examples/examples/align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use cushy::styles::ThemePair;
use cushy::widget::MakeWidget;
use cushy::widgets::grid::{GridDimension, GridWidgets};
use cushy::widgets::{Grid, Space};
use guide_examples::book_example;

// ANCHOR: content
fn content() -> impl MakeWidget {
Expand Down Expand Up @@ -84,7 +83,7 @@ fn main() {
let theme = ThemePair::default();
let container_color = theme.dark.surface.low_container;
let primary = theme.dark.primary.color;
book_example!(align).still_frame(|recorder| {
cushy::example!(align).still_frame(|recorder| {
const LEFT: u32 = 145;
const RIGHT: u32 = 705;
const H_CENTER: u32 = (RIGHT + LEFT) / 2;
Expand Down
2 changes: 1 addition & 1 deletion guide/guide-examples/examples/composition-makewidget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn composition_makewidget() -> impl cushy::widget::MakeWidget {
}

fn main() {
guide_examples::book_example!(composition_makewidget).untested_still_frame();
cushy::example!(composition_makewidget).untested_still_frame();
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion guide/guide-examples/examples/composition-widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ fn composition_widget() -> impl cushy::widget::MakeWidget {
}

fn main() {
guide_examples::book_example!(composition_widget).untested_still_frame();
cushy::example!(composition_widget).untested_still_frame();
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion guide/guide-examples/examples/composition-wrapperwidget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ fn composition_wrapperwidget() -> impl cushy::widget::MakeWidget {
}

fn main() {
guide_examples::book_example!(composition_wrapperwidget).untested_still_frame();
cushy::example!(composition_wrapperwidget).untested_still_frame();
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion guide/guide-examples/examples/hello-world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ fn book() {
"Hello, World!"
}

guide_examples::book_example!(hello_world).untested_still_frame();
cushy::example!(hello_world).untested_still_frame();
}
2 changes: 1 addition & 1 deletion guide/guide-examples/examples/intro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn book() {
name_input.and(greeting).into_rows()
}

guide_examples::book_example!(intro).animated(|animation| {
cushy::example!(intro).animated(|animation| {
animation.wait_for(Duration::from_secs(1)).unwrap();
animation
.animate_text_input("Ferris 🦀", Duration::from_secs(1))
Expand Down
3 changes: 1 addition & 2 deletions guide/guide-examples/examples/thread-progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::time::Duration;
use cushy::value::{Destination, Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::progress::Progressable;
use guide_examples::book_example;

fn thread_progress() -> impl MakeWidget {
// ANCHOR: example
Expand All @@ -23,7 +22,7 @@ fn thread_progress() -> impl MakeWidget {
}

fn main() {
book_example!(thread_progress).animated(|recorder| {
cushy::example!(thread_progress).animated(|recorder| {
recorder.wait_for(Duration::from_secs(2)).unwrap();
});
}
Expand Down
140 changes: 0 additions & 140 deletions guide/guide-examples/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,141 +1 @@
use std::panic::AssertUnwindSafe;
use std::path::PathBuf;

use cushy::figures::units::Px;
use cushy::figures::Size;
use cushy::widget::MakeWidget;
use cushy::widgets::container::ContainerShadow;
use cushy::window::{AnimationRecorder, Rgba8, VirtualRecorder, VirtualRecorderBuilder};

pub struct BookExampleBuilder {
name: &'static str,
recorder: VirtualRecorderBuilder<Rgba8>,
}

impl BookExampleBuilder {
pub fn finish(self) -> BookExample {
BookExample {
name: self.name,
recorder: self.recorder.finish().expect("error creating recorder"),
}
}

pub fn untested_still_frame(self) {
self.finish().untested_still_frame()
}

pub fn prepare_with<Prepare>(self, prepare: Prepare) -> BookExample
where
Prepare: FnOnce(&mut VirtualRecorder<Rgba8>),
{
self.finish().prepare_with(prepare)
}

pub fn still_frame<Test>(self, test: Test)
where
Test: FnOnce(&mut VirtualRecorder<Rgba8>),
{
self.finish().still_frame(test);
}

pub fn animated<Test>(self, test: Test)
where
Test: FnOnce(&mut AnimationRecorder<'_, Rgba8>),
{
self.finish().animated(test);
}
}

fn target_dir() -> PathBuf {
let target_dir = std::env::current_dir()
.expect("missing current dir")
.parent()
.expect("missing guide folder")
.join("src")
.join("examples");
assert!(
target_dir.is_dir(),
"current directory is not guide-examples"
);

target_dir
}

pub struct BookExample {
name: &'static str,
recorder: VirtualRecorder<Rgba8>,
}

impl BookExample {
pub fn build(name: &'static str, interface: impl MakeWidget) -> BookExampleBuilder {
BookExampleBuilder {
name,
recorder: interface
.contain()
.shadow(ContainerShadow::drop(Px::new(16)))
.width(Px::new(750))
.build_recorder()
.with_alpha()
.resize_to_fit()
.size(Size::new(750, 432)),
}
}

pub fn untested_still_frame(self) {
self.still_frame(|_| {});
}

pub fn prepare_with<Prepare>(mut self, prepare: Prepare) -> Self
where
Prepare: FnOnce(&mut VirtualRecorder<Rgba8>),
{
prepare(&mut self.recorder);
self
}

pub fn still_frame<Test>(mut self, test: Test)
where
Test: FnOnce(&mut VirtualRecorder<Rgba8>),
{
let capture = std::env::var("CAPTURE").is_ok();
let errored =
std::panic::catch_unwind(AssertUnwindSafe(|| test(&mut self.recorder))).is_err();
if errored || capture {
let path = target_dir().join(format!("{}.png", self.name));
self.recorder
.image()
.save(&path)
.expect("error saving file");
println!("Wrote {}", path.display());

if errored {
std::process::exit(-1);
}
}
}

pub fn animated<Test>(mut self, test: Test)
where
Test: FnOnce(&mut AnimationRecorder<'_, Rgba8>),
{
let mut animation = self.recorder.record_animated_png(60);
let capture = std::env::var("CAPTURE").is_ok();
let errored = std::panic::catch_unwind(AssertUnwindSafe(|| test(&mut animation))).is_err();
if errored || capture {
let path = target_dir().join(format!("{}.png", self.name));
animation.write_to(&path).expect("error saving file");
println!("Wrote {}", path.display());

if errored {
std::process::exit(-1);
}
}
}
}

#[macro_export]
macro_rules! book_example {
($name:ident) => {
guide_examples::BookExample::build(stringify!($name), $name())
};
}
Loading

0 comments on commit 15b8b3e

Please sign in to comment.