diff --git a/docs/egui_demo_app.js b/docs/egui_demo_app.js index 1dfbb610..b1a17055 100644 --- a/docs/egui_demo_app.js +++ b/docs/egui_demo_app.js @@ -212,22 +212,22 @@ function makeMutClosure(arg0, arg1, dtor, f) { return real; } -function __wbg_adapter_28(arg0, arg1, arg2) { - wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h25f84cc60118f837(arg0, arg1, addHeapObject(arg2)); +function __wbg_adapter_28(arg0, arg1) { + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h0fd05312e5982956(arg0, arg1); } -function __wbg_adapter_31(arg0, arg1) { - wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha2c5a72e5c948e73(arg0, arg1); +function __wbg_adapter_31(arg0, arg1, arg2) { + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h67fa6b1a144b91cc(arg0, arg1, addHeapObject(arg2)); } function __wbg_adapter_34(arg0, arg1, arg2) { - wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h25f84cc60118f837(arg0, arg1, addHeapObject(arg2)); + wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h67fa6b1a144b91cc(arg0, arg1, addHeapObject(arg2)); } function __wbg_adapter_37(arg0, arg1) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hded0e2f18c7b6997(retptr, arg0, arg1); + wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha165bf8c3b3285b8(retptr, arg0, arg1); var r0 = getInt32Memory0()[retptr / 4 + 0]; var r1 = getInt32Memory0()[retptr / 4 + 1]; if (r1) { @@ -1537,32 +1537,32 @@ async function init(input) { const ret = wasm.memory; return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2300 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 831, __wbg_adapter_28); + imports.wbg.__wbindgen_closure_wrapper1269 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 371, __wbg_adapter_28); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2301 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 831, __wbg_adapter_31); + imports.wbg.__wbindgen_closure_wrapper1270 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 371, __wbg_adapter_31); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2302 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 831, __wbg_adapter_34); + imports.wbg.__wbindgen_closure_wrapper1271 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 371, __wbg_adapter_34); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2311 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 831, __wbg_adapter_37); + imports.wbg.__wbindgen_closure_wrapper1280 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 371, __wbg_adapter_37); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2544 = function(arg0, arg1, arg2) { - const ret = makeClosure(arg0, arg1, 981, __wbg_adapter_40); + imports.wbg.__wbindgen_closure_wrapper1513 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 524, __wbg_adapter_40); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2545 = function(arg0, arg1, arg2) { - const ret = makeClosure(arg0, arg1, 981, __wbg_adapter_43); + imports.wbg.__wbindgen_closure_wrapper1514 = function(arg0, arg1, arg2) { + const ret = makeClosure(arg0, arg1, 524, __wbg_adapter_43); return addHeapObject(ret); }; - imports.wbg.__wbindgen_closure_wrapper2583 = function(arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 1001, __wbg_adapter_46); + imports.wbg.__wbindgen_closure_wrapper1552 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 544, __wbg_adapter_46); return addHeapObject(ret); }; diff --git a/docs/egui_demo_app_bg.wasm b/docs/egui_demo_app_bg.wasm index 7316876c..6b97112f 100644 Binary files a/docs/egui_demo_app_bg.wasm and b/docs/egui_demo_app_bg.wasm differ diff --git a/egui/src/lib.rs b/egui/src/lib.rs index 28db8b02..d521eb5d 100644 --- a/egui/src/lib.rs +++ b/egui/src/lib.rs @@ -177,7 +177,7 @@ //! This means it is responsibility of the egui user to store the state (`value`) so that it persists between frames. //! //! It can be useful to read the code for the toggle switch example widget to get a better understanding -//! of how egui works: . +//! of how egui works: . //! //! Read more about the pros and cons of immediate mode at . //! diff --git a/egui_demo_app/src/backend_panel.rs b/egui_demo_app/src/backend_panel.rs index 041882fe..28810075 100644 --- a/egui_demo_app/src/backend_panel.rs +++ b/egui_demo_app/src/backend_panel.rs @@ -78,11 +78,6 @@ impl BackendPanel { pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) { egui::trace!(ui); - ui.vertical_centered(|ui| { - ui.heading("💻 Backend"); - }); - - ui.separator(); self.integration_ui(ui, frame); @@ -132,20 +127,11 @@ impl BackendPanel { } fn integration_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) { - if frame.is_web() { - ui.label("egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."); - ui.label( - "Everything you see is rendered as textured triangles. There is no DOM and no HTML elements. \ - This is the web page, reinvented with game tech."); - ui.hyperlink("https://github.com/emilk/egui"); - - ui.separator(); - } - ui.horizontal(|ui| { ui.spacing_mut().item_spacing.x = 0.0; ui.label("egui running inside "); ui.hyperlink_to("eframe", "https://github.com/emilk/egui/tree/master/eframe"); + ui.label("."); }); if let Some(web_info) = &frame.info().web_info { @@ -169,7 +155,9 @@ impl BackendPanel { .on_hover_text("Resize the window to be small like a phone.") .clicked() { - frame.set_window_size(egui::Vec2::new(375.0, 812.0)); // iPhone 12 mini + // frame.set_window_size(egui::Vec2::new(375.0, 812.0)); // iPhone 12 mini + frame.set_window_size(egui::Vec2::new(375.0, 667.0)); // iPhone SE 2nd gen + ui.close_menu(); } } diff --git a/egui_demo_app/src/frame_history.rs b/egui_demo_app/src/frame_history.rs index 556d3754..3d322a8a 100644 --- a/egui_demo_app/src/frame_history.rs +++ b/egui_demo_app/src/frame_history.rs @@ -49,11 +49,13 @@ impl FrameHistory { ); egui::warn_if_debug_build(ui); - egui::CollapsingHeader::new("📊 CPU usage history") - .default_open(false) - .show(ui, |ui| { - self.graph(ui); - }); + if !cfg!(target_arch = "wasm32") { + egui::CollapsingHeader::new("📊 CPU usage history") + .default_open(false) + .show(ui, |ui| { + self.graph(ui); + }); + } } fn graph(&mut self, ui: &mut egui::Ui) -> egui::Response { diff --git a/egui_demo_app/src/wrap_app.rs b/egui_demo_app/src/wrap_app.rs index 05a692fc..b6410af9 100644 --- a/egui_demo_app/src/wrap_app.rs +++ b/egui_demo_app/src/wrap_app.rs @@ -1,3 +1,4 @@ +use egui_demo_lib::is_mobile; use egui_glow::glow; #[derive(Default)] @@ -181,47 +182,30 @@ impl eframe::App for WrapApp { egui::TopBottomPanel::top("wrap_app_top_bar").show(ctx, |ui| { egui::trace!(ui); - self.bar_contents(ui, frame); + ui.horizontal_wrapped(|ui| { + ui.visuals_mut().button_frame = false; + self.bar_contents(ui, frame); + }); }); self.state.backend_panel.update(ctx, frame); - if self.state.backend_panel.open || ctx.memory().everything_is_visible() { - egui::SidePanel::left("backend_panel").show(ctx, |ui| { - self.state.backend_panel.ui(ui, frame); + if !is_mobile(ctx) + && (self.state.backend_panel.open || ctx.memory().everything_is_visible()) + { + egui::SidePanel::left("backend_panel") + .resizable(false) + .show(ctx, |ui| { + ui.vertical_centered(|ui| { + ui.heading("💻 Backend"); + }); - ui.separator(); - - ui.horizontal(|ui| { - if ui - .button("Reset egui") - .on_hover_text("Forget scroll, positions, sizes etc") - .clicked() - { - *ui.ctx().memory() = Default::default(); - } - - if ui.button("Reset everything").clicked() { - self.state = Default::default(); - *ui.ctx().memory() = Default::default(); - } + ui.separator(); + self.backend_panel_contents(ui, frame); }); - }); } - let mut found_anchor = false; - - let selected_anchor = self.state.selected_anchor.clone(); - for (_name, anchor, app) in self.apps_iter_mut() { - if anchor == selected_anchor || ctx.memory().everything_is_visible() { - app.update(ctx, frame); - found_anchor = true; - } - } - - if !found_anchor { - self.state.selected_anchor = "demo".into(); - } + self.show_selected_app(ctx, frame); self.state.backend_panel.end_of_frame(ctx); @@ -234,44 +218,87 @@ impl eframe::App for WrapApp { } impl WrapApp { + fn backend_panel_contents(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) { + self.state.backend_panel.ui(ui, frame); + + ui.separator(); + + ui.horizontal(|ui| { + if ui + .button("Reset egui") + .on_hover_text("Forget scroll, positions, sizes etc") + .clicked() + { + *ui.ctx().memory() = Default::default(); + ui.close_menu(); + } + + if ui.button("Reset everything").clicked() { + self.state = Default::default(); + *ui.ctx().memory() = Default::default(); + ui.close_menu(); + } + }); + } + + fn show_selected_app(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { + let mut found_anchor = false; + let selected_anchor = self.state.selected_anchor.clone(); + for (_name, anchor, app) in self.apps_iter_mut() { + if anchor == selected_anchor || ctx.memory().everything_is_visible() { + app.update(ctx, frame); + found_anchor = true; + } + } + if !found_anchor { + self.state.selected_anchor = "demo".into(); + } + } + fn bar_contents(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) { - // A menu-bar is a horizontal layout with some special styles applied. - // egui::menu::bar(ui, |ui| { - ui.horizontal_wrapped(|ui| { - egui::widgets::global_dark_light_mode_switch(ui); + egui::widgets::global_dark_light_mode_switch(ui); - ui.checkbox(&mut self.state.backend_panel.open, "💻 Backend"); - ui.separator(); + ui.separator(); - let mut selected_anchor = self.state.selected_anchor.clone(); - for (name, anchor, _app) in self.apps_iter_mut() { - if ui - .selectable_label(selected_anchor == anchor, name) - .clicked() - { - selected_anchor = anchor.to_owned(); - if frame.is_web() { - ui.output().open_url(format!("#{}", anchor)); - } + if is_mobile(ui.ctx()) { + ui.menu_button("💻 Backend", |ui| { + ui.set_style(ui.ctx().style()); // ignore the "menu" style set by `menu_button`. + self.backend_panel_contents(ui, frame); + }); + } else { + ui.toggle_value(&mut self.state.backend_panel.open, "💻 Backend"); + } + + ui.separator(); + + let mut selected_anchor = self.state.selected_anchor.clone(); + for (name, anchor, _app) in self.apps_iter_mut() { + if ui + .selectable_label(selected_anchor == anchor, name) + .clicked() + { + selected_anchor = anchor.to_owned(); + if frame.is_web() { + ui.output().open_url(format!("#{}", anchor)); } } - self.state.selected_anchor = selected_anchor; + } + self.state.selected_anchor = selected_anchor; - ui.with_layout(egui::Layout::right_to_left(), |ui| { - if false { - // TODO: fix the overlap on small screens - if let Some(seconds_since_midnight) = crate::seconds_since_midnight() { - if clock_button(ui, seconds_since_midnight).clicked() { - self.state.selected_anchor = "clock".to_owned(); - if frame.is_web() { - ui.output().open_url("#clock"); - } + ui.with_layout(egui::Layout::right_to_left(), |ui| { + if false { + // TODO: fix the overlap on small screens + if let Some(seconds_since_midnight) = crate::seconds_since_midnight() { + if clock_button(ui, seconds_since_midnight).clicked() { + self.state.selected_anchor = "clock".to_owned(); + if frame.is_web() { + ui.output().open_url("#clock"); } } } + } - egui::warn_if_debug_build(ui); - }); + egui::warn_if_debug_build(ui); }); } diff --git a/egui_demo_lib/src/demo/about.rs b/egui_demo_lib/src/demo/about.rs new file mode 100644 index 00000000..7c975e9e --- /dev/null +++ b/egui_demo_lib/src/demo/about.rs @@ -0,0 +1,94 @@ +#[derive(Default)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(default))] +pub struct About {} + +impl super::Demo for About { + fn name(&self) -> &'static str { + "About egui" + } + + fn show(&mut self, ctx: &egui::Context, open: &mut bool) { + egui::Window::new(self.name()) + .default_width(320.0) + .open(open) + .show(ctx, |ui| { + use super::View as _; + self.ui(ui); + }); + } +} + +impl super::View for About { + fn ui(&mut self, ui: &mut egui::Ui) { + use egui::special_emojis::{OS_APPLE, OS_LINUX, OS_WINDOWS}; + + ui.heading("egui"); + ui.label(format!( + "egui is an immediate mode GUI library written in Rust. egui runs both on the web and natively on {}{}{}. \ + On the web it is compiled to WebAssembly and rendered with WebGL.{}", + OS_APPLE, OS_LINUX, OS_WINDOWS, + if cfg!(target_arch = "wasm32") { + " Everything you see is rendered as textured triangles. There is no DOM, HTML, JS or CSS. Just Rust." + } else {""} + )); + ui.label("egui is designed to be easy to use, portable, and fast."); + + ui.add_space(12.0); // ui.separator(); + ui.heading("Immediate mode"); + about_immediate_mode(ui); + + ui.add_space(12.0); // ui.separator(); + ui.heading("Links"); + links(ui); + } +} + +fn about_immediate_mode(ui: &mut egui::Ui) { + use crate::syntax_highlighting::code_view_ui; + ui.style_mut().spacing.interact_size.y = 0.0; // hack to make `horizontal_wrapped` work better with text. + + ui.horizontal_wrapped(|ui| { + ui.spacing_mut().item_spacing.x = 0.0; + ui.label("Immediate mode is a GUI paradigm that lets you create a GUI with less code and simpler control flow. For example, this is how you create a "); + let _ = ui.small_button("button"); + ui.label(" in egui:"); + }); + + ui.add_space(8.0); + code_view_ui( + ui, + r#" + if ui.button("Save").clicked() { + my_state.save(); + }"# + .trim_start_matches('\n'), + ); + ui.add_space(8.0); + + ui.label("Note how there are no callbacks or messages, and no button state to store."); + + ui.label("Immediate mode has its roots in gaming, where everything on the screen is painted at the display refresh rate, i.e. at 60+ frames per second. \ + In immediate mode GUIs, the entire interface is layed out and painted at the same high rate. \ + This makes immediate mode GUIs especially well suited for highly interactive applications."); + + ui.horizontal_wrapped(|ui| { + ui.spacing_mut().item_spacing.x = 0.0; + ui.label("More about immediate mode "); + ui.hyperlink_to("here", "https://github.com/emilk/egui#why-immediate-mode"); + ui.label("."); + }); +} + +fn links(ui: &mut egui::Ui) { + use egui::special_emojis::{GITHUB, TWITTER}; + ui.hyperlink_to( + format!("{} egui on GitHub", GITHUB), + "https://github.com/emilk/egui", + ); + ui.hyperlink_to( + format!("{} @ernerfeldt", TWITTER), + "https://twitter.com/ernerfeldt", + ); + ui.hyperlink_to("egui documentation", "https://docs.rs/egui/"); +} diff --git a/egui_demo_lib/src/demo/demo_app_windows.rs b/egui_demo_lib/src/demo/demo_app_windows.rs index da4f183c..05da20d4 100644 --- a/egui_demo_lib/src/demo/demo_app_windows.rs +++ b/egui_demo_lib/src/demo/demo_app_windows.rs @@ -1,7 +1,11 @@ -use super::Demo; use egui::{Context, ScrollArea, Ui}; use std::collections::BTreeSet; +use super::About; +use super::Demo; +use super::View; +use crate::is_mobile; + // ---------------------------------------------------------------------------- #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] @@ -56,7 +60,7 @@ impl Demos { let Self { demos, open } = self; for demo in demos { let mut is_open = open.contains(demo.name()); - ui.checkbox(&mut is_open, demo.name()); + ui.toggle_value(&mut is_open, demo.name()); set_open(open, demo.name(), is_open); } } @@ -111,7 +115,7 @@ impl Tests { let Self { demos, open } = self; for demo in demos { let mut is_open = open.contains(demo.name()); - ui.checkbox(&mut is_open, demo.name()); + ui.toggle_value(&mut is_open, demo.name()); set_open(open, demo.name(), is_open); } } @@ -141,23 +145,103 @@ fn set_open(open: &mut BTreeSet, key: &'static str, is_open: bool) { // ---------------------------------------------------------------------------- /// A menu bar in which you can select different demo windows to show. -#[derive(Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct DemoWindows { + about_is_open: bool, + about: About, demos: Demos, tests: Tests, } +impl Default for DemoWindows { + fn default() -> Self { + Self { + about_is_open: true, + about: Default::default(), + demos: Default::default(), + tests: Default::default(), + } + } +} + impl DemoWindows { /// Show the app ui (menu bar and windows). - /// `sidebar_ui` can be used to optionally show some things in the sidebar pub fn ui(&mut self, ctx: &Context) { - let Self { demos, tests } = self; + if is_mobile(ctx) { + self.mobile_ui(ctx); + } else { + self.desktop_ui(ctx); + } + } + fn mobile_ui(&mut self, ctx: &Context) { + if self.about_is_open { + egui::CentralPanel::default().show(ctx, |_ui| {}); // just to paint a background for the windows to be on top of. Needed on web because of https://github.com/emilk/egui/issues/1548 + + let screen_size = ctx.input().screen_rect.size(); + let default_width = (screen_size.x - 20.0).min(400.0); + + let mut close = false; + egui::Window::new(self.about.name()) + .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0]) + .default_width(default_width) + .default_height(ctx.available_rect().height() - 46.0) + .vscroll(true) + .open(&mut self.about_is_open) + .resizable(false) + .collapsible(false) + .show(ctx, |ui| { + self.about.ui(ui); + ui.add_space(12.0); + ui.vertical_centered_justified(|ui| { + if ui + .button(egui::RichText::new("Continue to the demo!").size(24.0)) + .clicked() + { + close = true; + } + }); + }); + self.about_is_open &= !close; + } else { + self.mobile_top_bar(ctx); + self.show_windows(ctx); + } + } + + fn mobile_top_bar(&mut self, ctx: &Context) { + egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| { + egui::menu::bar(ui, |ui| { + let font_size = 20.0; + + ui.menu_button(egui::RichText::new("⏷ demos").size(font_size), |ui| { + ui.set_style(ui.ctx().style()); // ignore the "menu" style set by `menu_button`. + self.demo_list_ui(ui); + if ui.ui_contains_pointer() && ui.input().pointer.any_click() { + ui.close_menu(); + } + }); + + ui.with_layout(egui::Layout::right_to_left(), |ui| { + use egui::special_emojis::{GITHUB, TWITTER}; + ui.hyperlink_to( + egui::RichText::new(TWITTER).size(font_size), + "https://twitter.com/ernerfeldt", + ); + ui.hyperlink_to( + egui::RichText::new(GITHUB).size(font_size), + "https://github.com/emilk/egui", + ); + }); + }); + }); + } + + fn desktop_ui(&mut self, ctx: &Context) { egui::SidePanel::right("egui_demo_panel") - .min_width(150.0) - .default_width(180.0) + .resizable(false) + .default_width(145.0) .show(ctx, |ui| { egui::trace!(ui); ui.vertical_centered(|ui| { @@ -166,78 +250,72 @@ impl DemoWindows { ui.separator(); - ScrollArea::vertical().show(ui, |ui| { - use egui::special_emojis::{GITHUB, OS_APPLE, OS_LINUX, OS_WINDOWS, TWITTER}; + use egui::special_emojis::{GITHUB, TWITTER}; + ui.hyperlink_to( + format!("{} egui on GitHub", GITHUB), + "https://github.com/emilk/egui", + ); + ui.hyperlink_to( + format!("{} @ernerfeldt", TWITTER), + "https://twitter.com/ernerfeldt", + ); - ui.label("egui is an immediate mode GUI library written in Rust."); + ui.separator(); - ui.label(format!( - "egui runs on the web, or natively on {}{}{}", - OS_APPLE, OS_LINUX, OS_WINDOWS, - )); - - ui.hyperlink_to( - format!("{} egui on GitHub", GITHUB), - "https://github.com/emilk/egui", - ); - - ui.hyperlink_to( - format!("{} @ernerfeldt", TWITTER), - "https://twitter.com/ernerfeldt", - ); - - ui.separator(); - demos.checkboxes(ui); - ui.separator(); - tests.checkboxes(ui); - ui.separator(); - - ui.vertical_centered(|ui| { - if ui.button("Organize windows").clicked() { - ui.ctx().memory().reset_areas(); - } - }); - }); + self.demo_list_ui(ui); }); egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| { - show_menu_bar(ui); + egui::menu::bar(ui, |ui| { + file_menu_button(ui); + }); }); - egui::CentralPanel::default().show(ctx, |_ui| {}); // just to paint a background for the windows to be on top of. Needed on web because of https://github.com/emilk/egui/issues/1548 - - self.windows(ctx); + self.show_windows(ctx); } /// Show the open windows. - fn windows(&mut self, ctx: &Context) { - let Self { demos, tests } = self; + fn show_windows(&mut self, ctx: &Context) { + egui::CentralPanel::default().show(ctx, |_ui| {}); // just to paint a background for the windows to be on top of. Needed on web because of https://github.com/emilk/egui/issues/1548 + self.about.show(ctx, &mut self.about_is_open); + self.demos.windows(ctx); + self.tests.windows(ctx); + } - demos.windows(ctx); - tests.windows(ctx); + fn demo_list_ui(&mut self, ui: &mut egui::Ui) { + ScrollArea::vertical().show(ui, |ui| { + ui.with_layout(egui::Layout::top_down_justified(egui::Align::LEFT), |ui| { + ui.toggle_value(&mut self.about_is_open, self.about.name()); + + ui.separator(); + self.demos.checkboxes(ui); + ui.separator(); + self.tests.checkboxes(ui); + ui.separator(); + + if ui.button("Organize windows").clicked() { + ui.ctx().memory().reset_areas(); + } + }); + }); } } // ---------------------------------------------------------------------------- -fn show_menu_bar(ui: &mut Ui) { - trace!(ui); - use egui::*; - - menu::bar(ui, |ui| { - ui.menu_button("File", |ui| { - if ui.button("Organize windows").clicked() { - ui.ctx().memory().reset_areas(); - ui.close_menu(); - } - if ui - .button("Reset egui memory") - .on_hover_text("Forget scroll, positions, sizes etc") - .clicked() - { - *ui.ctx().memory() = Default::default(); - ui.close_menu(); - } - }); +fn file_menu_button(ui: &mut Ui) { + ui.menu_button("File", |ui| { + if ui.button("Organize windows").clicked() { + ui.ctx().memory().reset_areas(); + ui.close_menu(); + } + if ui + .button("Reset egui memory") + .on_hover_text("Forget scroll, positions, sizes etc") + .clicked() + { + *ui.ctx().memory() = Default::default(); + ui.close_menu(); + } }); } diff --git a/egui_demo_lib/src/demo/mod.rs b/egui_demo_lib/src/demo/mod.rs index ec78696d..53893567 100644 --- a/egui_demo_lib/src/demo/mod.rs +++ b/egui_demo_lib/src/demo/mod.rs @@ -4,6 +4,7 @@ // ---------------------------------------------------------------------------- +pub mod about; pub mod code_editor; pub mod code_example; pub mod context_menu; @@ -30,7 +31,8 @@ pub mod window_options; pub mod window_with_panels; pub use { - demo_app_windows::DemoWindows, misc_demo_window::MiscDemoWindow, widget_gallery::WidgetGallery, + about::About, demo_app_windows::DemoWindows, misc_demo_window::MiscDemoWindow, + widget_gallery::WidgetGallery, }; // ---------------------------------------------------------------------------- diff --git a/egui_demo_lib/src/demo/plot_demo.rs b/egui_demo_lib/src/demo/plot_demo.rs index 75bf1779..2b81427a 100644 --- a/egui_demo_lib/src/demo/plot_demo.rs +++ b/egui_demo_lib/src/demo/plot_demo.rs @@ -370,6 +370,7 @@ impl CustomAxisDemo { marks } + #[allow(clippy::unused_self)] fn ui(&mut self, ui: &mut Ui) -> Response { const MINS_PER_DAY: f64 = CustomAxisDemo::MINS_PER_DAY; const MINS_PER_H: f64 = CustomAxisDemo::MINS_PER_H; @@ -587,6 +588,7 @@ impl ItemsDemo { struct InteractionDemo {} impl InteractionDemo { + #[allow(clippy::unused_self)] fn ui(&mut self, ui: &mut Ui) -> Response { let plot = Plot::new("interaction_demo").height(300.0); diff --git a/egui_demo_lib/src/lib.rs b/egui_demo_lib/src/lib.rs index e1964533..49387918 100644 --- a/egui_demo_lib/src/lib.rs +++ b/egui_demo_lib/src/lib.rs @@ -92,3 +92,12 @@ fn test_egui_zero_window_size() { ); } } + +// ---------------------------------------------------------------------------- + +/// Detect narrow screens. This is used to show a simpler UI on mobile devices, +/// especially for the web demo at . +pub fn is_mobile(ctx: &egui::Context) -> bool { + let screen_size = ctx.input().screen_rect().size(); + screen_size.x < 550.0 +}