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
|
||||
with:
|
||||
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:
|
||||
name: Rustfmt
|
||||
|
|
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -626,7 +626,6 @@ version = "0.6.0"
|
|||
dependencies = [
|
||||
"ahash",
|
||||
"atomic_refcell",
|
||||
"criterion",
|
||||
"parking_lot",
|
||||
"rusttype",
|
||||
"serde",
|
||||
|
@ -638,6 +637,7 @@ name = "egui_demo"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"egui_demo_lib",
|
||||
"egui_glium",
|
||||
"egui_web",
|
||||
"js-sys",
|
||||
|
@ -645,6 +645,14 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "egui_demo_lib"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"egui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "egui_glium"
|
||||
version = "0.6.0"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"egui_demo_lib",
|
||||
"egui_demo",
|
||||
"egui_glium",
|
||||
"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 --doc
|
||||
|
||||
cargo check -p egui --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 example_web --lib --target wasm32-unknown-unknown
|
||||
|
|
|
@ -26,9 +26,6 @@ rusttype = "0.9"
|
|||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
serde_json = { version = "1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.3", default-features = false }
|
||||
|
||||
[features]
|
||||
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.
|
||||
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> {
|
||||
let resize_grab_radius_side = self.style().interaction.resize_grab_radius_side;
|
||||
self.memory().layer_id_at(pos, resize_grab_radius_side)
|
||||
|
|
|
@ -130,15 +130,6 @@ impl Default for 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 {
|
||||
Self {
|
||||
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`"]
|
||||
pub fn vertical(cross_align: Align) -> Self {
|
||||
Self::top_down(cross_align)
|
||||
|
|
|
@ -82,7 +82,6 @@ mod animation_manager;
|
|||
pub mod app;
|
||||
pub mod containers;
|
||||
mod context;
|
||||
pub mod demos;
|
||||
mod id;
|
||||
mod input;
|
||||
mod introspection;
|
||||
|
@ -103,7 +102,6 @@ pub use {
|
|||
align::Align,
|
||||
containers::*,
|
||||
context::{Context, CtxRef},
|
||||
demos::DemoApp,
|
||||
id::Id,
|
||||
input::*,
|
||||
layers::*,
|
||||
|
@ -122,28 +120,50 @@ pub use {
|
|||
widgets::*,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub(crate) fn has_debug_assertions() -> bool {
|
||||
pub(crate) const fn has_debug_assertions() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
pub(crate) fn has_debug_assertions() -> bool {
|
||||
pub(crate) const fn has_debug_assertions() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_egui_e2e() {
|
||||
let mut demo_windows = crate::demos::DemoWindows::default();
|
||||
let mut ctx = crate::CtxRef::default();
|
||||
let raw_input = crate::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());
|
||||
/// Helper function that adds a label when compiling with debug assertions enabled.
|
||||
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)
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ crate-type = ["cdylib", "rlib"]
|
|||
|
||||
[dependencies]
|
||||
egui = { path = "../egui", features = ["serde", "serde_json"] }
|
||||
egui_demo_lib = { path = "../egui_demo_lib" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
# For compiling natively:
|
||||
|
|
|
@ -12,7 +12,7 @@ use wasm_bindgen::prelude::*;
|
|||
#[cfg(target_arch = "wasm32")]
|
||||
#[wasm_bindgen]
|
||||
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))?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
// When compiling natively:
|
||||
fn main() {
|
||||
let app = egui::DemoApp::default();
|
||||
let app = egui_demo_lib::DemoApp::default();
|
||||
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 demo_windows = egui::demos::DemoWindows::default();
|
||||
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||
|
||||
c.bench_function("demo_windows_minimal", |b| {
|
||||
b.iter(|| {
|
||||
|
@ -19,7 +19,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
{
|
||||
let mut ctx = egui::CtxRef::default();
|
||||
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| {
|
||||
b.iter(|| {
|
||||
|
@ -33,7 +33,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
{
|
||||
let mut ctx = egui::CtxRef::default();
|
||||
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());
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None, |_ui| {});
|
||||
let (_, paint_commands) = ctx.end_frame();
|
||||
|
@ -49,7 +49,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
c.bench_function("label", |b| {
|
||||
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\
|
||||
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)
|
||||
.show(ui, |ui| {
|
||||
self.graph(ui);
|
||||
|
@ -100,8 +100,6 @@ impl FrameHistory {
|
|||
}
|
||||
|
||||
fn graph(&mut self, ui: &mut Ui) -> Response {
|
||||
use crate::*;
|
||||
|
||||
let graph_top_cpu_usage = 0.010;
|
||||
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", serde(default))]
|
||||
pub struct DemoApp {
|
||||
demo_windows: demos::DemoWindows,
|
||||
demo_windows: crate::DemoWindows,
|
||||
|
||||
backend_window_open: bool,
|
||||
|
||||
|
@ -236,7 +234,7 @@ impl DemoApp {
|
|||
.or_else(|| Some(ui.ctx().pixels_per_point()));
|
||||
if let Some(pixels_per_point) = &mut self.pixels_per_point {
|
||||
ui.add(
|
||||
crate::Slider::f32(pixels_per_point, 0.5..=5.0)
|
||||
egui::Slider::f32(pixels_per_point, 0.5..=5.0)
|
||||
.logarithmic(true)
|
||||
.text("Scale (physical pixels per point)"),
|
||||
);
|
||||
|
@ -286,16 +284,16 @@ impl app::App for DemoApp {
|
|||
}
|
||||
|
||||
#[cfg(feature = "serde_json")]
|
||||
fn load(&mut self, storage: &dyn crate::app::Storage) {
|
||||
*self = crate::app::get_value(storage, crate::app::APP_KEY).unwrap_or_default()
|
||||
fn load(&mut self, storage: &dyn egui::app::Storage) {
|
||||
*self = egui::app::get_value(storage, egui::app::APP_KEY).unwrap_or_default()
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde_json")]
|
||||
fn save(&mut self, storage: &mut dyn crate::app::Storage) {
|
||||
crate::app::set_value(storage, crate::app::APP_KEY, self);
|
||||
fn save(&mut self, storage: &mut dyn egui::app::Storage) {
|
||||
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
|
||||
.on_new_frame(ctx.input().time, integration_context.info.cpu_usage);
|
||||
|
||||
|
@ -307,12 +305,12 @@ impl app::App for DemoApp {
|
|||
.unwrap_or_default();
|
||||
|
||||
let link = if web_location_hash == "clock" {
|
||||
Some(demos::DemoLink::Clock)
|
||||
Some(crate::DemoLink::Clock)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let demo_environment = demos::DemoEnvironment {
|
||||
let demo_environment = crate::DemoEnvironment {
|
||||
seconds_since_midnight: integration_context.info.seconds_since_midnight,
|
||||
link,
|
||||
};
|
||||
|
@ -339,7 +337,7 @@ impl app::App for DemoApp {
|
|||
);
|
||||
|
||||
let mut backend_window_open = self.backend_window_open;
|
||||
crate::Window::new("💻 Backend")
|
||||
egui::Window::new("💻 Backend")
|
||||
.min_width(360.0)
|
||||
.scroll(false)
|
||||
.open(&mut backend_window_open)
|
|
@ -1,6 +1,4 @@
|
|||
use crate::widgets::color_picker::show_color;
|
||||
use crate::*;
|
||||
use color::*;
|
||||
use egui::{color::*, widgets::color_picker::show_color, *};
|
||||
use std::collections::HashMap;
|
||||
|
||||
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 {
|
||||
use crate::paint::*;
|
||||
use egui::paint::*;
|
||||
let response = ui.allocate_response(GRADIENT_SIZE, Sense::hover());
|
||||
if bg_fill != Default::default() {
|
||||
let mut triangles = Triangles::default();
|
||||
|
@ -324,12 +322,12 @@ impl Gradient {
|
|||
(0..=n)
|
||||
.map(|i| {
|
||||
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[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[3] as f32)..=(right[3] as f32), t).round() as u8, // Don't ever do this please!
|
||||
])
|
||||
)
|
||||
})
|
||||
.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", serde(default))]
|
||||
|
@ -10,12 +10,13 @@ impl Default for DancingStrings {
|
|||
}
|
||||
}
|
||||
|
||||
impl Demo for DancingStrings {
|
||||
impl crate::Demo for DancingStrings {
|
||||
fn name(&self) -> &str {
|
||||
"♫ Dancing Strings"
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
|
||||
use crate::View;
|
||||
Window::new(self.name())
|
||||
.open(open)
|
||||
.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) {
|
||||
Frame::dark_canvas(ui.style()).show(ui, |ui| {
|
||||
ui.ctx().request_repaint();
|
||||
|
@ -62,6 +63,6 @@ impl View for DancingStrings {
|
|||
|
||||
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
|
||||
#[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", serde(default))]
|
||||
struct LayoutDemo {
|
|
@ -1,8 +1,4 @@
|
|||
use crate::{
|
||||
app,
|
||||
demos::{self, Demo},
|
||||
CtxRef, Resize, ScrollArea, Ui, Window,
|
||||
};
|
||||
use egui::{app, CtxRef, Resize, ScrollArea, Ui, Window};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -29,17 +25,17 @@ pub struct DemoEnvironment {
|
|||
struct Demos {
|
||||
/// open, view
|
||||
#[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 {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
demos: vec![
|
||||
(false, Box::new(crate::demos::FontBook::default())),
|
||||
(false, Box::new(crate::demos::Painting::default())),
|
||||
(false, Box::new(crate::demos::DancingStrings::default())),
|
||||
(false, Box::new(crate::demos::DragAndDropDemo::default())),
|
||||
(false, Box::new(crate::demos::Tests::default())),
|
||||
(false, Box::new(crate::FontBook::default())),
|
||||
(false, Box::new(crate::Painting::default())),
|
||||
(false, Box::new(crate::DancingStrings::default())),
|
||||
(false, Box::new(crate::DragAndDropDemo::default())),
|
||||
(false, Box::new(crate::Tests::default())),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -67,12 +63,12 @@ impl Demos {
|
|||
pub struct DemoWindows {
|
||||
open_windows: OpenWindows,
|
||||
|
||||
demo_window: demos::DemoWindow,
|
||||
demo_window: crate::DemoWindow,
|
||||
|
||||
#[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
|
||||
demos: Demos,
|
||||
|
@ -104,16 +100,16 @@ impl DemoWindows {
|
|||
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");
|
||||
crate::demos::warn_if_debug_build(ui);
|
||||
egui::warn_if_debug_build(ui);
|
||||
|
||||
ui.separator();
|
||||
|
||||
ScrollArea::auto_sized().show(ui, |ui| {
|
||||
ui.label("Egui is an immediate mode GUI library written in Rust.");
|
||||
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 🐧");
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
|
@ -215,7 +211,7 @@ impl DemoWindows {
|
|||
.show(ctx, |ui| {
|
||||
ui.label("scroll: NO");
|
||||
ui.label("resizable: YES");
|
||||
ui.label(demos::LOREM_IPSUM);
|
||||
ui.label(crate::LOREM_IPSUM);
|
||||
});
|
||||
|
||||
Window::new("resizable + embedded scroll")
|
||||
|
@ -228,8 +224,8 @@ impl DemoWindows {
|
|||
ui.label("resizable: YES");
|
||||
ui.heading("We have a sub-region with scroll bar:");
|
||||
ScrollArea::auto_sized().show(ui, |ui| {
|
||||
ui.label(demos::LOREM_IPSUM_LONG);
|
||||
ui.label(demos::LOREM_IPSUM_LONG);
|
||||
ui.label(crate::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
|
||||
});
|
||||
|
@ -242,7 +238,7 @@ impl DemoWindows {
|
|||
.show(ctx, |ui| {
|
||||
ui.label("scroll: YES");
|
||||
ui.label("resizable: YES");
|
||||
ui.label(demos::LOREM_IPSUM_LONG);
|
||||
ui.label(crate::LOREM_IPSUM_LONG);
|
||||
});
|
||||
|
||||
Window::new("auto_sized")
|
||||
|
@ -252,7 +248,7 @@ impl DemoWindows {
|
|||
ui.label("This window will auto-size based on its contents.");
|
||||
ui.heading("Resize this area:");
|
||||
Resize::default().show(ui, |ui| {
|
||||
ui.label(demos::LOREM_IPSUM);
|
||||
ui.label(crate::LOREM_IPSUM);
|
||||
});
|
||||
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>) {
|
||||
use crate::*;
|
||||
use egui::*;
|
||||
|
||||
menu::bar(ui, |ui| {
|
||||
menu::menu(ui, "File", |ui| {
|
|
@ -1,7 +1,4 @@
|
|||
use crate::{
|
||||
demos::{Demo, View},
|
||||
*,
|
||||
};
|
||||
use egui::*;
|
||||
|
||||
pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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 {
|
||||
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 {
|
||||
"✋ Drag and Drop"
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &CtxRef, open: &mut bool) {
|
||||
use crate::View;
|
||||
Window::new(self.name())
|
||||
.open(open)
|
||||
.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) {
|
||||
ui.label("This is a proof-of-concept of drag-and-drop in Egui");
|
||||
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 {
|
||||
standard: bool,
|
||||
emojis: bool,
|
||||
filter: String,
|
||||
text_style: TextStyle,
|
||||
text_style: egui::TextStyle,
|
||||
}
|
||||
|
||||
impl Default for FontBook {
|
||||
|
@ -13,13 +11,14 @@ impl Default for FontBook {
|
|||
standard: false,
|
||||
emojis: true,
|
||||
filter: Default::default(),
|
||||
text_style: TextStyle::Button,
|
||||
text_style: egui::TextStyle::Button,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if self.filter.is_empty()
|
||||
|| name.contains(&self.filter)
|
||||
|
@ -27,7 +26,7 @@ impl FontBook {
|
|||
{
|
||||
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.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 {
|
||||
"🔤 Font Book"
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool) {
|
||||
Window::new(self.name()).open(open).show(ctx, |ui| {
|
||||
use demos::View;
|
||||
fn show(&mut self, ctx: &egui::CtxRef, open: &mut bool) {
|
||||
egui::Window::new(self.name()).open(open).show(ctx, |ui| {
|
||||
use crate::View;
|
||||
self.ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl demos::View for FontBook {
|
||||
fn ui(&mut self, ui: &mut Ui) {
|
||||
use crate::demos::font_contents_emoji::FULL_EMOJI_LIST;
|
||||
use crate::demos::font_contents_ubuntu::UBUNTU_FONT_CHARACTERS;
|
||||
impl crate::View for FontBook {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
use crate::font_contents_emoji::FULL_EMOJI_LIST;
|
||||
use crate::font_contents_ubuntu::UBUNTU_FONT_CHARACTERS;
|
||||
|
||||
ui.label(format!(
|
||||
"Egui supports {} standard characters and {} emojis.\nClick on a character to copy it.",
|
||||
|
@ -66,8 +65,8 @@ impl demos::View for FontBook {
|
|||
|
||||
ui.separator();
|
||||
|
||||
combo_box_with_label(ui, "Text style", format!("{:?}", self.text_style), |ui| {
|
||||
for style in TextStyle::all() {
|
||||
egui::combo_box_with_label(ui, "Text style", format!("{:?}", self.text_style), |ui| {
|
||||
for style in egui::TextStyle::all() {
|
||||
ui.selectable_value(&mut self.text_style, style, format!("{:?}", style));
|
||||
}
|
||||
});
|
||||
|
@ -89,9 +88,9 @@ impl demos::View for FontBook {
|
|||
|
||||
ui.separator();
|
||||
|
||||
crate::ScrollArea::auto_sized().show(ui, |ui| {
|
||||
egui::ScrollArea::auto_sized().show(ui, |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 {
|
||||
self.characters_ui(ui, UBUNTU_FONT_CHARACTERS);
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{containers::*, widgets::*, *};
|
||||
use egui::{containers::*, widgets::*, *};
|
||||
use std::f32::consts::TAU;
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
|
@ -1,6 +1,52 @@
|
|||
//! Demo-code for showing how Egui is used.
|
||||
//!
|
||||
//! 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 color_test;
|
||||
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
|
||||
pub trait View {
|
||||
fn ui(&mut self, ui: &mut crate::Ui);
|
||||
fn ui(&mut self, ui: &mut egui::Ui);
|
||||
}
|
||||
|
||||
/// Something to view
|
||||
|
@ -42,55 +88,20 @@ pub trait Demo {
|
|||
fn name(&self) -> &str;
|
||||
|
||||
/// 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.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __egui_github_link_file {
|
||||
() => {
|
||||
__egui_github_link_file!("(source code)")
|
||||
crate::__egui_github_link_file!("(source code)")
|
||||
};
|
||||
($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_rules! __egui_github_link_file_line {
|
||||
() => {
|
||||
__egui_github_link_file_line!("(source code)")
|
||||
crate::__egui_github_link_file_line!("(source code)")
|
||||
};
|
||||
($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", serde(default))]
|
||||
|
@ -58,7 +59,7 @@ impl Painting {
|
|||
}
|
||||
}
|
||||
|
||||
impl demos::Demo for Painting {
|
||||
impl crate::Demo for Painting {
|
||||
fn name(&self) -> &str {
|
||||
"🖊 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) {
|
||||
ui.add(__egui_github_link_file!("(source code)"));
|
||||
ui.add(crate::__egui_github_link_file!("(source code)"));
|
||||
self.ui_control(ui);
|
||||
ui.label("Paint with your mouse/touch!");
|
||||
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", serde(default))]
|
|
@ -1,4 +1,4 @@
|
|||
use crate::*;
|
||||
use egui::*;
|
||||
use std::f64::INFINITY;
|
||||
|
||||
/// Showcase sliders
|
|
@ -1,23 +1,21 @@
|
|||
use crate::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Tests {}
|
||||
|
||||
impl demos::Demo for Tests {
|
||||
impl crate::Demo for Tests {
|
||||
fn name(&self) -> &str {
|
||||
"📋 Tests"
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &crate::CtxRef, open: &mut bool) {
|
||||
Window::new(self.name()).open(open).show(ctx, |ui| {
|
||||
use demos::View;
|
||||
fn show(&mut self, ctx: &egui::CtxRef, open: &mut bool) {
|
||||
egui::Window::new(self.name()).open(open).show(ctx, |ui| {
|
||||
use crate::View;
|
||||
self.ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl demos::View for Tests {
|
||||
fn ui(&mut self, ui: &mut Ui) {
|
||||
impl crate::View for Tests {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
ui.heading("Name collision example");
|
||||
|
||||
ui.label("\
|
||||
|
@ -46,6 +44,6 @@ impl demos::View for Tests {
|
|||
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.
|
||||
//! This is meant to be read as a tutorial, hence the plethora of comments.
|
||||
use crate::*;
|
||||
|
||||
/// 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:
|
||||
// 1. Decide a size for the widget
|
||||
// 2. Allocate space for it
|
||||
|
@ -25,7 +24,7 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
|||
// 2. Allocating space:
|
||||
// This is where we get a region of the screen assigned.
|
||||
// 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!.
|
||||
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?".
|
||||
// This will, for instance, give us different colors when the widget is hovered or clicked.
|
||||
let visuals = ui.style().interact(&response);
|
||||
let off_bg_fill = 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 bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||
let off_bg_fill = egui::Rgba::new(0.0, 0.0, 0.0, 0.0);
|
||||
let on_bg_fill = egui::Rgba::new(0.0, 0.5, 0.25, 1.0);
|
||||
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.
|
||||
let rect = response.rect;
|
||||
let radius = 0.5 * rect.height();
|
||||
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
||||
// 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 center = pos2(circle_x, rect.center().y);
|
||||
let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
||||
let center = egui::pos2(circle_x, rect.center().y);
|
||||
ui.painter()
|
||||
.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:
|
||||
#[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 response = ui.allocate_response(desired_size, Sense::click());
|
||||
let response = ui.allocate_response(desired_size, egui::Sense::click());
|
||||
*on ^= response.clicked; // toggle if clicked
|
||||
|
||||
let how_on = ui.ctx().animate_bool(response.id, *on);
|
||||
let visuals = ui.style().interact(&response);
|
||||
let off_bg_fill = 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 bg_fill = lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||
let off_bg_fill = egui::Rgba::new(0.0, 0.0, 0.0, 0.0);
|
||||
let on_bg_fill = egui::Rgba::new(0.0, 0.5, 0.25, 1.0);
|
||||
let bg_fill = egui::lerp(off_bg_fill..=on_bg_fill, how_on);
|
||||
let rect = response.rect;
|
||||
let radius = 0.5 * rect.height();
|
||||
ui.painter().rect(rect, radius, bg_fill, visuals.bg_stroke);
|
||||
let circle_x = lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
||||
let center = pos2(circle_x, rect.center().y);
|
||||
let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
|
||||
let center = egui::pos2(circle_x, rect.center().y);
|
||||
ui.painter()
|
||||
.circle(center, 0.75 * radius, visuals.fg_fill, visuals.fg_stroke);
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
pub fn demo(ui: &mut Ui, on: &mut bool) {
|
||||
ui.horizontal_wrapped_for_text(TextStyle::Button, |ui| {
|
||||
pub fn demo(ui: &mut egui::Ui, on: &mut bool) {
|
||||
ui.horizontal_wrapped_for_text(egui::TextStyle::Button, |ui| {
|
||||
ui.label("It's easy to create your own widgets!");
|
||||
ui.label("This toggle switch is just one function and 15 lines of code:");
|
||||
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)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
|
@ -20,7 +20,7 @@ pub struct Widgets {
|
|||
button_enabled: bool,
|
||||
count: usize,
|
||||
radio: Enum,
|
||||
sliders: Sliders,
|
||||
sliders: crate::Sliders,
|
||||
angle: f32,
|
||||
color: Srgba,
|
||||
single_line_text_input: String,
|
||||
|
@ -46,7 +46,7 @@ impl Default for Widgets {
|
|||
|
||||
impl Widgets {
|
||||
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.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");
|
||||
});
|
||||
|
||||
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::Second, "Second");
|
||||
ui.selectable_value(&mut self.radio, Enum::Third, "Third");
|
||||
|
@ -110,12 +110,12 @@ impl Widgets {
|
|||
});
|
||||
|
||||
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)
|
||||
.text("A slider"),
|
||||
);
|
||||
|
||||
CollapsingHeader::new("More sliders")
|
||||
egui::CollapsingHeader::new("More sliders")
|
||||
.default_open(false)
|
||||
.show(ui, |ui| {
|
||||
self.sliders.ui(ui);
|
||||
|
@ -136,7 +136,7 @@ impl Widgets {
|
|||
ui.separator();
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
|
@ -154,6 +154,6 @@ impl Widgets {
|
|||
ui.text_edit_multiline(&mut self.multiline_text_input);
|
||||
|
||||
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