[demo] Move Fractal Clock to WrapApp
This commit is contained in:
parent
b1022d01c1
commit
4848c171eb
10 changed files with 100 additions and 140 deletions
|
@ -137,11 +137,20 @@ impl TopPanel {
|
|||
/// });
|
||||
/// ```
|
||||
#[derive(Default)]
|
||||
pub struct CentralPanel {}
|
||||
pub struct CentralPanel {
|
||||
frame: Option<Frame>,
|
||||
}
|
||||
|
||||
impl CentralPanel {
|
||||
pub fn frame(mut self, frame: Frame) -> Self {
|
||||
self.frame = Some(frame);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl CentralPanel {
|
||||
pub fn show<R>(self, ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) {
|
||||
let Self {} = self;
|
||||
let Self { frame } = self;
|
||||
|
||||
let panel_rect = ctx.available_rect();
|
||||
|
||||
|
@ -151,7 +160,7 @@ impl CentralPanel {
|
|||
let clip_rect = ctx.input().screen_rect();
|
||||
let mut panel_ui = Ui::new(ctx.clone(), layer_id, id, panel_rect, clip_rect);
|
||||
|
||||
let frame = Frame::central_panel(&ctx.style());
|
||||
let frame = frame.unwrap_or_else(|| Frame::central_panel(&ctx.style()));
|
||||
let r = frame.show(&mut panel_ui, |ui| {
|
||||
let r = add_contents(ui);
|
||||
ui.expand_to_include_rect(ui.max_rect()); // Use it all
|
||||
|
|
|
@ -10,7 +10,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
c.bench_function("demo_windows_minimal", |b| {
|
||||
b.iter(|| {
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
||||
demo_windows.ui(&ctx, &mut None, |_ui| {});
|
||||
ctx.end_frame()
|
||||
})
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
c.bench_function("demo_windows_full", |b| {
|
||||
b.iter(|| {
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
||||
demo_windows.ui(&ctx, &mut None, |_ui| {});
|
||||
ctx.end_frame()
|
||||
})
|
||||
});
|
||||
|
@ -35,7 +35,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
||||
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
||||
demo_windows.ui(&ctx, &mut None, |_ui| {});
|
||||
let (_, paint_commands) = ctx.end_frame();
|
||||
|
||||
c.bench_function("tessellate", |b| {
|
||||
|
|
|
@ -297,24 +297,6 @@ impl epi::App for DemoApp {
|
|||
self.frame_history
|
||||
.on_new_frame(ctx.input().time, frame.info().cpu_usage);
|
||||
|
||||
let web_location_hash = frame
|
||||
.info()
|
||||
.web_info
|
||||
.as_ref()
|
||||
.map(|info| info.web_location_hash.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
let link = if web_location_hash == "clock" {
|
||||
Some(super::DemoLink::Clock)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let demo_environment = super::DemoEnvironment {
|
||||
seconds_since_midnight: frame.info().seconds_since_midnight,
|
||||
link,
|
||||
};
|
||||
|
||||
let mean_frame_time = self.frame_history.mean_frame_time();
|
||||
|
||||
let Self {
|
||||
|
@ -323,7 +305,7 @@ impl epi::App for DemoApp {
|
|||
..
|
||||
} = self;
|
||||
|
||||
demo_windows.ui(ctx, &demo_environment, frame.tex_allocator(), |ui| {
|
||||
demo_windows.ui(ctx, frame.tex_allocator(), |ui| {
|
||||
ui.separator();
|
||||
ui.checkbox(backend_window_open, "💻 Backend");
|
||||
|
||||
|
|
|
@ -2,24 +2,6 @@ use egui::{CtxRef, Resize, ScrollArea, Ui, Window};
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// Link to show a specific part of the demo app.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum DemoLink {
|
||||
Clock,
|
||||
}
|
||||
|
||||
/// Special input to the demo-app.
|
||||
#[derive(Default)]
|
||||
pub struct DemoEnvironment {
|
||||
/// Local time. Used for the clock in the demo app.
|
||||
pub seconds_since_midnight: Option<f64>,
|
||||
|
||||
/// Set to `Some` to open a specific part of the demo app.
|
||||
pub link: Option<DemoLink>,
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
struct Demos {
|
||||
|
@ -67,13 +49,8 @@ pub struct DemoWindows {
|
|||
#[serde(skip)]
|
||||
color_test: super::ColorTest,
|
||||
|
||||
fractal_clock: super::FractalClock,
|
||||
|
||||
/// open, title, view
|
||||
demos: Demos,
|
||||
|
||||
#[serde(skip)]
|
||||
previous_link: Option<DemoLink>,
|
||||
}
|
||||
|
||||
impl DemoWindows {
|
||||
|
@ -82,26 +59,11 @@ impl DemoWindows {
|
|||
pub fn ui(
|
||||
&mut self,
|
||||
ctx: &CtxRef,
|
||||
env: &DemoEnvironment,
|
||||
tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>,
|
||||
sidebar_ui: impl FnOnce(&mut Ui),
|
||||
) {
|
||||
if self.previous_link != env.link {
|
||||
match env.link {
|
||||
None => {}
|
||||
Some(DemoLink::Clock) => {
|
||||
self.open_windows = OpenWindows {
|
||||
fractal_clock: true,
|
||||
..OpenWindows::none()
|
||||
};
|
||||
}
|
||||
}
|
||||
self.previous_link = env.link;
|
||||
}
|
||||
|
||||
egui::SidePanel::left("side_panel", 190.0).show(ctx, |ui| {
|
||||
ui.heading("✒ Egui Demo");
|
||||
egui::warn_if_debug_build(ui);
|
||||
|
||||
ui.separator();
|
||||
|
||||
|
@ -132,24 +94,22 @@ impl DemoWindows {
|
|||
});
|
||||
|
||||
egui::TopPanel::top("menu_bar").show(ctx, |ui| {
|
||||
show_menu_bar(ui, &mut self.open_windows, env.seconds_since_midnight);
|
||||
show_menu_bar(ui);
|
||||
});
|
||||
|
||||
self.windows(ctx, env, tex_allocator);
|
||||
self.windows(ctx, tex_allocator);
|
||||
}
|
||||
|
||||
/// Show the open windows.
|
||||
fn windows(
|
||||
&mut self,
|
||||
ctx: &CtxRef,
|
||||
env: &DemoEnvironment,
|
||||
tex_allocator: &mut Option<&mut dyn epi::TextureAllocator>,
|
||||
) {
|
||||
let Self {
|
||||
open_windows,
|
||||
demo_window,
|
||||
color_test,
|
||||
fractal_clock,
|
||||
demos,
|
||||
..
|
||||
} = self;
|
||||
|
@ -191,12 +151,6 @@ impl DemoWindows {
|
|||
|
||||
demos.show(ctx);
|
||||
|
||||
fractal_clock.window(
|
||||
ctx,
|
||||
&mut open_windows.fractal_clock,
|
||||
env.seconds_since_midnight,
|
||||
);
|
||||
|
||||
self.resize_windows(ctx);
|
||||
}
|
||||
|
||||
|
@ -259,7 +213,6 @@ impl DemoWindows {
|
|||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
struct OpenWindows {
|
||||
demo: bool,
|
||||
fractal_clock: bool,
|
||||
|
||||
// egui stuff:
|
||||
settings: bool,
|
||||
|
@ -284,7 +237,6 @@ impl OpenWindows {
|
|||
fn none() -> Self {
|
||||
Self {
|
||||
demo: false,
|
||||
fractal_clock: false,
|
||||
|
||||
settings: false,
|
||||
inspection: false,
|
||||
|
@ -298,7 +250,6 @@ impl OpenWindows {
|
|||
fn checkboxes(&mut self, ui: &mut Ui) {
|
||||
let Self {
|
||||
demo,
|
||||
fractal_clock,
|
||||
settings,
|
||||
inspection,
|
||||
memory,
|
||||
|
@ -317,11 +268,10 @@ impl OpenWindows {
|
|||
.on_hover_text("For testing the integrations painter");
|
||||
ui.separator();
|
||||
ui.label("Misc:");
|
||||
ui.checkbox(fractal_clock, "🕑 Fractal Clock");
|
||||
}
|
||||
}
|
||||
|
||||
fn show_menu_bar(ui: &mut Ui, windows: &mut OpenWindows, seconds_since_midnight: Option<f64>) {
|
||||
fn show_menu_bar(ui: &mut Ui) {
|
||||
use egui::*;
|
||||
|
||||
menu::bar(ui, |ui| {
|
||||
|
@ -337,24 +287,5 @@ fn show_menu_bar(ui: &mut Ui, windows: &mut OpenWindows, seconds_since_midnight:
|
|||
*ui.ctx().memory() = Default::default();
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(time) = seconds_since_midnight {
|
||||
let time = format!(
|
||||
"{:02}:{:02}:{:02}.{:02}",
|
||||
(time % (24.0 * 60.0 * 60.0) / 3600.0).floor(),
|
||||
(time % (60.0 * 60.0) / 60.0).floor(),
|
||||
(time % 60.0).floor(),
|
||||
(time % 1.0 * 100.0).floor()
|
||||
);
|
||||
|
||||
ui.with_layout(Layout::right_to_left(), |ui| {
|
||||
if ui
|
||||
.add(Button::new(time).text_style(TextStyle::Monospace))
|
||||
.clicked
|
||||
{
|
||||
windows.fractal_clock = !windows.fractal_clock;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ mod drag_and_drop;
|
|||
mod font_book;
|
||||
pub mod font_contents_emoji;
|
||||
pub mod font_contents_ubuntu;
|
||||
mod fractal_clock;
|
||||
mod painting;
|
||||
mod scrolls;
|
||||
mod sliders;
|
||||
|
@ -23,8 +22,8 @@ mod widgets;
|
|||
|
||||
pub use {
|
||||
app::*, color_test::ColorTest, dancing_strings::DancingStrings, demo_window::DemoWindow,
|
||||
demo_windows::*, drag_and_drop::*, font_book::FontBook, fractal_clock::FractalClock,
|
||||
painting::Painting, scrolls::Scrolls, sliders::Sliders, tests::Tests, widgets::Widgets,
|
||||
demo_windows::*, drag_and_drop::*, font_book::FontBook, painting::Painting, scrolls::Scrolls,
|
||||
sliders::Sliders, tests::Tests, widgets::Widgets,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -29,17 +29,19 @@ impl Default for FractalClock {
|
|||
}
|
||||
}
|
||||
|
||||
impl FractalClock {
|
||||
pub fn window(&mut self, ctx: &CtxRef, open: &mut bool, seconds_since_midnight: Option<f64>) {
|
||||
Window::new("🕑 Fractal Clock")
|
||||
.open(open)
|
||||
.default_size(vec2(512.0, 512.0))
|
||||
.scroll(false)
|
||||
// Dark background frame to make it pop:
|
||||
.frame(Frame::window(&ctx.style()).fill(Srgba::black_alpha(250)))
|
||||
.show(ctx, |ui| self.ui(ui, seconds_since_midnight));
|
||||
impl epi::App for FractalClock {
|
||||
fn name(&self) -> &str {
|
||||
"🕑 Fractal Clock"
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) {
|
||||
egui::CentralPanel::default()
|
||||
.frame(Frame::dark_canvas(&ctx.style()))
|
||||
.show(ctx, |ui| self.ui(ui, frame.info().seconds_since_midnight));
|
||||
}
|
||||
}
|
||||
|
||||
impl FractalClock {
|
||||
pub fn ui(&mut self, ui: &mut Ui, seconds_since_midnight: Option<f64>) {
|
||||
if !self.paused {
|
||||
self.time = seconds_since_midnight.unwrap_or_else(|| ui.input().time);
|
|
@ -1,7 +1,9 @@
|
|||
mod demo;
|
||||
mod fractal_clock;
|
||||
mod http_app;
|
||||
|
||||
pub use demo::DemoApp;
|
||||
pub use fractal_clock::FractalClock;
|
||||
pub use http_app::HttpApp;
|
||||
|
||||
pub use demo::DemoWindows; // used for tests
|
||||
|
|
|
@ -96,7 +96,7 @@ fn test_egui_e2e() {
|
|||
const NUM_FRAMES: usize = 5;
|
||||
for _ in 0..NUM_FRAMES {
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
||||
demo_windows.ui(&ctx, &mut None, |_ui| {});
|
||||
let (_output, paint_commands) = ctx.end_frame();
|
||||
let paint_jobs = ctx.tessellate(paint_commands);
|
||||
assert!(!paint_jobs.is_empty());
|
||||
|
|
|
@ -2,10 +2,27 @@
|
|||
#[derive(Default, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct WrapApp {
|
||||
selectable_demo_name: String,
|
||||
selected_anchor: String,
|
||||
apps: Apps,
|
||||
}
|
||||
|
||||
#[derive(Default, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct Apps {
|
||||
demo: crate::apps::DemoApp,
|
||||
http: crate::apps::HttpApp,
|
||||
clock: crate::apps::FractalClock,
|
||||
}
|
||||
|
||||
impl Apps {
|
||||
fn iter_mut(&mut self) -> impl Iterator<Item = (&str, &mut dyn epi::App)> {
|
||||
vec![
|
||||
("demo", &mut self.demo as &mut dyn epi::App),
|
||||
("http", &mut self.http as &mut dyn epi::App),
|
||||
("clock", &mut self.clock as &mut dyn epi::App),
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl epi::App for WrapApp {
|
||||
|
@ -22,46 +39,63 @@ impl epi::App for WrapApp {
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) {
|
||||
let web_location_hash = frame
|
||||
.info()
|
||||
.web_info
|
||||
.as_ref()
|
||||
.map(|info| info.web_location_hash.clone())
|
||||
.unwrap_or_default();
|
||||
if let Some(web_info) = frame.info().web_info.as_ref() {
|
||||
if let Some(anchor) = web_info.web_location_hash.strip_prefix("#") {
|
||||
self.selected_anchor = anchor.to_owned();
|
||||
}
|
||||
}
|
||||
|
||||
if web_location_hash == "#clock" {
|
||||
// TODO
|
||||
} else if web_location_hash == "#http" {
|
||||
self.selectable_demo_name = self.http.name().to_owned();
|
||||
if self.selected_anchor.is_empty() {
|
||||
self.selected_anchor = self.apps.iter_mut().next().unwrap().0.to_owned();
|
||||
}
|
||||
|
||||
egui::TopPanel::top("wrap_app").show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(format!("web_location_hash: {:?}", web_location_hash));
|
||||
ui.label("Demo Apps:");
|
||||
ui.selectable_value(
|
||||
&mut self.selectable_demo_name,
|
||||
self.demo.name().to_owned(),
|
||||
self.demo.name(),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.selectable_demo_name,
|
||||
self.http.name().to_owned(),
|
||||
self.http.name(),
|
||||
);
|
||||
// A menu-bar is a horizontal layout with some special styles applied.
|
||||
egui::menu::bar(ui, |ui| {
|
||||
for (anchor, app) in self.apps.iter_mut() {
|
||||
if ui
|
||||
.selectable_label(self.selected_anchor == anchor, app.name())
|
||||
.clicked
|
||||
{
|
||||
self.selected_anchor = anchor.to_owned();
|
||||
if frame.is_web() {
|
||||
ui.output().open_url = Some(format!("#{}", anchor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.with_layout(egui::Layout::right_to_left(), |ui| {
|
||||
if let Some(seconds_since_midnight) = frame.info().seconds_since_midnight {
|
||||
if clock_button(ui, seconds_since_midnight).clicked {
|
||||
self.selected_anchor = "clock".to_owned();
|
||||
if frame.is_web() {
|
||||
ui.output().open_url = Some("#clock".to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
egui::warn_if_debug_build(ui);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if self.selectable_demo_name == self.demo.name() {
|
||||
self.demo.update(ctx, frame);
|
||||
} else if self.selectable_demo_name == self.http.name() {
|
||||
self.http.update(ctx, frame);
|
||||
} else {
|
||||
self.selectable_demo_name = self.demo.name().to_owned();
|
||||
for (anchor, app) in self.apps.iter_mut() {
|
||||
if anchor == self.selected_anchor {
|
||||
app.update(ctx, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clock_button(ui: &mut egui::Ui, seconds_since_midnight: f64) -> egui::Response {
|
||||
let time = seconds_since_midnight;
|
||||
let time = format!(
|
||||
"{:02}:{:02}:{:02}.{:02}",
|
||||
(time % (24.0 * 60.0 * 60.0) / 3600.0).floor(),
|
||||
(time % (60.0 * 60.0) / 60.0).floor(),
|
||||
(time % 60.0).floor(),
|
||||
(time % 1.0 * 100.0).floor()
|
||||
);
|
||||
|
||||
ui.add(egui::Button::new(time).text_style(egui::TextStyle::Monospace))
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ impl<'a> Frame<'a> {
|
|||
pub struct WebInfo {
|
||||
/// e.g. "#fragment" part of "www.example.com/index.html#fragment".
|
||||
/// Note that the leading `#` is included in the string.
|
||||
/// Also known as "hash-link" or "anchor".
|
||||
pub web_location_hash: String,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue