Split out the Egui demo code to new crate egui_demo_lib
This commit is contained in:
parent
650450bc3a
commit
6953dc7d5d
31 changed files with 282 additions and 204 deletions
2
.github/workflows/rust.yml
vendored
2
.github/workflows/rust.yml
vendored
|
@ -52,7 +52,7 @@ jobs:
|
||||||
- uses: actions-rs/cargo@v1
|
- uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: -p egui # Only test egui due to weird build issues with the others
|
args: -p egui -p egui_demo_lib # TODO: fix weird build issues with the others
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
name: Rustfmt
|
name: Rustfmt
|
||||||
|
|
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -626,7 +626,6 @@ version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"atomic_refcell",
|
"atomic_refcell",
|
||||||
"criterion",
|
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rusttype",
|
"rusttype",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -638,6 +637,7 @@ name = "egui_demo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"egui",
|
"egui",
|
||||||
|
"egui_demo_lib",
|
||||||
"egui_glium",
|
"egui_glium",
|
||||||
"egui_web",
|
"egui_web",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -645,6 +645,14 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui_demo_lib"
|
||||||
|
version = "0.6.0"
|
||||||
|
dependencies = [
|
||||||
|
"criterion",
|
||||||
|
"egui",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "egui_glium"
|
name = "egui_glium"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"egui_demo_lib",
|
||||||
"egui_demo",
|
"egui_demo",
|
||||||
"egui_glium",
|
"egui_glium",
|
||||||
"egui_web",
|
"egui_web",
|
||||||
|
|
1
check.sh
1
check.sh
|
@ -7,7 +7,6 @@ CARGO_INCREMENTAL=0 cargo clippy --workspace --all-targets --all-features -- -D
|
||||||
cargo test --workspace --all-targets --all-features
|
cargo test --workspace --all-targets --all-features
|
||||||
cargo test --workspace --doc
|
cargo test --workspace --doc
|
||||||
|
|
||||||
cargo check -p egui --lib --target wasm32-unknown-unknown
|
|
||||||
cargo check -p egui_web --lib --target wasm32-unknown-unknown
|
cargo check -p egui_web --lib --target wasm32-unknown-unknown
|
||||||
cargo check -p egui_demo --lib --target wasm32-unknown-unknown
|
cargo check -p egui_demo --lib --target wasm32-unknown-unknown
|
||||||
cargo check -p example_web --lib --target wasm32-unknown-unknown
|
cargo check -p example_web --lib --target wasm32-unknown-unknown
|
||||||
|
|
|
@ -26,9 +26,6 @@ rusttype = "0.9"
|
||||||
serde = { version = "1", features = ["derive"], optional = true }
|
serde = { version = "1", features = ["derive"], optional = true }
|
||||||
serde_json = { version = "1", optional = true }
|
serde_json = { version = "1", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
criterion = { version = "0.3", default-features = false }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["atomic_refcell", "default_fonts"]
|
default = ["atomic_refcell", "default_fonts"]
|
||||||
|
|
||||||
|
@ -38,7 +35,3 @@ default_fonts = []
|
||||||
|
|
||||||
# Only needed if you plan to use the same egui::Context from multiple threads.
|
# Only needed if you plan to use the same egui::Context from multiple threads.
|
||||||
multi_threaded = ["parking_lot"]
|
multi_threaded = ["parking_lot"]
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "benchmark"
|
|
||||||
harness = false
|
|
||||||
|
|
|
@ -676,6 +676,12 @@ impl Context {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Move all the graphics at the given layer.
|
||||||
|
/// Can be used to implement drag-and-drop (see relevant demo).
|
||||||
|
pub fn translate_layer(&self, layer_id: LayerId, delta: Vec2) {
|
||||||
|
self.graphics().list(layer_id).translate(delta);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn layer_id_at(&self, pos: Pos2) -> Option<LayerId> {
|
pub fn layer_id_at(&self, pos: Pos2) -> Option<LayerId> {
|
||||||
let resize_grab_radius_side = self.style().interaction.resize_grab_radius_side;
|
let resize_grab_radius_side = self.style().interaction.resize_grab_radius_side;
|
||||||
self.memory().layer_id_at(pos, resize_grab_radius_side)
|
self.memory().layer_id_at(pos, resize_grab_radius_side)
|
||||||
|
|
|
@ -130,15 +130,6 @@ impl Default for Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout {
|
impl Layout {
|
||||||
pub(crate) fn from_main_dir_and_cross_align(main_dir: Direction, cross_align: Align) -> Self {
|
|
||||||
Self {
|
|
||||||
main_dir,
|
|
||||||
main_wrap: false,
|
|
||||||
cross_align,
|
|
||||||
cross_justify: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn left_to_right() -> Self {
|
pub fn left_to_right() -> Self {
|
||||||
Self {
|
Self {
|
||||||
main_dir: Direction::LeftToRight,
|
main_dir: Direction::LeftToRight,
|
||||||
|
@ -180,6 +171,15 @@ impl Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_main_dir_and_cross_align(main_dir: Direction, cross_align: Align) -> Self {
|
||||||
|
Self {
|
||||||
|
main_dir,
|
||||||
|
main_wrap: false,
|
||||||
|
cross_align,
|
||||||
|
cross_justify: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[deprecated = "Use `top_down`"]
|
#[deprecated = "Use `top_down`"]
|
||||||
pub fn vertical(cross_align: Align) -> Self {
|
pub fn vertical(cross_align: Align) -> Self {
|
||||||
Self::top_down(cross_align)
|
Self::top_down(cross_align)
|
||||||
|
|
|
@ -82,7 +82,6 @@ mod animation_manager;
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod containers;
|
pub mod containers;
|
||||||
mod context;
|
mod context;
|
||||||
pub mod demos;
|
|
||||||
mod id;
|
mod id;
|
||||||
mod input;
|
mod input;
|
||||||
mod introspection;
|
mod introspection;
|
||||||
|
@ -103,7 +102,6 @@ pub use {
|
||||||
align::Align,
|
align::Align,
|
||||||
containers::*,
|
containers::*,
|
||||||
context::{Context, CtxRef},
|
context::{Context, CtxRef},
|
||||||
demos::DemoApp,
|
|
||||||
id::Id,
|
id::Id,
|
||||||
input::*,
|
input::*,
|
||||||
layers::*,
|
layers::*,
|
||||||
|
@ -122,28 +120,50 @@ pub use {
|
||||||
widgets::*,
|
widgets::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub(crate) fn has_debug_assertions() -> bool {
|
pub(crate) const fn has_debug_assertions() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
pub(crate) fn has_debug_assertions() -> bool {
|
pub(crate) const fn has_debug_assertions() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
/// Helper function that adds a label when compiling with debug assertions enabled.
|
||||||
fn test_egui_e2e() {
|
pub fn warn_if_debug_build(ui: &mut crate::Ui) {
|
||||||
let mut demo_windows = crate::demos::DemoWindows::default();
|
if crate::has_debug_assertions() {
|
||||||
let mut ctx = crate::CtxRef::default();
|
ui.label(
|
||||||
let raw_input = crate::RawInput::default();
|
crate::Label::new("‼ Debug build ‼")
|
||||||
|
.small()
|
||||||
|
.text_color(crate::color::RED),
|
||||||
|
)
|
||||||
|
.on_hover_text("Egui was compiled with debug assertions enabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const NUM_FRAMES: usize = 5;
|
// ----------------------------------------------------------------------------
|
||||||
for _ in 0..NUM_FRAMES {
|
|
||||||
ctx.begin_frame(raw_input.clone());
|
/// Create a [`Hyperlink`](crate::Hyperlink) to this file (and line) on Github
|
||||||
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
///
|
||||||
let (_output, paint_commands) = ctx.end_frame();
|
/// Example: `ui.add(github_link_file_line!("https://github.com/YOUR/PROJECT/blob/master/", "(source code)"));`
|
||||||
let paint_jobs = ctx.tessellate(paint_commands);
|
#[macro_export]
|
||||||
assert!(!paint_jobs.is_empty());
|
macro_rules! github_link_file_line {
|
||||||
|
($github_url:expr, $label:expr) => {{
|
||||||
|
let url = format!("{}{}#L{}", $github_url, file!(), line!());
|
||||||
|
$crate::Hyperlink::new(url).text($label)
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a [`Hyperlink`](crate::Hyperlink) to this file on github.
|
||||||
|
///
|
||||||
|
/// Example: `ui.add(github_link_file!("https://github.com/YOUR/PROJECT/blob/master/", "(source code)"));`
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! github_link_file {
|
||||||
|
($github_url:expr, $label:expr) => {{
|
||||||
|
let url = format!("{}{}", $github_url, file!());
|
||||||
|
$crate::Hyperlink::new(url).text($label)
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
egui = { path = "../egui", features = ["serde", "serde_json"] }
|
egui = { path = "../egui", features = ["serde", "serde_json"] }
|
||||||
|
egui_demo_lib = { path = "../egui_demo_lib" }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
# For compiling natively:
|
# For compiling natively:
|
||||||
|
|
|
@ -12,7 +12,7 @@ use wasm_bindgen::prelude::*;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn start(canvas_id: &str) -> Result<(), wasm_bindgen::JsValue> {
|
pub fn start(canvas_id: &str) -> Result<(), wasm_bindgen::JsValue> {
|
||||||
let app = egui::DemoApp::default();
|
let app = egui_demo_lib::DemoApp::default();
|
||||||
egui_web::start(canvas_id, Box::new(app))?;
|
egui_web::start(canvas_id, Box::new(app))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
|
|
||||||
// When compiling natively:
|
// When compiling natively:
|
||||||
fn main() {
|
fn main() {
|
||||||
let app = egui::DemoApp::default();
|
let app = egui_demo_lib::DemoApp::default();
|
||||||
egui_glium::run(Box::new(app));
|
egui_glium::run(Box::new(app));
|
||||||
}
|
}
|
||||||
|
|
25
egui_demo_lib/Cargo.toml
Normal file
25
egui_demo_lib/Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
[package]
|
||||||
|
name = "egui_demo_lib"
|
||||||
|
version = "0.6.0"
|
||||||
|
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||||
|
description = "Example library for Egui"
|
||||||
|
edition = "2018"
|
||||||
|
homepage = "https://github.com/emilk/egui"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
repository = "https://github.com/emilk/egui"
|
||||||
|
categories = ["gui", "graphics"]
|
||||||
|
keywords = ["glium", "egui", "gui", "gamedev"]
|
||||||
|
include = [ "**/*.rs", "Cargo.toml"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
egui = { version = "0.6.0", path = "../egui" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = { version = "0.3", default-features = false }
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "benchmark"
|
||||||
|
harness = false
|
8
egui_demo_lib/README.md
Normal file
8
egui_demo_lib/README.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Egui Demo Library
|
||||||
|
|
||||||
|
This crate contains example code for Egui.
|
||||||
|
|
||||||
|
It is in a separate crate for two reasons:
|
||||||
|
|
||||||
|
* To ensure it only uses the public `egui` API.
|
||||||
|
* To remove the amount of code in `egui` proper.
|
|
@ -5,7 +5,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ctx = egui::CtxRef::default();
|
let mut ctx = egui::CtxRef::default();
|
||||||
let mut demo_windows = egui::demos::DemoWindows::default();
|
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||||
|
|
||||||
c.bench_function("demo_windows_minimal", |b| {
|
c.bench_function("demo_windows_minimal", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -19,7 +19,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
{
|
{
|
||||||
let mut ctx = egui::CtxRef::default();
|
let mut ctx = egui::CtxRef::default();
|
||||||
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
||||||
let mut demo_windows = egui::demos::DemoWindows::default();
|
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||||
|
|
||||||
c.bench_function("demo_windows_full", |b| {
|
c.bench_function("demo_windows_full", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
@ -33,7 +33,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
{
|
{
|
||||||
let mut ctx = egui::CtxRef::default();
|
let mut ctx = egui::CtxRef::default();
|
||||||
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
||||||
let mut demo_windows = egui::demos::DemoWindows::default();
|
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||||
ctx.begin_frame(raw_input.clone());
|
ctx.begin_frame(raw_input.clone());
|
||||||
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
||||||
let (_, paint_commands) = ctx.end_frame();
|
let (_, paint_commands) = ctx.end_frame();
|
||||||
|
@ -49,7 +49,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
egui::CentralPanel::default().show(&ctx, |ui| {
|
egui::CentralPanel::default().show(&ctx, |ui| {
|
||||||
c.bench_function("label", |b| {
|
c.bench_function("label", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
ui.label(egui::demos::LOREM_IPSUM_LONG);
|
ui.label(egui_demo_lib::LOREM_IPSUM_LONG);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{app, demos, util::History, CtxRef, Response, Ui};
|
use egui::{util::History, *};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -90,9 +90,9 @@ impl FrameHistory {
|
||||||
"Includes Egui layout and tessellation time.\n\
|
"Includes Egui layout and tessellation time.\n\
|
||||||
Does not include GPU usage, nor overhead for sending data to GPU.",
|
Does not include GPU usage, nor overhead for sending data to GPU.",
|
||||||
);
|
);
|
||||||
crate::demos::warn_if_debug_build(ui);
|
egui::warn_if_debug_build(ui);
|
||||||
|
|
||||||
crate::CollapsingHeader::new("📊 CPU usage history")
|
egui::CollapsingHeader::new("📊 CPU usage history")
|
||||||
.default_open(false)
|
.default_open(false)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
self.graph(ui);
|
self.graph(ui);
|
||||||
|
@ -100,8 +100,6 @@ impl FrameHistory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn graph(&mut self, ui: &mut Ui) -> Response {
|
fn graph(&mut self, ui: &mut Ui) -> Response {
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
let graph_top_cpu_usage = 0.010;
|
let graph_top_cpu_usage = 0.010;
|
||||||
ui.label("Egui CPU usage history");
|
ui.label("Egui CPU usage history");
|
||||||
|
|
||||||
|
@ -179,7 +177,7 @@ impl FrameHistory {
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "serde", serde(default))]
|
||||||
pub struct DemoApp {
|
pub struct DemoApp {
|
||||||
demo_windows: demos::DemoWindows,
|
demo_windows: crate::DemoWindows,
|
||||||
|
|
||||||
backend_window_open: bool,
|
backend_window_open: bool,
|
||||||
|
|
||||||
|
@ -236,7 +234,7 @@ impl DemoApp {
|
||||||
.or_else(|| Some(ui.ctx().pixels_per_point()));
|
.or_else(|| Some(ui.ctx().pixels_per_point()));
|
||||||
if let Some(pixels_per_point) = &mut self.pixels_per_point {
|
if let Some(pixels_per_point) = &mut self.pixels_per_point {
|
||||||
ui.add(
|
ui.add(
|
||||||
crate::Slider::f32(pixels_per_point, 0.5..=5.0)
|
egui::Slider::f32(pixels_per_point, 0.5..=5.0)
|
||||||
.logarithmic(true)
|
.logarithmic(true)
|
||||||
.text("Scale (physical pixels per point)"),
|
.text("Scale (physical pixels per point)"),
|
||||||
);
|
);
|
||||||
|
@ -286,16 +284,16 @@ impl app::App for DemoApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde_json")]
|
#[cfg(feature = "serde_json")]
|
||||||
fn load(&mut self, storage: &dyn crate::app::Storage) {
|
fn load(&mut self, storage: &dyn egui::app::Storage) {
|
||||||
*self = crate::app::get_value(storage, crate::app::APP_KEY).unwrap_or_default()
|
*self = egui::app::get_value(storage, egui::app::APP_KEY).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde_json")]
|
#[cfg(feature = "serde_json")]
|
||||||
fn save(&mut self, storage: &mut dyn crate::app::Storage) {
|
fn save(&mut self, storage: &mut dyn egui::app::Storage) {
|
||||||
crate::app::set_value(storage, crate::app::APP_KEY, self);
|
egui::app::set_value(storage, egui::app::APP_KEY, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui(&mut self, ctx: &CtxRef, integration_context: &mut crate::app::IntegrationContext<'_>) {
|
fn ui(&mut self, ctx: &CtxRef, integration_context: &mut egui::app::IntegrationContext<'_>) {
|
||||||
self.frame_history
|
self.frame_history
|
||||||
.on_new_frame(ctx.input().time, integration_context.info.cpu_usage);
|
.on_new_frame(ctx.input().time, integration_context.info.cpu_usage);
|
||||||
|
|
||||||
|
@ -307,12 +305,12 @@ impl app::App for DemoApp {
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let link = if web_location_hash == "clock" {
|
let link = if web_location_hash == "clock" {
|
||||||
Some(demos::DemoLink::Clock)
|
Some(crate::DemoLink::Clock)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let demo_environment = demos::DemoEnvironment {
|
let demo_environment = crate::DemoEnvironment {
|
||||||
seconds_since_midnight: integration_context.info.seconds_since_midnight,
|
seconds_since_midnight: integration_context.info.seconds_since_midnight,
|
||||||
link,
|
link,
|
||||||
};
|
};
|
||||||
|
@ -339,7 +337,7 @@ impl app::App for DemoApp {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut backend_window_open = self.backend_window_open;
|
let mut backend_window_open = self.backend_window_open;
|
||||||
crate::Window::new("💻 Backend")
|
egui::Window::new("💻 Backend")
|
||||||
.min_width(360.0)
|
.min_width(360.0)
|
||||||
.scroll(false)
|
.scroll(false)
|
||||||
.open(&mut backend_window_open)
|
.open(&mut backend_window_open)
|
|
@ -1,6 +1,4 @@
|
||||||
use crate::widgets::color_picker::show_color;
|
use egui::{color::*, widgets::color_picker::show_color, *};
|
||||||
use crate::*;
|
|
||||||
use color::*;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
const GRADIENT_SIZE: Vec2 = vec2(256.0, 24.0);
|
const GRADIENT_SIZE: Vec2 = vec2(256.0, 24.0);
|
||||||
|
@ -266,7 +264,7 @@ impl ColorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response {
|
fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response {
|
||||||
use crate::paint::*;
|
use egui::paint::*;
|
||||||
let response = ui.allocate_response(GRADIENT_SIZE, Sense::hover());
|
let response = ui.allocate_response(GRADIENT_SIZE, Sense::hover());
|
||||||
if bg_fill != Default::default() {
|
if bg_fill != Default::default() {
|
||||||
let mut triangles = Triangles::default();
|
let mut triangles = Triangles::default();
|
||||||
|
@ -324,12 +322,12 @@ impl Gradient {
|
||||||
(0..=n)
|
(0..=n)
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let t = i as f32 / n as f32;
|
let t = i as f32 / n as f32;
|
||||||
Srgba([
|
Srgba::from_rgba_premultiplied(
|
||||||
lerp((left[0] as f32)..=(right[0] as f32), t).round() as u8, // Don't ever do this please!
|
lerp((left[0] as f32)..=(right[0] as f32), t).round() as u8, // Don't ever do this please!
|
||||||
lerp((left[1] as f32)..=(right[1] as f32), t).round() as u8, // Don't ever do this please!
|
lerp((left[1] as f32)..=(right[1] as f32), t).round() as u8, // Don't ever do this please!
|
||||||
lerp((left[2] as f32)..=(right[2] as f32), t).round() as u8, // Don't ever do this please!
|
lerp((left[2] as f32)..=(right[2] as f32), t).round() as u8, // Don't ever do this please!
|
||||||
lerp((left[3] as f32)..=(right[3] as f32), t).round() as u8, // Don't ever do this please!
|
lerp((left[3] as f32)..=(right[3] as f32), t).round() as u8, // Don't ever do this please!
|
||||||
])
|
)
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{containers::*, demos::*, *};
|
use egui::{containers::*, *};
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "serde", serde(default))]
|
||||||
|
@ -10,12 +10,13 @@ impl Default for DancingStrings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Demo for DancingStrings {
|
impl crate::Demo for DancingStrings {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"♫ Dancing Strings"
|
"♫ Dancing Strings"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
|
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
|
||||||
|
use crate::View;
|
||||||
Window::new(self.name())
|
Window::new(self.name())
|
||||||
.open(open)
|
.open(open)
|
||||||
.default_size(vec2(512.0, 256.0))
|
.default_size(vec2(512.0, 256.0))
|
||||||
|
@ -24,7 +25,7 @@ impl Demo for DancingStrings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for DancingStrings {
|
impl crate::View for DancingStrings {
|
||||||
fn ui(&mut self, ui: &mut Ui) {
|
fn ui(&mut self, ui: &mut Ui) {
|
||||||
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
||||||
ui.ctx().request_repaint();
|
ui.ctx().request_repaint();
|
||||||
|
@ -62,6 +63,6 @@ impl View for DancingStrings {
|
||||||
|
|
||||||
ui.painter().extend(cmds);
|
ui.painter().extend(cmds);
|
||||||
});
|
});
|
||||||
ui.add(__egui_github_link_file!());
|
ui.add(crate::__egui_github_link_file!());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{color::*, demos::*, *};
|
use crate::*;
|
||||||
|
use egui::{color::*, *};
|
||||||
|
|
||||||
/// Showcase some ui code
|
/// Showcase some ui code
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
@ -221,8 +222,6 @@ impl BoxPainting {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
use crate::layout::*;
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "serde", serde(default))]
|
||||||
struct LayoutDemo {
|
struct LayoutDemo {
|
|
@ -1,8 +1,4 @@
|
||||||
use crate::{
|
use egui::{app, CtxRef, Resize, ScrollArea, Ui, Window};
|
||||||
app,
|
|
||||||
demos::{self, Demo},
|
|
||||||
CtxRef, Resize, ScrollArea, Ui, Window,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -29,17 +25,17 @@ pub struct DemoEnvironment {
|
||||||
struct Demos {
|
struct Demos {
|
||||||
/// open, view
|
/// open, view
|
||||||
#[cfg_attr(feature = "serde", serde(skip))] // TODO: serialize the `open` state.
|
#[cfg_attr(feature = "serde", serde(skip))] // TODO: serialize the `open` state.
|
||||||
demos: Vec<(bool, Box<dyn Demo>)>,
|
demos: Vec<(bool, Box<dyn crate::Demo>)>,
|
||||||
}
|
}
|
||||||
impl Default for Demos {
|
impl Default for Demos {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
demos: vec![
|
demos: vec![
|
||||||
(false, Box::new(crate::demos::FontBook::default())),
|
(false, Box::new(crate::FontBook::default())),
|
||||||
(false, Box::new(crate::demos::Painting::default())),
|
(false, Box::new(crate::Painting::default())),
|
||||||
(false, Box::new(crate::demos::DancingStrings::default())),
|
(false, Box::new(crate::DancingStrings::default())),
|
||||||
(false, Box::new(crate::demos::DragAndDropDemo::default())),
|
(false, Box::new(crate::DragAndDropDemo::default())),
|
||||||
(false, Box::new(crate::demos::Tests::default())),
|
(false, Box::new(crate::Tests::default())),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,12 +63,12 @@ impl Demos {
|
||||||
pub struct DemoWindows {
|
pub struct DemoWindows {
|
||||||
open_windows: OpenWindows,
|
open_windows: OpenWindows,
|
||||||
|
|
||||||
demo_window: demos::DemoWindow,
|
demo_window: crate::DemoWindow,
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
#[cfg_attr(feature = "serde", serde(skip))]
|
||||||
color_test: demos::ColorTest,
|
color_test: crate::ColorTest,
|
||||||
|
|
||||||
fractal_clock: demos::FractalClock,
|
fractal_clock: crate::FractalClock,
|
||||||
|
|
||||||
/// open, title, view
|
/// open, title, view
|
||||||
demos: Demos,
|
demos: Demos,
|
||||||
|
@ -104,16 +100,16 @@ impl DemoWindows {
|
||||||
self.previous_link = env.link;
|
self.previous_link = env.link;
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::SidePanel::left("side_panel", 190.0).show(ctx, |ui| {
|
egui::SidePanel::left("side_panel", 190.0).show(ctx, |ui| {
|
||||||
ui.heading("✒ Egui Demo");
|
ui.heading("✒ Egui Demo");
|
||||||
crate::demos::warn_if_debug_build(ui);
|
egui::warn_if_debug_build(ui);
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
ScrollArea::auto_sized().show(ui, |ui| {
|
ScrollArea::auto_sized().show(ui, |ui| {
|
||||||
ui.label("Egui is an immediate mode GUI library written in Rust.");
|
ui.label("Egui is an immediate mode GUI library written in Rust.");
|
||||||
ui.add(
|
ui.add(
|
||||||
crate::Hyperlink::new("https://github.com/emilk/egui").text(" Egui home page"),
|
egui::Hyperlink::new("https://github.com/emilk/egui").text(" Egui home page"),
|
||||||
);
|
);
|
||||||
|
|
||||||
ui.label("Egui can be run on the web, or natively on 🐧");
|
ui.label("Egui can be run on the web, or natively on 🐧");
|
||||||
|
@ -136,7 +132,7 @@ impl DemoWindows {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
crate::TopPanel::top("menu_bar").show(ctx, |ui| {
|
egui::TopPanel::top("menu_bar").show(ctx, |ui| {
|
||||||
show_menu_bar(ui, &mut self.open_windows, env.seconds_since_midnight);
|
show_menu_bar(ui, &mut self.open_windows, env.seconds_since_midnight);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -215,7 +211,7 @@ impl DemoWindows {
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.label("scroll: NO");
|
ui.label("scroll: NO");
|
||||||
ui.label("resizable: YES");
|
ui.label("resizable: YES");
|
||||||
ui.label(demos::LOREM_IPSUM);
|
ui.label(crate::LOREM_IPSUM);
|
||||||
});
|
});
|
||||||
|
|
||||||
Window::new("resizable + embedded scroll")
|
Window::new("resizable + embedded scroll")
|
||||||
|
@ -228,8 +224,8 @@ impl DemoWindows {
|
||||||
ui.label("resizable: YES");
|
ui.label("resizable: YES");
|
||||||
ui.heading("We have a sub-region with scroll bar:");
|
ui.heading("We have a sub-region with scroll bar:");
|
||||||
ScrollArea::auto_sized().show(ui, |ui| {
|
ScrollArea::auto_sized().show(ui, |ui| {
|
||||||
ui.label(demos::LOREM_IPSUM_LONG);
|
ui.label(crate::LOREM_IPSUM_LONG);
|
||||||
ui.label(demos::LOREM_IPSUM_LONG);
|
ui.label(crate::LOREM_IPSUM_LONG);
|
||||||
});
|
});
|
||||||
// ui.heading("Some additional text here, that should also be visible"); // this works, but messes with the resizing a bit
|
// ui.heading("Some additional text here, that should also be visible"); // this works, but messes with the resizing a bit
|
||||||
});
|
});
|
||||||
|
@ -242,7 +238,7 @@ impl DemoWindows {
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.label("scroll: YES");
|
ui.label("scroll: YES");
|
||||||
ui.label("resizable: YES");
|
ui.label("resizable: YES");
|
||||||
ui.label(demos::LOREM_IPSUM_LONG);
|
ui.label(crate::LOREM_IPSUM_LONG);
|
||||||
});
|
});
|
||||||
|
|
||||||
Window::new("auto_sized")
|
Window::new("auto_sized")
|
||||||
|
@ -252,7 +248,7 @@ impl DemoWindows {
|
||||||
ui.label("This window will auto-size based on its contents.");
|
ui.label("This window will auto-size based on its contents.");
|
||||||
ui.heading("Resize this area:");
|
ui.heading("Resize this area:");
|
||||||
Resize::default().show(ui, |ui| {
|
Resize::default().show(ui, |ui| {
|
||||||
ui.label(demos::LOREM_IPSUM);
|
ui.label(crate::LOREM_IPSUM);
|
||||||
});
|
});
|
||||||
ui.heading("Resize the above area!");
|
ui.heading("Resize the above area!");
|
||||||
});
|
});
|
||||||
|
@ -327,7 +323,7 @@ impl OpenWindows {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_menu_bar(ui: &mut Ui, windows: &mut OpenWindows, seconds_since_midnight: Option<f64>) {
|
fn show_menu_bar(ui: &mut Ui, windows: &mut OpenWindows, seconds_since_midnight: Option<f64>) {
|
||||||
use crate::*;
|
use egui::*;
|
||||||
|
|
||||||
menu::bar(ui, |ui| {
|
menu::bar(ui, |ui| {
|
||||||
menu::menu(ui, "File", |ui| {
|
menu::menu(ui, "File", |ui| {
|
|
@ -1,7 +1,4 @@
|
||||||
use crate::{
|
use egui::*;
|
||||||
demos::{Demo, View},
|
|
||||||
*,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
|
pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
|
||||||
let is_being_dragged = ui.memory().is_being_dragged(id);
|
let is_being_dragged = ui.memory().is_being_dragged(id);
|
||||||
|
@ -18,7 +15,7 @@ pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
|
||||||
ui.output().cursor_icon = CursorIcon::Grabbing;
|
ui.output().cursor_icon = CursorIcon::Grabbing;
|
||||||
|
|
||||||
// Paint the body to a new layer:
|
// Paint the body to a new layer:
|
||||||
let layer_id = LayerId::new(layers::Order::Tooltip, id);
|
let layer_id = LayerId::new(Order::Tooltip, id);
|
||||||
let response = ui.with_layer_id(layer_id, body).1;
|
let response = ui.with_layer_id(layer_id, body).1;
|
||||||
|
|
||||||
// Now we move the visuals of the body to where the mouse is.
|
// Now we move the visuals of the body to where the mouse is.
|
||||||
|
@ -30,7 +27,7 @@ pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
|
||||||
|
|
||||||
if let Some(mouse_pos) = ui.input().mouse.pos {
|
if let Some(mouse_pos) = ui.input().mouse.pos {
|
||||||
let delta = mouse_pos - response.rect.center();
|
let delta = mouse_pos - response.rect.center();
|
||||||
ui.ctx().graphics().list(layer_id).translate(delta);
|
ui.ctx().translate_layer(layer_id, delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,12 +89,13 @@ impl Default for DragAndDropDemo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Demo for DragAndDropDemo {
|
impl crate::Demo for DragAndDropDemo {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"✋ Drag and Drop"
|
"✋ Drag and Drop"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
|
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
|
||||||
|
use crate::View;
|
||||||
Window::new(self.name())
|
Window::new(self.name())
|
||||||
.open(open)
|
.open(open)
|
||||||
.default_size(vec2(256.0, 256.0))
|
.default_size(vec2(256.0, 256.0))
|
||||||
|
@ -107,7 +105,7 @@ impl Demo for DragAndDropDemo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for DragAndDropDemo {
|
impl crate::View for DragAndDropDemo {
|
||||||
fn ui(&mut self, ui: &mut Ui) {
|
fn ui(&mut self, ui: &mut Ui) {
|
||||||
ui.label("This is a proof-of-concept of drag-and-drop in Egui");
|
ui.label("This is a proof-of-concept of drag-and-drop in Egui");
|
||||||
ui.label("Drag items between columns.");
|
ui.label("Drag items between columns.");
|
||||||
|
@ -153,6 +151,6 @@ impl View for DragAndDropDemo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.add(__egui_github_link_file!());
|
ui.add(crate::__egui_github_link_file!());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub struct FontBook {
|
pub struct FontBook {
|
||||||
standard: bool,
|
standard: bool,
|
||||||
emojis: bool,
|
emojis: bool,
|
||||||
filter: String,
|
filter: String,
|
||||||
text_style: TextStyle,
|
text_style: egui::TextStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FontBook {
|
impl Default for FontBook {
|
||||||
|
@ -13,13 +11,14 @@ impl Default for FontBook {
|
||||||
standard: false,
|
standard: false,
|
||||||
emojis: true,
|
emojis: true,
|
||||||
filter: Default::default(),
|
filter: Default::default(),
|
||||||
text_style: TextStyle::Button,
|
text_style: egui::TextStyle::Button,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontBook {
|
impl FontBook {
|
||||||
fn characters_ui(&self, ui: &mut Ui, characters: &[(u32, char, &str)]) {
|
fn characters_ui(&self, ui: &mut egui::Ui, characters: &[(u32, char, &str)]) {
|
||||||
|
use egui::{Button, Label};
|
||||||
for &(_, chr, name) in characters {
|
for &(_, chr, name) in characters {
|
||||||
if self.filter.is_empty()
|
if self.filter.is_empty()
|
||||||
|| name.contains(&self.filter)
|
|| name.contains(&self.filter)
|
||||||
|
@ -27,7 +26,7 @@ impl FontBook {
|
||||||
{
|
{
|
||||||
let button = Button::new(chr).text_style(self.text_style).frame(false);
|
let button = Button::new(chr).text_style(self.text_style).frame(false);
|
||||||
|
|
||||||
let tooltip_ui = |ui: &mut Ui| {
|
let tooltip_ui = |ui: &mut egui::Ui| {
|
||||||
ui.add(Label::new(chr).text_style(self.text_style));
|
ui.add(Label::new(chr).text_style(self.text_style));
|
||||||
ui.label(format!("{}\nU+{:X}\n\nClick to copy", name, chr as u32));
|
ui.label(format!("{}\nU+{:X}\n\nClick to copy", name, chr as u32));
|
||||||
};
|
};
|
||||||
|
@ -40,23 +39,23 @@ impl FontBook {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl demos::Demo for FontBook {
|
impl crate::Demo for FontBook {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"🔤 Font Book"
|
"🔤 Font Book"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool) {
|
fn show(&mut self, ctx: &egui::CtxRef, open: &mut bool) {
|
||||||
Window::new(self.name()).open(open).show(ctx, |ui| {
|
egui::Window::new(self.name()).open(open).show(ctx, |ui| {
|
||||||
use demos::View;
|
use crate::View;
|
||||||
self.ui(ui);
|
self.ui(ui);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl demos::View for FontBook {
|
impl crate::View for FontBook {
|
||||||
fn ui(&mut self, ui: &mut Ui) {
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
use crate::demos::font_contents_emoji::FULL_EMOJI_LIST;
|
use crate::font_contents_emoji::FULL_EMOJI_LIST;
|
||||||
use crate::demos::font_contents_ubuntu::UBUNTU_FONT_CHARACTERS;
|
use crate::font_contents_ubuntu::UBUNTU_FONT_CHARACTERS;
|
||||||
|
|
||||||
ui.label(format!(
|
ui.label(format!(
|
||||||
"Egui supports {} standard characters and {} emojis.\nClick on a character to copy it.",
|
"Egui supports {} standard characters and {} emojis.\nClick on a character to copy it.",
|
||||||
|
@ -66,8 +65,8 @@ impl demos::View for FontBook {
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
combo_box_with_label(ui, "Text style", format!("{:?}", self.text_style), |ui| {
|
egui::combo_box_with_label(ui, "Text style", format!("{:?}", self.text_style), |ui| {
|
||||||
for style in TextStyle::all() {
|
for style in egui::TextStyle::all() {
|
||||||
ui.selectable_value(&mut self.text_style, style, format!("{:?}", style));
|
ui.selectable_value(&mut self.text_style, style, format!("{:?}", style));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -89,9 +88,9 @@ impl demos::View for FontBook {
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
crate::ScrollArea::auto_sized().show(ui, |ui| {
|
egui::ScrollArea::auto_sized().show(ui, |ui| {
|
||||||
ui.horizontal_wrapped(|ui| {
|
ui.horizontal_wrapped(|ui| {
|
||||||
ui.style_mut().spacing.item_spacing = Vec2::splat(2.0);
|
ui.style_mut().spacing.item_spacing = egui::Vec2::splat(2.0);
|
||||||
|
|
||||||
if self.standard {
|
if self.standard {
|
||||||
self.characters_ui(ui, UBUNTU_FONT_CHARACTERS);
|
self.characters_ui(ui, UBUNTU_FONT_CHARACTERS);
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{containers::*, widgets::*, *};
|
use egui::{containers::*, widgets::*, *};
|
||||||
use std::f32::consts::TAU;
|
use std::f32::consts::TAU;
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
|
@ -1,6 +1,52 @@
|
||||||
//! Demo-code for showing how Egui is used.
|
//! Demo-code for showing how Egui is used.
|
||||||
//!
|
//!
|
||||||
//! The demo-code is also used in benchmarks and tests.
|
//! The demo-code is also used in benchmarks and tests.
|
||||||
|
|
||||||
|
#![cfg_attr(not(debug_assertions), deny(warnings))] // Forbid warnings in release builds
|
||||||
|
#![forbid(unsafe_code)]
|
||||||
|
#![warn(
|
||||||
|
clippy::all,
|
||||||
|
clippy::await_holding_lock,
|
||||||
|
clippy::dbg_macro,
|
||||||
|
clippy::doc_markdown,
|
||||||
|
clippy::empty_enum,
|
||||||
|
clippy::enum_glob_use,
|
||||||
|
clippy::exit,
|
||||||
|
clippy::filter_map_next,
|
||||||
|
clippy::fn_params_excessive_bools,
|
||||||
|
clippy::if_let_mutex,
|
||||||
|
clippy::imprecise_flops,
|
||||||
|
clippy::inefficient_to_string,
|
||||||
|
clippy::linkedlist,
|
||||||
|
clippy::lossy_float_literal,
|
||||||
|
clippy::macro_use_imports,
|
||||||
|
clippy::match_on_vec_items,
|
||||||
|
clippy::match_wildcard_for_single_variants,
|
||||||
|
clippy::mem_forget,
|
||||||
|
clippy::mismatched_target_os,
|
||||||
|
clippy::missing_errors_doc,
|
||||||
|
clippy::missing_safety_doc,
|
||||||
|
clippy::needless_borrow,
|
||||||
|
clippy::needless_continue,
|
||||||
|
clippy::needless_pass_by_value,
|
||||||
|
clippy::option_option,
|
||||||
|
clippy::pub_enum_variant_names,
|
||||||
|
clippy::rest_pat_in_fully_bound_structs,
|
||||||
|
clippy::todo,
|
||||||
|
clippy::unimplemented,
|
||||||
|
clippy::unnested_or_patterns,
|
||||||
|
clippy::verbose_file_reads,
|
||||||
|
future_incompatible,
|
||||||
|
missing_crate_level_docs,
|
||||||
|
missing_doc_code_examples,
|
||||||
|
// missing_docs,
|
||||||
|
nonstandard_style,
|
||||||
|
rust_2018_idioms,
|
||||||
|
unused_doc_comments,
|
||||||
|
)]
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod color_test;
|
mod color_test;
|
||||||
mod dancing_strings;
|
mod dancing_strings;
|
||||||
|
@ -34,7 +80,7 @@ Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, tur
|
||||||
|
|
||||||
/// Something to view in the demo windows
|
/// Something to view in the demo windows
|
||||||
pub trait View {
|
pub trait View {
|
||||||
fn ui(&mut self, ui: &mut crate::Ui);
|
fn ui(&mut self, ui: &mut egui::Ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Something to view
|
/// Something to view
|
||||||
|
@ -42,55 +88,20 @@ pub trait Demo {
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
|
|
||||||
/// Show windows, etc
|
/// Show windows, etc
|
||||||
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool);
|
fn show(&mut self, ctx: &egui::CtxRef, open: &mut bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub fn warn_if_debug_build(ui: &mut crate::Ui) {
|
|
||||||
if crate::has_debug_assertions() {
|
|
||||||
ui.label(
|
|
||||||
crate::Label::new("‼ Debug build ‼")
|
|
||||||
.small()
|
|
||||||
.text_color(crate::color::RED),
|
|
||||||
)
|
|
||||||
.on_hover_text("Egui was compiled with debug assertions enabled.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// Create a [`Hyperlink`](crate::Hyperlink) to this file (and line) on Github
|
|
||||||
///
|
|
||||||
/// Example: `ui.add(github_link_file_line!("https://github.com/YOUR/PROJECT/blob/master/", "(source code)"));`
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! github_link_file_line {
|
|
||||||
($github_url:expr, $label:expr) => {{
|
|
||||||
let url = format!("{}{}#L{}", $github_url, file!(), line!());
|
|
||||||
$crate::Hyperlink::new(url).text($label)
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a [`Hyperlink`](crate::Hyperlink) to this file on github.
|
|
||||||
///
|
|
||||||
/// Example: `ui.add(github_link_file!("https://github.com/YOUR/PROJECT/blob/master/", "(source code)"));`
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! github_link_file {
|
|
||||||
($github_url:expr, $label:expr) => {{
|
|
||||||
let url = format!("{}{}", $github_url, file!());
|
|
||||||
$crate::Hyperlink::new(url).text($label)
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a [`Hyperlink`](crate::Hyperlink) to this egui source code file on github.
|
/// Create a [`Hyperlink`](crate::Hyperlink) to this egui source code file on github.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! __egui_github_link_file {
|
macro_rules! __egui_github_link_file {
|
||||||
() => {
|
() => {
|
||||||
__egui_github_link_file!("(source code)")
|
crate::__egui_github_link_file!("(source code)")
|
||||||
};
|
};
|
||||||
($label:expr) => {
|
($label:expr) => {
|
||||||
github_link_file!("https://github.com/emilk/egui/blob/master/", $label).small()
|
egui::github_link_file!("https://github.com/emilk/egui/blob/master/", $label).small()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,9 +110,27 @@ macro_rules! __egui_github_link_file {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! __egui_github_link_file_line {
|
macro_rules! __egui_github_link_file_line {
|
||||||
() => {
|
() => {
|
||||||
__egui_github_link_file_line!("(source code)")
|
crate::__egui_github_link_file_line!("(source code)")
|
||||||
};
|
};
|
||||||
($label:expr) => {
|
($label:expr) => {
|
||||||
github_link_file_line!("https://github.com/emilk/egui/blob/master/", $label).small()
|
egui::github_link_file_line!("https://github.com/emilk/egui/blob/master/", $label).small()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_egui_e2e() {
|
||||||
|
let mut demo_windows = crate::DemoWindows::default();
|
||||||
|
let mut ctx = egui::CtxRef::default();
|
||||||
|
let raw_input = egui::RawInput::default();
|
||||||
|
|
||||||
|
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| {});
|
||||||
|
let (_output, paint_commands) = ctx.end_frame();
|
||||||
|
let paint_jobs = ctx.tessellate(paint_commands);
|
||||||
|
assert!(!paint_jobs.is_empty());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{demos::*, *};
|
use crate::*;
|
||||||
|
use egui::*;
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "serde", serde(default))]
|
||||||
|
@ -58,7 +59,7 @@ impl Painting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl demos::Demo for Painting {
|
impl crate::Demo for Painting {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"🖊 Painting"
|
"🖊 Painting"
|
||||||
}
|
}
|
||||||
|
@ -72,9 +73,9 @@ impl demos::Demo for Painting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl demos::View for Painting {
|
impl crate::View for Painting {
|
||||||
fn ui(&mut self, ui: &mut Ui) {
|
fn ui(&mut self, ui: &mut Ui) {
|
||||||
ui.add(__egui_github_link_file!("(source code)"));
|
ui.add(crate::__egui_github_link_file!("(source code)"));
|
||||||
self.ui_control(ui);
|
self.ui_control(ui);
|
||||||
ui.label("Paint with your mouse/touch!");
|
ui.label("Paint with your mouse/touch!");
|
||||||
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{color::*, demos::LOREM_IPSUM_LONG, *};
|
use crate::LOREM_IPSUM_LONG;
|
||||||
|
use egui::{color::*, *};
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "serde", serde(default))]
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::*;
|
use egui::*;
|
||||||
use std::f64::INFINITY;
|
use std::f64::INFINITY;
|
||||||
|
|
||||||
/// Showcase sliders
|
/// Showcase sliders
|
|
@ -1,23 +1,21 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Tests {}
|
pub struct Tests {}
|
||||||
|
|
||||||
impl demos::Demo for Tests {
|
impl crate::Demo for Tests {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"📋 Tests"
|
"📋 Tests"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool) {
|
fn show(&mut self, ctx: &egui::CtxRef, open: &mut bool) {
|
||||||
Window::new(self.name()).open(open).show(ctx, |ui| {
|
egui::Window::new(self.name()).open(open).show(ctx, |ui| {
|
||||||
use demos::View;
|
use crate::View;
|
||||||
self.ui(ui);
|
self.ui(ui);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl demos::View for Tests {
|
impl crate::View for Tests {
|
||||||
fn ui(&mut self, ui: &mut Ui) {
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
ui.heading("Name collision example");
|
ui.heading("Name collision example");
|
||||||
|
|
||||||
ui.label("\
|
ui.label("\
|
||||||
|
@ -46,6 +44,6 @@ impl demos::View for Tests {
|
||||||
let _ = ui.button("Button");
|
let _ = ui.button("Button");
|
||||||
let _ = ui.button("Button");
|
let _ = ui.button("Button");
|
||||||
|
|
||||||
ui.add(__egui_github_link_file!());
|
ui.add(crate::__egui_github_link_file!());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
//! Source code example of how to create your own widget.
|
//! Source code example of how to create your own widget.
|
||||||
//! This is meant to be read as a tutorial, hence the plethora of comments.
|
//! This is meant to be read as a tutorial, hence the plethora of comments.
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// iOS-style toggle switch:
|
/// iOS-style toggle switch:
|
||||||
///
|
///
|
||||||
|
@ -10,7 +9,7 @@ use crate::*;
|
||||||
/// | |.......|
|
/// | |.......|
|
||||||
/// \_______\_____/
|
/// \_______\_____/
|
||||||
/// ```
|
/// ```
|
||||||
pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
pub fn toggle(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
// Widget code can be broken up in four steps:
|
// Widget code can be broken up in four steps:
|
||||||
// 1. Decide a size for the widget
|
// 1. Decide a size for the widget
|
||||||
// 2. Allocate space for it
|
// 2. Allocate space for it
|
||||||
|
@ -25,7 +24,7 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
// 2. Allocating space:
|
// 2. Allocating space:
|
||||||
// This is where we get a region of the screen assigned.
|
// This is where we get a region of the screen assigned.
|
||||||
// We also tell the Ui to sense clicks in the allocated region.
|
// We also tell the Ui to sense clicks in the allocated region.
|
||||||
let response = ui.allocate_response(desired_size, Sense::click());
|
let response = ui.allocate_response(desired_size, egui::Sense::click());
|
||||||
|
|
||||||
// 3. Interact: Time to check for clicks!.
|
// 3. Interact: Time to check for clicks!.
|
||||||
if response.clicked {
|
if response.clicked {
|
||||||
|
@ -41,16 +40,16 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
// "how should something that is being interacted with be painted?".
|
// "how should something that is being interacted with be painted?".
|
||||||
// This will, for instance, give us different colors when the widget is hovered or clicked.
|
// This will, for instance, give us different colors when the widget is hovered or clicked.
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
let off_bg_fill = Rgba::new(0.0, 0.0, 0.0, 0.0);
|
let off_bg_fill = egui::Rgba::new(0.0, 0.0, 0.0, 0.0);
|
||||||
let on_bg_fill = Rgba::new(0.0, 0.5, 0.25, 1.0);
|
let on_bg_fill = egui::Rgba::new(0.0, 0.5, 0.25, 1.0);
|
||||||
let bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||||
// All coordinates are in absolute screen coordinates so we use `rect` to place the elements.
|
// All coordinates are in absolute screen coordinates so we use `rect` to place the elements.
|
||||||
let rect = response.rect;
|
let rect = response.rect;
|
||||||
let radius = 0.5 * rect.height();
|
let radius = 0.5 * rect.height();
|
||||||
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
||||||
// Paint the circle, animating it from left to right with `how_on`:
|
// Paint the circle, animating it from left to right with `how_on`:
|
||||||
let circle_x = lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
||||||
let center = pos2(circle_x, rect.center().y);
|
let center = egui::pos2(circle_x, rect.center().y);
|
||||||
ui.painter()
|
ui.painter()
|
||||||
.circle(center, 0.75 * radius, visuals.fg_fill, visuals.fg_stroke);
|
.circle(center, 0.75 * radius, visuals.fg_fill, visuals.fg_stroke);
|
||||||
|
|
||||||
|
@ -61,32 +60,32 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
|
|
||||||
/// Here is the same code again, but a bit more compact:
|
/// Here is the same code again, but a bit more compact:
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn toggle_compact(ui: &mut Ui, on: &mut bool) -> Response {
|
fn toggle_compact(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
|
||||||
let desired_size = ui.style().spacing.interact_size;
|
let desired_size = ui.style().spacing.interact_size;
|
||||||
let response = ui.allocate_response(desired_size, Sense::click());
|
let response = ui.allocate_response(desired_size, egui::Sense::click());
|
||||||
*on ^= response.clicked; // toggle if clicked
|
*on ^= response.clicked; // toggle if clicked
|
||||||
|
|
||||||
let how_on = ui.ctx().animate_bool(response.id, *on);
|
let how_on = ui.ctx().animate_bool(response.id, *on);
|
||||||
let visuals = ui.style().interact(&response);
|
let visuals = ui.style().interact(&response);
|
||||||
let off_bg_fill = Rgba::new(0.0, 0.0, 0.0, 0.0);
|
let off_bg_fill = egui::Rgba::new(0.0, 0.0, 0.0, 0.0);
|
||||||
let on_bg_fill = Rgba::new(0.0, 0.5, 0.25, 1.0);
|
let on_bg_fill = egui::Rgba::new(0.0, 0.5, 0.25, 1.0);
|
||||||
let bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||||
let rect = response.rect;
|
let rect = response.rect;
|
||||||
let radius = 0.5 * rect.height();
|
let radius = 0.5 * rect.height();
|
||||||
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
||||||
let circle_x = lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
||||||
let center = pos2(circle_x, rect.center().y);
|
let center = egui::pos2(circle_x, rect.center().y);
|
||||||
ui.painter()
|
ui.painter()
|
||||||
.circle(center, 0.75 * radius, visuals.fg_fill, visuals.fg_stroke);
|
.circle(center, 0.75 * radius, visuals.fg_fill, visuals.fg_stroke);
|
||||||
|
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn demo(ui: &mut Ui, on: &mut bool) {
|
pub fn demo(ui: &mut egui::Ui, on: &mut bool) {
|
||||||
ui.horizontal_wrapped_for_text(TextStyle::Button, |ui| {
|
ui.horizontal_wrapped_for_text(egui::TextStyle::Button, |ui| {
|
||||||
ui.label("It's easy to create your own widgets!");
|
ui.label("It's easy to create your own widgets!");
|
||||||
ui.label("This toggle switch is just one function and 15 lines of code:");
|
ui.label("This toggle switch is just one function and 15 lines of code:");
|
||||||
toggle(ui, on).on_hover_text("Click to toggle");
|
toggle(ui, on).on_hover_text("Click to toggle");
|
||||||
ui.add(__egui_github_link_file!());
|
ui.add(crate::__egui_github_link_file!());
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{color::*, demos::Sliders, *};
|
use egui::{color::*, *};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
@ -20,7 +20,7 @@ pub struct Widgets {
|
||||||
button_enabled: bool,
|
button_enabled: bool,
|
||||||
count: usize,
|
count: usize,
|
||||||
radio: Enum,
|
radio: Enum,
|
||||||
sliders: Sliders,
|
sliders: crate::Sliders,
|
||||||
angle: f32,
|
angle: f32,
|
||||||
color: Srgba,
|
color: Srgba,
|
||||||
single_line_text_input: String,
|
single_line_text_input: String,
|
||||||
|
@ -46,7 +46,7 @@ impl Default for Widgets {
|
||||||
|
|
||||||
impl Widgets {
|
impl Widgets {
|
||||||
pub fn ui(&mut self, ui: &mut Ui) {
|
pub fn ui(&mut self, ui: &mut Ui) {
|
||||||
ui.add(__egui_github_link_file_line!());
|
ui.add(crate::__egui_github_link_file_line!());
|
||||||
|
|
||||||
ui.horizontal_wrapped_for_text(TextStyle::Body, |ui| {
|
ui.horizontal_wrapped_for_text(TextStyle::Body, |ui| {
|
||||||
ui.add(Label::new("Text can have").text_color(srgba(110, 255, 110, 255)));
|
ui.add(Label::new("Text can have").text_color(srgba(110, 255, 110, 255)));
|
||||||
|
@ -83,7 +83,7 @@ impl Widgets {
|
||||||
ui.radio_value(&mut self.radio, Enum::Third, "Third");
|
ui.radio_value(&mut self.radio, Enum::Third, "Third");
|
||||||
});
|
});
|
||||||
|
|
||||||
combo_box_with_label(ui, "Combo Box", format!("{:?}", self.radio), |ui| {
|
egui::combo_box_with_label(ui, "Combo Box", format!("{:?}", self.radio), |ui| {
|
||||||
ui.selectable_value(&mut self.radio, Enum::First, "First");
|
ui.selectable_value(&mut self.radio, Enum::First, "First");
|
||||||
ui.selectable_value(&mut self.radio, Enum::Second, "Second");
|
ui.selectable_value(&mut self.radio, Enum::Second, "Second");
|
||||||
ui.selectable_value(&mut self.radio, Enum::Third, "Third");
|
ui.selectable_value(&mut self.radio, Enum::Third, "Third");
|
||||||
|
@ -110,12 +110,12 @@ impl Widgets {
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.add(
|
ui.add(
|
||||||
Slider::f64(&mut self.sliders.value, 1.0..=100.0)
|
egui::Slider::f64(&mut self.sliders.value, 1.0..=100.0)
|
||||||
.logarithmic(true)
|
.logarithmic(true)
|
||||||
.text("A slider"),
|
.text("A slider"),
|
||||||
);
|
);
|
||||||
|
|
||||||
CollapsingHeader::new("More sliders")
|
egui::CollapsingHeader::new("More sliders")
|
||||||
.default_open(false)
|
.default_open(false)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
self.sliders.ui(ui);
|
self.sliders.ui(ui);
|
||||||
|
@ -136,7 +136,7 @@ impl Widgets {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add(Label::new("Click to select a different text color: ").text_color(self.color));
|
ui.colored_label(self.color, "Click to select a different text color: ");
|
||||||
ui.color_edit_button_srgba(&mut self.color);
|
ui.color_edit_button_srgba(&mut self.color);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -154,6 +154,6 @@ impl Widgets {
|
||||||
ui.text_edit_multiline(&mut self.multiline_text_input);
|
ui.text_edit_multiline(&mut self.multiline_text_input);
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
super::toggle_switch::demo(ui, &mut self.toggle_switch);
|
crate::toggle_switch::demo(ui, &mut self.toggle_switch);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue