1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 05:40:03 -04:00

Reverted the demos back

This commit is contained in:
Konkitoman
2023-08-04 10:18:24 +03:00
parent e8027b3c3a
commit 6a7d162d40
19 changed files with 304 additions and 549 deletions

View File

@@ -14,7 +14,7 @@ impl super::Demo for About {
.open(open) .open(open)
.show(ctx, |ui| { .show(ctx, |ui| {
use super::View as _; use super::View as _;
Self::default().ui(ui); self.ui(ui);
}); });
} }
} }

View File

@@ -1,21 +1,12 @@
use std::sync::{Arc, RwLock};
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[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 CodeEditorData { pub struct CodeEditor {
language: String, language: String,
code: String, code: String,
} }
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] impl Default for CodeEditor {
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Default, Clone)]
pub struct CodeEditor {
data: Arc<RwLock<CodeEditorData>>,
}
impl Default for CodeEditorData {
fn default() -> Self { fn default() -> Self {
Self { Self {
language: "rs".into(), language: "rs".into(),
@@ -35,18 +26,17 @@ impl super::Demo for CodeEditor {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
use super::View as _; use super::View as _;
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.default_height(500.0) .default_height(500.0)
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, move |ui| self.ui(ui));
} }
} }
impl super::View for CodeEditor { impl super::View for CodeEditor {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
let CodeEditorData { language, code } = &mut *self.data.write().unwrap(); let CodeEditor { language, code } = self;
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.set_height(0.0); ui.set_height(0.0);

View File

@@ -1,17 +1,10 @@
use std::sync::{Arc, RwLock};
#[derive(Debug)] #[derive(Debug)]
pub struct CodeExampleData { pub struct CodeExample {
name: String, name: String,
age: u32, age: u32,
} }
#[derive(Debug, Default, Clone)] impl Default for CodeExample {
pub struct CodeExample {
data: Arc<RwLock<CodeExampleData>>,
}
impl Default for CodeExampleData {
fn default() -> Self { fn default() -> Self {
Self { Self {
name: "Arthur".to_owned(), name: "Arthur".to_owned(),
@@ -36,29 +29,28 @@ impl CodeExample {
});"#, });"#,
); );
// Putting things on the same line using ui.horizontal: // Putting things on the same line using ui.horizontal:
let mut data = self.data.write().unwrap();
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Your name: "); ui.label("Your name: ");
ui.text_edit_singleline(&mut data.name); ui.text_edit_singleline(&mut self.name);
}); });
ui.end_row(); ui.end_row();
show_code( show_code(
ui, ui,
r#"egui::Slider::new(&mut data.age, 0..=120).text("age")"#, r#"egui::Slider::new(&mut self.age, 0..=120).text("age")"#,
); );
ui.add(egui::Slider::new(&mut data.age, 0..=120).text("age")); ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
ui.end_row(); ui.end_row();
show_code( show_code(
ui, ui,
r#" r#"
if ui.button("Click each year").clicked() { if ui.button("Click each year").clicked() {
data.age += 1; self.age += 1;
}"#, }"#,
); );
if ui.button("Click each year").clicked() { if ui.button("Click each year").clicked() {
data.age += 1; self.age += 1;
} }
ui.end_row(); ui.end_row();
@@ -66,7 +58,7 @@ impl CodeExample {
ui, ui,
r#"ui.label(format!("Hello '{}', age {}", self.name, self.age));"#, r#"ui.label(format!("Hello '{}', age {}", self.name, self.age));"#,
); );
ui.label(format!("Hello '{}', age {}", data.name, data.age)); ui.label(format!("Hello '{}', age {}", self.name, self.age));
ui.end_row(); ui.end_row();
} }
} }
@@ -77,14 +69,13 @@ impl super::Demo for CodeExample {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
use super::View; use super::View;
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.default_size([800.0, 400.0]) .default_size([800.0, 400.0])
.vscroll(false) .vscroll(false)
.hscroll(true) .hscroll(true)
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, move |ui| self.ui(ui));
} }
} }

View File

@@ -1,5 +1,3 @@
use std::sync::{Arc, RwLock};
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
enum Plot { enum Plot {
@@ -16,9 +14,10 @@ fn gaussian(x: f64) -> f64 {
fn sigmoid(x: f64) -> f64 { fn sigmoid(x: f64) -> f64 {
-1.0 + 2.0 / (1.0 + f64::exp(-x)) -1.0 + 2.0 / (1.0 + f64::exp(-x))
} }
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ContextMenusData { pub struct ContextMenus {
plot: Plot, plot: Plot,
show_axes: [bool; 2], show_axes: [bool; 2],
allow_drag: bool, allow_drag: bool,
@@ -30,19 +29,7 @@ pub struct ContextMenusData {
height: f32, height: f32,
} }
#[derive(Clone, Default)] impl Default for ContextMenus {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ContextMenus {
data: Arc<RwLock<ContextMenusData>>,
}
impl PartialEq for ContextMenus {
fn eq(&self, other: &Self) -> bool {
*self.data.read().unwrap() == *other.data.read().unwrap()
}
}
impl Default for ContextMenusData {
fn default() -> Self { fn default() -> Self {
Self { Self {
plot: Plot::Sin, plot: Plot::Sin,
@@ -64,13 +51,12 @@ impl super::Demo for ContextMenus {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
use super::View; use super::View;
egui::Window::new(self.name()) egui::Window::new(self.name())
.vscroll(false) .vscroll(false)
.resizable(false) .resizable(false)
.open(open) .open(open)
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, move |ui| self.ui(ui));
} }
} }
@@ -87,14 +73,13 @@ impl super::View for ContextMenus {
ui.label("Right-click plot to edit it!"); ui.label("Right-click plot to edit it!");
ui.horizontal(|ui| { ui.horizontal(|ui| {
self.example_plot(ui).context_menu(|ui| { self.example_plot(ui).context_menu(|ui| {
let data = &mut *self.data.write().unwrap();
ui.menu_button("Plot", |ui| { ui.menu_button("Plot", |ui| {
if ui.radio_value(&mut data.plot, Plot::Sin, "Sin").clicked() if ui.radio_value(&mut self.plot, Plot::Sin, "Sin").clicked()
|| ui || ui
.radio_value(&mut data.plot, Plot::Bell, "Gaussian") .radio_value(&mut self.plot, Plot::Bell, "Gaussian")
.clicked() .clicked()
|| ui || ui
.radio_value(&mut data.plot, Plot::Sigmoid, "Sigmoid") .radio_value(&mut self.plot, Plot::Sigmoid, "Sigmoid")
.clicked() .clicked()
{ {
ui.close_menu(); ui.close_menu();
@@ -102,22 +87,22 @@ impl super::View for ContextMenus {
}); });
egui::Grid::new("button_grid").show(ui, |ui| { egui::Grid::new("button_grid").show(ui, |ui| {
ui.add( ui.add(
egui::DragValue::new(&mut data.width) egui::DragValue::new(&mut self.width)
.speed(1.0) .speed(1.0)
.prefix("Width:"), .prefix("Width:"),
); );
ui.add( ui.add(
egui::DragValue::new(&mut data.height) egui::DragValue::new(&mut self.height)
.speed(1.0) .speed(1.0)
.prefix("Height:"), .prefix("Height:"),
); );
ui.end_row(); ui.end_row();
ui.checkbox(&mut data.show_axes[0], "x-Axis"); ui.checkbox(&mut self.show_axes[0], "x-Axis");
ui.checkbox(&mut data.show_axes[1], "y-Axis"); ui.checkbox(&mut self.show_axes[1], "y-Axis");
ui.end_row(); ui.end_row();
if ui.checkbox(&mut data.allow_drag, "Drag").changed() if ui.checkbox(&mut self.allow_drag, "Drag").changed()
|| ui.checkbox(&mut data.allow_zoom, "Zoom").changed() || ui.checkbox(&mut self.allow_zoom, "Zoom").changed()
|| ui.checkbox(&mut data.allow_scroll, "Scroll").changed() || ui.checkbox(&mut self.allow_scroll, "Scroll").changed()
{ {
ui.close_menu(); ui.close_menu();
} }
@@ -132,7 +117,6 @@ impl super::View for ContextMenus {
impl ContextMenus { impl ContextMenus {
fn example_plot(&self, ui: &mut egui::Ui) -> egui::Response { fn example_plot(&self, ui: &mut egui::Ui) -> egui::Response {
let data = &mut *self.data.write().unwrap();
use egui::plot::{Line, PlotPoints}; use egui::plot::{Line, PlotPoints};
let n = 128; let n = 128;
let line = Line::new( let line = Line::new(
@@ -140,7 +124,7 @@ impl ContextMenus {
.map(|i| { .map(|i| {
use std::f64::consts::TAU; use std::f64::consts::TAU;
let x = egui::remap(i as f64, 0.0..=n as f64, -TAU..=TAU); let x = egui::remap(i as f64, 0.0..=n as f64, -TAU..=TAU);
match data.plot { match self.plot {
Plot::Sin => [x, x.sin()], Plot::Sin => [x, x.sin()],
Plot::Bell => [x, 10.0 * gaussian(x)], Plot::Bell => [x, 10.0 * gaussian(x)],
Plot::Sigmoid => [x, sigmoid(x)], Plot::Sigmoid => [x, sigmoid(x)],
@@ -149,14 +133,14 @@ impl ContextMenus {
.collect::<PlotPoints>(), .collect::<PlotPoints>(),
); );
egui::plot::Plot::new("example_plot") egui::plot::Plot::new("example_plot")
.show_axes(data.show_axes) .show_axes(self.show_axes)
.allow_drag(data.allow_drag) .allow_drag(self.allow_drag)
.allow_zoom(data.allow_zoom) .allow_zoom(self.allow_zoom)
.allow_scroll(data.allow_scroll) .allow_scroll(self.allow_scroll)
.center_x_axis(data.center_x_axis) .center_x_axis(self.center_x_axis)
.center_x_axis(data.center_y_axis) .center_x_axis(self.center_y_axis)
.width(data.width) .width(self.width)
.height(data.height) .height(self.height)
.data_aspect(1.0) .data_aspect(1.0)
.show(ui, |plot_ui| plot_ui.line(line)) .show(ui, |plot_ui| plot_ui.line(line))
.response .response

View File

@@ -1,5 +1,3 @@
use std::sync::{Arc, RwLock};
use egui::*; use egui::*;
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)) {
@@ -77,32 +75,23 @@ pub fn drop_target<R>(
InnerResponse::new(ret, response) InnerResponse::new(ret, response)
} }
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct DragAndDropDemo { pub struct DragAndDropDemo {
/// columns with items /// columns with items
columns: Arc<RwLock<Vec<Vec<String>>>>, columns: Vec<Vec<String>>,
}
impl PartialEq for DragAndDropDemo {
fn eq(&self, other: &Self) -> bool {
*self.columns.read().unwrap() == *other.columns.read().unwrap()
}
} }
impl Default for DragAndDropDemo { impl Default for DragAndDropDemo {
fn default() -> Self { fn default() -> Self {
Self { Self {
columns: Arc::new(RwLock::new( columns: vec![
vec![ vec!["Item A", "Item B", "Item C"],
vec!["Item A", "Item B", "Item C"], vec!["Item D", "Item E"],
vec!["Item D", "Item E"], vec!["Item F", "Item G", "Item H"],
vec!["Item F", "Item G", "Item H"], ]
] .into_iter()
.into_iter() .map(|v| v.into_iter().map(ToString::to_string).collect())
.map(|v| v.into_iter().map(ToString::to_string).collect()) .collect(),
.collect(),
)),
} }
} }
} }
@@ -113,14 +102,13 @@ impl super::Demo for DragAndDropDemo {
} }
fn show(&mut self, ctx: &Context, open: &mut bool) { fn show(&mut self, ctx: &Context, open: &mut bool) {
let clone = self.clone();
use super::View as _; use super::View as _;
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))
.vscroll(false) .vscroll(false)
.resizable(false) .resizable(false)
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, move |ui| self.ui(ui));
} }
} }
@@ -132,7 +120,7 @@ impl super::View for DragAndDropDemo {
let id_source = "my_drag_and_drop_demo"; let id_source = "my_drag_and_drop_demo";
let mut source_col_row = None; let mut source_col_row = None;
let mut drop_col = None; let mut drop_col = None;
let mut columns = self.columns.write().unwrap(); let columns = &mut self.columns;
ui.columns(columns.len(), |uis| { ui.columns(columns.len(), |uis| {
for (col_idx, column) in columns.clone().into_iter().enumerate() { for (col_idx, column) in columns.clone().into_iter().enumerate() {
let ui = &mut uis[col_idx]; let ui = &mut uis[col_idx];

View File

@@ -1,19 +1,11 @@
use std::{ use std::collections::BTreeMap;
collections::BTreeMap, pub struct FontBook {
sync::{Arc, RwLock},
};
pub struct FontBookData {
filter: String, filter: String,
font_id: egui::FontId, font_id: egui::FontId,
named_chars: BTreeMap<egui::FontFamily, BTreeMap<char, String>>, named_chars: BTreeMap<egui::FontFamily, BTreeMap<char, String>>,
} }
#[derive(Default, Clone)] impl Default for FontBook {
pub struct FontBook {
data: Arc<RwLock<FontBookData>>,
}
impl Default for FontBookData {
fn default() -> Self { fn default() -> Self {
Self { Self {
filter: Default::default(), filter: Default::default(),
@@ -29,12 +21,11 @@ impl super::Demo for FontBook {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -45,12 +36,10 @@ impl super::View for FontBook {
ui.add(crate::egui_github_link_file!()); ui.add(crate::egui_github_link_file!());
}); });
let data = &mut *self.data.write().unwrap();
ui.label(format!( ui.label(format!(
"The selected font supports {} characters.", "The selected font supports {} characters.",
data.named_chars self.named_chars
.get(&data.font_id.family) .get(&self.font_id.family)
.map(|map| map.len()) .map(|map| map.len())
.unwrap_or_default() .unwrap_or_default()
)); ));
@@ -67,22 +56,22 @@ impl super::View for FontBook {
ui.separator(); ui.separator();
egui::introspection::font_id_ui(ui, &mut data.font_id); egui::introspection::font_id_ui(ui, &mut self.font_id);
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Filter:"); ui.label("Filter:");
ui.add(egui::TextEdit::singleline(&mut data.filter).desired_width(120.0)); ui.add(egui::TextEdit::singleline(&mut self.filter).desired_width(120.0));
data.filter = data.filter.to_lowercase(); self.filter = self.filter.to_lowercase();
if ui.button("").clicked() { if ui.button("").clicked() {
data.filter.clear(); self.filter.clear();
} }
}); });
let filter = &data.filter; let filter = &self.filter;
let named_chars = data let named_chars = self
.named_chars .named_chars
.entry(data.font_id.family.clone()) .entry(self.font_id.family.clone())
.or_insert_with(|| available_characters(ui, data.font_id.family.clone())); .or_insert_with(|| available_characters(ui, self.font_id.family.clone()));
ui.separator(); ui.separator();
@@ -93,13 +82,13 @@ impl super::View for FontBook {
for (&chr, name) in named_chars { for (&chr, name) in named_chars {
if filter.is_empty() || name.contains(filter) || *filter == chr.to_string() { if filter.is_empty() || name.contains(filter) || *filter == chr.to_string() {
let button = egui::Button::new( let button = egui::Button::new(
egui::RichText::new(chr.to_string()).font(data.font_id.clone()), egui::RichText::new(chr.to_string()).font(self.font_id.clone()),
) )
.frame(false); .frame(false);
let tooltip_ui = |ui: &mut egui::Ui| { let tooltip_ui = |ui: &mut egui::Ui| {
ui.label( ui.label(
egui::RichText::new(chr.to_string()).font(data.font_id.clone()), egui::RichText::new(chr.to_string()).font(self.font_id.clone()),
); );
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));
}; };

View File

@@ -1,10 +1,8 @@
use std::sync::{Arc, RwLock};
use egui::*; 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))]
pub struct LayoutTestData { pub struct LayoutTest {
// Identical to contents of `egui::Layout` // Identical to contents of `egui::Layout`
layout: LayoutSettings, layout: LayoutSettings,
@@ -13,14 +11,7 @@ pub struct LayoutTestData {
wrap_row_height: f32, wrap_row_height: f32,
} }
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] impl Default for LayoutTest {
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Default, Clone)]
pub struct LayoutTest {
data: Arc<RwLock<LayoutTestData>>,
}
impl Default for LayoutTestData {
fn default() -> Self { fn default() -> Self {
Self { Self {
layout: LayoutSettings::top_down(), layout: LayoutSettings::top_down(),
@@ -88,13 +79,12 @@ impl super::Demo for LayoutTest {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.resizable(false) .resizable(false)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -103,24 +93,23 @@ impl super::View for LayoutTest {
fn ui(&mut self, ui: &mut Ui) { fn ui(&mut self, ui: &mut Ui) {
ui.label("Tests and demonstrates the limits of the egui layouts"); ui.label("Tests and demonstrates the limits of the egui layouts");
self.content_ui(ui); self.content_ui(ui);
let data = self.data.write().unwrap();
Resize::default() Resize::default()
.default_size([150.0, 200.0]) .default_size([150.0, 200.0])
.show(ui, |ui| { .show(ui, |ui| {
if data.layout.main_wrap { if self.layout.main_wrap {
if data.layout.main_dir.is_horizontal() { if self.layout.main_dir.is_horizontal() {
ui.allocate_ui( ui.allocate_ui(
vec2(ui.available_size_before_wrap().x, data.wrap_row_height), vec2(ui.available_size_before_wrap().x, self.wrap_row_height),
|ui| ui.with_layout(data.layout.layout(), demo_ui), |ui| ui.with_layout(self.layout.layout(), demo_ui),
); );
} else { } else {
ui.allocate_ui( ui.allocate_ui(
vec2(data.wrap_column_width, ui.available_size_before_wrap().y), vec2(self.wrap_column_width, ui.available_size_before_wrap().y),
|ui| ui.with_layout(data.layout.layout(), demo_ui), |ui| ui.with_layout(self.layout.layout(), demo_ui),
); );
} }
} else { } else {
ui.with_layout(data.layout.layout(), demo_ui); ui.with_layout(self.layout.layout(), demo_ui);
} }
}); });
ui.label("Resize to see effect"); ui.label("Resize to see effect");
@@ -129,16 +118,15 @@ impl super::View for LayoutTest {
impl LayoutTest { impl LayoutTest {
pub fn content_ui(&mut self, ui: &mut Ui) { pub fn content_ui(&mut self, ui: &mut Ui) {
let mut data = self.data.write().unwrap();
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.selectable_value(&mut data.layout, LayoutSettings::top_down(), "Top-down"); ui.selectable_value(&mut self.layout, LayoutSettings::top_down(), "Top-down");
ui.selectable_value( ui.selectable_value(
&mut data.layout, &mut self.layout,
LayoutSettings::top_down_justified_centered(), LayoutSettings::top_down_justified_centered(),
"Top-down, centered and justified", "Top-down, centered and justified",
); );
ui.selectable_value( ui.selectable_value(
&mut data.layout, &mut self.layout,
LayoutSettings::horizontal_wrapped(), LayoutSettings::horizontal_wrapped(),
"Horizontal wrapped", "Horizontal wrapped",
); );
@@ -152,20 +140,20 @@ impl LayoutTest {
Direction::TopDown, Direction::TopDown,
Direction::BottomUp, Direction::BottomUp,
] { ] {
ui.radio_value(&mut data.layout.main_dir, dir, format!("{:?}", dir)); ui.radio_value(&mut self.layout.main_dir, dir, format!("{:?}", dir));
} }
}); });
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.checkbox(&mut data.layout.main_wrap, "Main wrap") ui.checkbox(&mut self.layout.main_wrap, "Main wrap")
.on_hover_text("Wrap when next widget doesn't fit the current row/column"); .on_hover_text("Wrap when next widget doesn't fit the current row/column");
if data.layout.main_wrap { if self.layout.main_wrap {
if data.layout.main_dir.is_horizontal() { if self.layout.main_dir.is_horizontal() {
ui.add(Slider::new(&mut data.wrap_row_height, 0.0..=200.0).text("Row height")); ui.add(Slider::new(&mut self.wrap_row_height, 0.0..=200.0).text("Row height"));
} else { } else {
ui.add( ui.add(
Slider::new(&mut data.wrap_column_width, 0.0..=200.0).text("Column width"), Slider::new(&mut self.wrap_column_width, 0.0..=200.0).text("Column width"),
); );
} }
} }
@@ -174,11 +162,11 @@ impl LayoutTest {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Cross Align:"); ui.label("Cross Align:");
for &align in &[Align::Min, Align::Center, Align::Max] { for &align in &[Align::Min, Align::Center, Align::Max] {
ui.radio_value(&mut data.layout.cross_align, align, format!("{:?}", align)); ui.radio_value(&mut self.layout.cross_align, align, format!("{:?}", align));
} }
}); });
ui.checkbox(&mut data.layout.cross_justify, "Cross Justified") ui.checkbox(&mut self.layout.cross_justify, "Cross Justified")
.on_hover_text("Try to fill full width/height (e.g. buttons)"); .on_hover_text("Try to fill full width/height (e.g. buttons)");
} }
} }

View File

@@ -1,12 +1,11 @@
use std::sync::{Arc, RwLock};
use super::*; use super::*;
use crate::LOREM_IPSUM; use crate::LOREM_IPSUM;
use egui::{epaint::text::TextWrapping, *}; use egui::{epaint::text::TextWrapping, *};
/// Showcase some ui code
#[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 MiscDemoWindowData { pub struct MiscDemoWindow {
num_columns: usize, num_columns: usize,
break_anywhere: bool, break_anywhere: bool,
@@ -22,17 +21,10 @@ pub struct MiscDemoWindowData {
dummy_bool: bool, dummy_bool: bool,
dummy_usize: usize, dummy_usize: usize,
} }
/// Showcase some ui code
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Default, Clone)]
pub struct MiscDemoWindow {
data: Arc<RwLock<MiscDemoWindowData>>,
}
impl Default for MiscDemoWindowData { impl Default for MiscDemoWindow {
fn default() -> MiscDemoWindowData { fn default() -> MiscDemoWindow {
MiscDemoWindowData { MiscDemoWindow {
num_columns: 2, num_columns: 2,
max_rows: 2, max_rows: 2,
@@ -57,12 +49,11 @@ impl Demo for MiscDemoWindow {
} }
fn show(&mut self, ctx: &Context, open: &mut bool) { fn show(&mut self, ctx: &Context, open: &mut bool) {
let clone = self.clone();
Window::new(self.name()) Window::new(self.name())
.open(open) .open(open)
.vscroll(true) .vscroll(true)
.hscroll(true) .hscroll(true)
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, move |ui| self.ui(ui));
} }
} }
@@ -70,13 +61,10 @@ impl View for MiscDemoWindow {
fn ui(&mut self, ui: &mut Ui) { fn ui(&mut self, ui: &mut Ui) {
ui.set_min_width(250.0); ui.set_min_width(250.0);
let mut data = self.data.write().unwrap();
let data = &mut *data;
CollapsingHeader::new("Widgets") CollapsingHeader::new("Widgets")
.default_open(true) .default_open(true)
.show(ui, |ui| { .show(ui, |ui| {
data.widgets.ui(ui); self.widgets.ui(ui);
}); });
CollapsingHeader::new("Text layout") CollapsingHeader::new("Text layout")
@@ -84,25 +72,25 @@ impl View for MiscDemoWindow {
.show(ui, |ui| { .show(ui, |ui| {
text_layout_ui( text_layout_ui(
ui, ui,
&mut data.max_rows, &mut self.max_rows,
&mut data.break_anywhere, &mut self.break_anywhere,
&mut data.overflow_character, &mut self.overflow_character,
); );
}); });
CollapsingHeader::new("Colors") CollapsingHeader::new("Colors")
.default_open(false) .default_open(false)
.show(ui, |ui| { .show(ui, |ui| {
data.colors.ui(ui); self.colors.ui(ui);
}); });
CollapsingHeader::new("Custom Collapsing Header") CollapsingHeader::new("Custom Collapsing Header")
.default_open(false) .default_open(false)
.show(ui, |ui| data.custom_collapsing_header.ui(ui)); .show(ui, |ui| self.custom_collapsing_header.ui(ui));
CollapsingHeader::new("Tree") CollapsingHeader::new("Tree")
.default_open(false) .default_open(false)
.show(ui, |ui| data.tree.ui(ui)); .show(ui, |ui| self.tree.ui(ui));
CollapsingHeader::new("Checkboxes") CollapsingHeader::new("Checkboxes")
.default_open(false) .default_open(false)
@@ -111,28 +99,28 @@ impl View for MiscDemoWindow {
ui.spacing_mut().item_spacing = Vec2::ZERO; ui.spacing_mut().item_spacing = Vec2::ZERO;
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
for _ in 0..64 { for _ in 0..64 {
ui.checkbox(&mut data.dummy_bool, ""); ui.checkbox(&mut self.dummy_bool, "");
} }
}); });
ui.checkbox(&mut data.dummy_bool, "checkbox"); ui.checkbox(&mut self.dummy_bool, "checkbox");
ui.label("Radiobuttons are similar:"); ui.label("Radiobuttons are similar:");
ui.spacing_mut().item_spacing = Vec2::ZERO; ui.spacing_mut().item_spacing = Vec2::ZERO;
ui.horizontal_wrapped(|ui| { ui.horizontal_wrapped(|ui| {
for i in 0..64 { for i in 0..64 {
ui.radio_value(&mut data.dummy_usize, i, ""); ui.radio_value(&mut self.dummy_usize, i, "");
} }
}); });
ui.radio_value(&mut data.dummy_usize, 64, "radio_value"); ui.radio_value(&mut self.dummy_usize, 64, "radio_value");
}); });
ui.collapsing("Columns", |ui| { ui.collapsing("Columns", |ui| {
ui.add(Slider::new(&mut data.num_columns, 1..=10).text("Columns")); ui.add(Slider::new(&mut self.num_columns, 1..=10).text("Columns"));
ui.columns(data.num_columns, |cols| { ui.columns(self.num_columns, |cols| {
for (i, col) in cols.iter_mut().enumerate() { for (i, col) in cols.iter_mut().enumerate() {
col.label(format!("Column {} out of {}", i + 1, data.num_columns)); col.label(format!("Column {} out of {}", i + 1, self.num_columns));
if i + 1 == data.num_columns && col.button("Delete this").clicked() { if i + 1 == self.num_columns && col.button("Delete this").clicked() {
data.num_columns -= 1; self.num_columns -= 1;
} }
} }
}); });
@@ -140,7 +128,7 @@ impl View for MiscDemoWindow {
CollapsingHeader::new("Test box rendering") CollapsingHeader::new("Test box rendering")
.default_open(false) .default_open(false)
.show(ui, |ui| data.box_painting.ui(ui)); .show(ui, |ui| self.box_painting.ui(ui));
CollapsingHeader::new("Resize") CollapsingHeader::new("Resize")
.default_open(false) .default_open(false)

View File

@@ -1,23 +1,16 @@
use std::sync::{Arc, RwLock};
use egui::{ use egui::{
emath::{RectTransform, Rot2}, emath::{RectTransform, Rot2},
vec2, Color32, Frame, Pos2, Rect, Sense, Stroke, Vec2, vec2, Color32, Frame, Pos2, Rect, Sense, Stroke, Vec2,
}; };
pub struct MultiTouchData { pub struct MultiTouch {
rotation: f32, rotation: f32,
translation: Vec2, translation: Vec2,
zoom: f32, zoom: f32,
last_touch_time: f64, last_touch_time: f64,
} }
#[derive(Clone, Default)] impl Default for MultiTouch {
pub struct MultiTouch {
data: Arc<RwLock<MultiTouchData>>,
}
impl Default for MultiTouchData {
fn default() -> Self { fn default() -> Self {
Self { Self {
rotation: 0., rotation: 0.,
@@ -34,14 +27,13 @@ impl super::Demo for MultiTouch {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.default_size(vec2(512.0, 512.0)) .default_size(vec2(512.0, 512.0))
.resizable(true) .resizable(true)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -91,24 +83,22 @@ impl super::View for MultiTouch {
// color and width: // color and width:
let mut stroke_width = 1.; let mut stroke_width = 1.;
if let Some(multi_touch) = ui.ctx().multi_touch() { if let Some(multi_touch) = ui.ctx().multi_touch() {
let mut data = self.data.write().unwrap();
// This adjusts the current zoom factor and rotation angle according to the dynamic // This adjusts the current zoom factor and rotation angle according to the dynamic
// change (for the current frame) of the touch gesture: // change (for the current frame) of the touch gesture:
data.zoom *= multi_touch.zoom_delta; self.zoom *= multi_touch.zoom_delta;
data.rotation += multi_touch.rotation_delta; self.rotation += multi_touch.rotation_delta;
// the translation we get from `multi_touch` needs to be scaled down to the // the translation we get from `multi_touch` needs to be scaled down to the
// normalized coordinates we use as the basis for painting: // normalized coordinates we use as the basis for painting:
data.translation += to_screen.inverse().scale() * multi_touch.translation_delta; self.translation += to_screen.inverse().scale() * multi_touch.translation_delta;
// touch pressure will make the arrow thicker (not all touch devices support this): // touch pressure will make the arrow thicker (not all touch devices support this):
stroke_width += 10. * multi_touch.force; stroke_width += 10. * multi_touch.force;
data.last_touch_time = ui.input(|i| i.time); self.last_touch_time = ui.input(|i| i.time);
} else { } else {
self.slowly_reset(ui); self.slowly_reset(ui);
} }
let data = self.data.read().unwrap(); let zoom_and_rotate = self.zoom * Rot2::from_angle(self.rotation);
let zoom_and_rotate = data.zoom * Rot2::from_angle(data.rotation); let arrow_start_offset = self.translation + zoom_and_rotate * vec2(-0.5, 0.5);
let arrow_start_offset = data.translation + zoom_and_rotate * vec2(-0.5, 0.5);
// Paints an arrow pointing from bottom-left (-0.5, 0.5) to top-right (0.5, -0.5), but // Paints an arrow pointing from bottom-left (-0.5, 0.5) to top-right (0.5, -0.5), but
// scaled, rotated, and translated according to the current touch gesture: // scaled, rotated, and translated according to the current touch gesture:
@@ -128,8 +118,7 @@ impl MultiTouch {
// This has nothing to do with the touch gesture. It just smoothly brings the // This has nothing to do with the touch gesture. It just smoothly brings the
// painted arrow back into its original position, for a nice visual effect: // painted arrow back into its original position, for a nice visual effect:
let mut data = self.data.write().unwrap(); let time_since_last_touch = (ui.input(|i| i.time) - self.last_touch_time) as f32;
let time_since_last_touch = (ui.input(|i| i.time) - data.last_touch_time) as f32;
let delay = 0.5; let delay = 0.5;
if time_since_last_touch < delay { if time_since_last_touch < delay {
@@ -140,15 +129,15 @@ impl MultiTouch {
egui::remap_clamp(time_since_last_touch, delay..=1.0, 1.0..=0.0).powf(4.0); egui::remap_clamp(time_since_last_touch, delay..=1.0, 1.0..=0.0).powf(4.0);
if half_life <= 1e-3 { if half_life <= 1e-3 {
data.zoom = 1.0; self.zoom = 1.0;
data.rotation = 0.0; self.rotation = 0.0;
data.translation = Vec2::ZERO; self.translation = Vec2::ZERO;
} else { } else {
let dt = ui.input(|i| i.unstable_dt); let dt = ui.input(|i| i.unstable_dt);
let half_life_factor = (-(2_f32.ln()) / half_life * dt).exp(); let half_life_factor = (-(2_f32.ln()) / half_life * dt).exp();
data.zoom = 1. + ((data.zoom - 1.) * half_life_factor); self.zoom = 1. + ((self.zoom - 1.) * half_life_factor);
data.rotation *= half_life_factor; self.rotation *= half_life_factor;
data.translation *= half_life_factor; self.translation *= half_life_factor;
ui.ctx().request_repaint(); ui.ctx().request_repaint();
} }
} }

View File

@@ -1,11 +1,9 @@
use std::sync::{Arc, RwLock};
use egui::epaint::{CubicBezierShape, PathShape, QuadraticBezierShape}; use egui::epaint::{CubicBezierShape, PathShape, QuadraticBezierShape};
use egui::*; 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))]
pub struct PaintBezierData { pub struct PaintBezier {
/// Bézier curve degree, it can be 3, 4. /// Bézier curve degree, it can be 3, 4.
degree: usize, degree: usize,
@@ -24,14 +22,7 @@ pub struct PaintBezierData {
bounding_box_stroke: Stroke, bounding_box_stroke: Stroke,
} }
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] impl Default for PaintBezier {
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Default, Clone)]
pub struct PaintBezier {
data: Arc<RwLock<PaintBezierData>>,
}
impl Default for PaintBezierData {
fn default() -> Self { fn default() -> Self {
Self { Self {
degree: 4, degree: 4,
@@ -51,15 +42,14 @@ impl Default for PaintBezierData {
impl PaintBezier { impl PaintBezier {
pub fn ui_control(&mut self, ui: &mut egui::Ui) { pub fn ui_control(&mut self, ui: &mut egui::Ui) {
let mut data = self.data.write().unwrap();
ui.collapsing("Colors", |ui| { ui.collapsing("Colors", |ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Fill color:"); ui.label("Fill color:");
ui.color_edit_button_srgba(&mut data.fill); ui.color_edit_button_srgba(&mut self.fill);
}); });
egui::stroke_ui(ui, &mut data.stroke, "Curve Stroke"); egui::stroke_ui(ui, &mut self.stroke, "Curve Stroke");
egui::stroke_ui(ui, &mut data.aux_stroke, "Auxiliary Stroke"); egui::stroke_ui(ui, &mut self.aux_stroke, "Auxiliary Stroke");
egui::stroke_ui(ui, &mut data.bounding_box_stroke, "Bounding Box Stroke"); egui::stroke_ui(ui, &mut self.bounding_box_stroke, "Bounding Box Stroke");
}); });
ui.collapsing("Global tessellation options", |ui| { ui.collapsing("Global tessellation options", |ui| {
@@ -69,8 +59,8 @@ impl PaintBezier {
.tessellation_options_mut(|to| *to = tessellation_options); .tessellation_options_mut(|to| *to = tessellation_options);
}); });
ui.radio_value(&mut data.degree, 3, "Quadratic Bézier"); ui.radio_value(&mut self.degree, 3, "Quadratic Bézier");
ui.radio_value(&mut data.degree, 4, "Cubic Bézier"); ui.radio_value(&mut self.degree, 4, "Cubic Bézier");
ui.label("Move the points by dragging them."); ui.label("Move the points by dragging them.");
ui.small("Only convex curves can be accurately filled."); ui.small("Only convex curves can be accurately filled.");
} }
@@ -85,14 +75,12 @@ impl PaintBezier {
); );
let control_point_radius = 8.0; let control_point_radius = 8.0;
let mut data = self.data.write().unwrap();
let data = &mut *data;
let control_point_shapes: Vec<Shape> = data let control_point_shapes: Vec<Shape> = self
.control_points .control_points
.iter_mut() .iter_mut()
.enumerate() .enumerate()
.take(data.degree) .take(self.degree)
.map(|(i, point)| { .map(|(i, point)| {
let size = Vec2::splat(2.0 * control_point_radius); let size = Vec2::splat(2.0 * control_point_radius);
@@ -111,33 +99,33 @@ impl PaintBezier {
}) })
.collect(); .collect();
let points_in_screen: Vec<Pos2> = data let points_in_screen: Vec<Pos2> = self
.control_points .control_points
.iter() .iter()
.take(data.degree) .take(self.degree)
.map(|p| to_screen * *p) .map(|p| to_screen * *p)
.collect(); .collect();
match data.degree { match self.degree {
3 => { 3 => {
let points = points_in_screen.clone().try_into().unwrap(); let points = points_in_screen.clone().try_into().unwrap();
let shape = let shape =
QuadraticBezierShape::from_points_stroke(points, true, data.fill, data.stroke); QuadraticBezierShape::from_points_stroke(points, true, self.fill, self.stroke);
painter.add(epaint::RectShape::stroke( painter.add(epaint::RectShape::stroke(
shape.visual_bounding_rect(), shape.visual_bounding_rect(),
0.0, 0.0,
data.bounding_box_stroke, self.bounding_box_stroke,
)); ));
painter.add(shape); painter.add(shape);
} }
4 => { 4 => {
let points = points_in_screen.clone().try_into().unwrap(); let points = points_in_screen.clone().try_into().unwrap();
let shape = let shape =
CubicBezierShape::from_points_stroke(points, true, data.fill, data.stroke); CubicBezierShape::from_points_stroke(points, true, self.fill, self.stroke);
painter.add(epaint::RectShape::stroke( painter.add(epaint::RectShape::stroke(
shape.visual_bounding_rect(), shape.visual_bounding_rect(),
0.0, 0.0,
data.bounding_box_stroke, self.bounding_box_stroke,
)); ));
painter.add(shape); painter.add(shape);
} }
@@ -146,7 +134,7 @@ impl PaintBezier {
} }
}; };
painter.add(PathShape::line(points_in_screen, data.aux_stroke)); painter.add(PathShape::line(points_in_screen, self.aux_stroke));
painter.extend(control_point_shapes); painter.extend(control_point_shapes);
response response
@@ -159,14 +147,13 @@ impl super::Demo for PaintBezier {
} }
fn show(&mut self, ctx: &Context, open: &mut bool) { fn show(&mut self, ctx: &Context, open: &mut bool) {
let clone = self.clone();
use super::View as _; use super::View as _;
Window::new(self.name()) Window::new(self.name())
.open(open) .open(open)
.vscroll(false) .vscroll(false)
.resizable(false) .resizable(false)
.default_size([300.0, 350.0]) .default_size([300.0, 350.0])
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, move |ui| self.ui(ui));
} }
} }

View File

@@ -1,22 +1,14 @@
use std::sync::{Arc, RwLock};
use egui::*; 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))]
pub struct PaintingData { pub struct Painting {
/// in 0-1 normalized coordinates /// in 0-1 normalized coordinates
lines: Vec<Vec<Pos2>>, lines: Vec<Vec<Pos2>>,
stroke: Stroke, stroke: Stroke,
} }
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] impl Default for Painting {
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Default, Clone)]
pub struct Painting {
data: Arc<RwLock<PaintingData>>,
}
impl Default for PaintingData {
fn default() -> Self { fn default() -> Self {
Self { Self {
lines: Default::default(), lines: Default::default(),
@@ -27,12 +19,11 @@ impl Default for PaintingData {
impl Painting { impl Painting {
pub fn ui_control(&mut self, ui: &mut egui::Ui) -> egui::Response { pub fn ui_control(&mut self, ui: &mut egui::Ui) -> egui::Response {
let mut data = self.data.write().unwrap();
ui.horizontal(|ui| { ui.horizontal(|ui| {
egui::stroke_ui(ui, &mut data.stroke, "Stroke"); egui::stroke_ui(ui, &mut self.stroke, "Stroke");
ui.separator(); ui.separator();
if ui.button("Clear Painting").clicked() { if ui.button("Clear Painting").clicked() {
data.lines.clear(); self.lines.clear();
} }
}) })
.response .response
@@ -48,13 +39,11 @@ impl Painting {
); );
let from_screen = to_screen.inverse(); let from_screen = to_screen.inverse();
let mut data = self.data.write().unwrap(); if self.lines.is_empty() {
self.lines.push(vec![]);
if data.lines.is_empty() {
data.lines.push(vec![]);
} }
let current_line = data.lines.last_mut().unwrap(); let current_line = self.lines.last_mut().unwrap();
if let Some(pointer_pos) = response.interact_pointer_pos() { if let Some(pointer_pos) = response.interact_pointer_pos() {
let canvas_pos = from_screen * pointer_pos; let canvas_pos = from_screen * pointer_pos;
@@ -63,17 +52,17 @@ impl Painting {
response.mark_changed(); response.mark_changed();
} }
} else if !current_line.is_empty() { } else if !current_line.is_empty() {
data.lines.push(vec![]); self.lines.push(vec![]);
response.mark_changed(); response.mark_changed();
} }
let shapes = data let shapes = self
.lines .lines
.iter() .iter()
.filter(|line| line.len() >= 2) .filter(|line| line.len() >= 2)
.map(|line| { .map(|line| {
let points: Vec<Pos2> = line.iter().map(|p| to_screen * *p).collect(); let points: Vec<Pos2> = line.iter().map(|p| to_screen * *p).collect();
egui::Shape::line(points, data.stroke) egui::Shape::line(points, self.stroke)
}); });
painter.extend(shapes); painter.extend(shapes);
@@ -88,13 +77,12 @@ impl super::Demo for Painting {
} }
fn show(&mut self, ctx: &Context, open: &mut bool) { fn show(&mut self, ctx: &Context, open: &mut bool) {
let clone = self.clone();
use super::View as _; use super::View as _;
Window::new(self.name()) Window::new(self.name())
.open(open) .open(open)
.default_size(vec2(512.0, 512.0)) .default_size(vec2(512.0, 512.0))
.vscroll(false) .vscroll(false)
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, move |ui| self.ui(ui));
} }
} }

View File

@@ -1,6 +1,5 @@
use std::f64::consts::TAU; use std::f64::consts::TAU;
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use std::sync::{Arc, RwLock};
use egui::plot::{AxisBools, GridInput, GridMark, PlotResponse}; use egui::plot::{AxisBools, GridInput, GridMark, PlotResponse};
use egui::*; use egui::*;
@@ -31,9 +30,8 @@ impl Default for Panel {
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[derive(Default, PartialEq)]
#[derive(PartialEq, Default)] pub struct PlotDemo {
pub struct PlotDemoData {
line_demo: LineDemo, line_demo: LineDemo,
marker_demo: MarkerDemo, marker_demo: MarkerDemo,
legend_demo: LegendDemo, legend_demo: LegendDemo,
@@ -45,30 +43,18 @@ pub struct PlotDemoData {
open_panel: Panel, open_panel: Panel,
} }
#[derive(Default, Clone)]
pub struct PlotDemo {
data: Arc<RwLock<PlotDemoData>>,
}
impl PartialEq for PlotDemo {
fn eq(&self, other: &Self) -> bool {
*self.data.read().unwrap() == *other.data.read().unwrap()
}
}
impl super::Demo for PlotDemo { impl super::Demo for PlotDemo {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"🗠 Plot" "🗠 Plot"
} }
fn show(&mut self, ctx: &Context, open: &mut bool) { fn show(&mut self, ctx: &Context, open: &mut bool) {
let clone = self.clone();
use super::View as _; use super::View as _;
Window::new(self.name()) Window::new(self.name())
.open(open) .open(open)
.default_size(vec2(400.0, 400.0)) .default_size(vec2(400.0, 400.0))
.vscroll(false) .vscroll(false)
.show(ctx, move |ui| clone.clone().ui(ui)); .show(ctx, |ui| self.ui(ui));
} }
} }
@@ -90,44 +76,43 @@ impl super::View for PlotDemo {
ui.add(crate::egui_github_link_file!()); ui.add(crate::egui_github_link_file!());
}); });
}); });
let mut data = self.data.write().unwrap();
ui.separator(); ui.separator();
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.selectable_value(&mut data.open_panel, Panel::Lines, "Lines"); ui.selectable_value(&mut self.open_panel, Panel::Lines, "Lines");
ui.selectable_value(&mut data.open_panel, Panel::Markers, "Markers"); ui.selectable_value(&mut self.open_panel, Panel::Markers, "Markers");
ui.selectable_value(&mut data.open_panel, Panel::Legend, "Legend"); ui.selectable_value(&mut self.open_panel, Panel::Legend, "Legend");
ui.selectable_value(&mut data.open_panel, Panel::Charts, "Charts"); ui.selectable_value(&mut self.open_panel, Panel::Charts, "Charts");
ui.selectable_value(&mut data.open_panel, Panel::Items, "Items"); ui.selectable_value(&mut self.open_panel, Panel::Items, "Items");
ui.selectable_value(&mut data.open_panel, Panel::Interaction, "Interaction"); ui.selectable_value(&mut self.open_panel, Panel::Interaction, "Interaction");
ui.selectable_value(&mut data.open_panel, Panel::CustomAxes, "Custom Axes"); ui.selectable_value(&mut self.open_panel, Panel::CustomAxes, "Custom Axes");
ui.selectable_value(&mut data.open_panel, Panel::LinkedAxes, "Linked Axes"); ui.selectable_value(&mut self.open_panel, Panel::LinkedAxes, "Linked Axes");
}); });
ui.separator(); ui.separator();
match data.open_panel { match self.open_panel {
Panel::Lines => { Panel::Lines => {
data.line_demo.ui(ui); self.line_demo.ui(ui);
} }
Panel::Markers => { Panel::Markers => {
data.marker_demo.ui(ui); self.marker_demo.ui(ui);
} }
Panel::Legend => { Panel::Legend => {
data.legend_demo.ui(ui); self.legend_demo.ui(ui);
} }
Panel::Charts => { Panel::Charts => {
data.charts_demo.ui(ui); self.charts_demo.ui(ui);
} }
Panel::Items => { Panel::Items => {
data.items_demo.ui(ui); self.items_demo.ui(ui);
} }
Panel::Interaction => { Panel::Interaction => {
data.interaction_demo.ui(ui); self.interaction_demo.ui(ui);
} }
Panel::CustomAxes => { Panel::CustomAxes => {
data.custom_axes_demo.ui(ui); self.custom_axes_demo.ui(ui);
} }
Panel::LinkedAxes => { Panel::LinkedAxes => {
data.linked_axes_demo.ui(ui); self.linked_axes_demo.ui(ui);
} }
} }
} }

View File

@@ -1,5 +1,3 @@
use std::sync::{Arc, RwLock};
use egui::*; use egui::*;
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
@@ -21,64 +19,49 @@ impl Default for ScrollDemo {
#[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))]
#[derive(Default, PartialEq)] #[derive(Default, PartialEq)]
pub struct ScrollingData { pub struct Scrolling {
demo: ScrollDemo, demo: ScrollDemo,
scroll_to: ScrollTo, scroll_to: ScrollTo,
scroll_stick_to: ScrollStickTo, scroll_stick_to: ScrollStickTo,
} }
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
#[derive(Default, Clone)]
pub struct Scrolling {
data: Arc<RwLock<ScrollingData>>,
}
impl PartialEq for Scrolling {
fn eq(&self, other: &Self) -> bool {
*self.data.read().unwrap() == *other.data.read().unwrap()
}
}
impl super::Demo for Scrolling { impl super::Demo for Scrolling {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"↕ Scrolling" "↕ Scrolling"
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.resizable(false) .resizable(false)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
impl super::View for Scrolling { impl super::View for Scrolling {
fn ui(&mut self, ui: &mut Ui) { fn ui(&mut self, ui: &mut Ui) {
let mut data = self.data.write().unwrap();
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.selectable_value(&mut data.demo, ScrollDemo::ScrollTo, "Scroll to"); ui.selectable_value(&mut self.demo, ScrollDemo::ScrollTo, "Scroll to");
ui.selectable_value( ui.selectable_value(
&mut data.demo, &mut self.demo,
ScrollDemo::ManyLines, ScrollDemo::ManyLines,
"Scroll a lot of lines", "Scroll a lot of lines",
); );
ui.selectable_value( ui.selectable_value(
&mut data.demo, &mut self.demo,
ScrollDemo::LargeCanvas, ScrollDemo::LargeCanvas,
"Scroll a large canvas", "Scroll a large canvas",
); );
ui.selectable_value(&mut data.demo, ScrollDemo::StickToEnd, "Stick to end"); ui.selectable_value(&mut self.demo, ScrollDemo::StickToEnd, "Stick to end");
ui.selectable_value(&mut data.demo, ScrollDemo::Bidirectional, "Bidirectional"); ui.selectable_value(&mut self.demo, ScrollDemo::Bidirectional, "Bidirectional");
}); });
ui.separator(); ui.separator();
match data.demo { match self.demo {
ScrollDemo::ScrollTo => { ScrollDemo::ScrollTo => {
data.scroll_to.ui(ui); self.scroll_to.ui(ui);
} }
ScrollDemo::ManyLines => { ScrollDemo::ManyLines => {
huge_content_lines(ui); huge_content_lines(ui);
@@ -87,7 +70,7 @@ impl super::View for Scrolling {
huge_content_painter(ui); huge_content_painter(ui);
} }
ScrollDemo::StickToEnd => { ScrollDemo::StickToEnd => {
data.scroll_stick_to.ui(ui); self.scroll_stick_to.ui(ui);
} }
ScrollDemo::Bidirectional => { ScrollDemo::Bidirectional => {
egui::ScrollArea::both().show(ui, |ui| { egui::ScrollArea::both().show(ui, |ui| {

View File

@@ -1,14 +1,11 @@
use egui::*; use egui::*;
use std::{ use std::f64::INFINITY;
f64::INFINITY,
sync::{Arc, RwLock},
};
/// Showcase sliders /// Showcase sliders
#[derive(PartialEq)] #[derive(PartialEq)]
#[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 SlidersData { pub struct Sliders {
pub min: f64, pub min: f64,
pub max: f64, pub max: f64,
pub logarithmic: bool, pub logarithmic: bool,
@@ -22,20 +19,7 @@ pub struct SlidersData {
pub trailing_fill: bool, pub trailing_fill: bool,
} }
#[derive(Clone, Default)] impl Default for Sliders {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Sliders {
pub data: Arc<RwLock<SlidersData>>,
}
impl PartialEq for Sliders {
fn eq(&self, other: &Self) -> bool {
*self.data.read().unwrap() == *other.data.read().unwrap()
}
}
impl Default for SlidersData {
fn default() -> Self { fn default() -> Self {
Self { Self {
min: 0.0, min: 0.0,
@@ -59,13 +43,12 @@ impl super::Demo for Sliders {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.resizable(false) .resizable(false)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -73,7 +56,7 @@ impl super::Demo for Sliders {
impl super::View for Sliders { impl super::View for Sliders {
fn ui(&mut self, ui: &mut Ui) { fn ui(&mut self, ui: &mut Ui) {
{ {
let SlidersData { let Sliders {
min, min,
max, max,
logarithmic, logarithmic,
@@ -85,7 +68,7 @@ impl super::View for Sliders {
vertical, vertical,
value, value,
trailing_fill, trailing_fill,
} = &mut *self.data.write().unwrap(); } = self;
ui.label("You can click a slider value to edit it with the keyboard."); ui.label("You can click a slider value to edit it with the keyboard.");
@@ -138,7 +121,7 @@ impl super::View for Sliders {
); );
if ui.button("Assign PI").clicked() { if ui.button("Assign PI").clicked() {
self.data.write().unwrap().value = std::f64::consts::PI; self.value = std::f64::consts::PI;
} }
} }

View File

@@ -1,5 +1,3 @@
use std::sync::{Arc, RwLock};
#[derive(PartialEq)] #[derive(PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
enum DemoType { enum DemoType {
@@ -8,8 +6,9 @@ enum DemoType {
ManyHeterogenous, ManyHeterogenous,
} }
/// Shows off a table with dynamic layout
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TableDemoData { pub struct TableDemo {
demo: DemoType, demo: DemoType,
striped: bool, striped: bool,
resizable: bool, resizable: bool,
@@ -18,14 +17,7 @@ pub struct TableDemoData {
scroll_to_row: Option<usize>, scroll_to_row: Option<usize>,
} }
/// Shows off a table with dynamic layout impl Default for TableDemo {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Default)]
pub struct TableDemo {
data: Arc<RwLock<TableDemoData>>,
}
impl Default for TableDemoData {
fn default() -> Self { fn default() -> Self {
Self { Self {
demo: DemoType::Manual, demo: DemoType::Manual,
@@ -44,14 +36,13 @@ impl super::Demo for TableDemo {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.resizable(true) .resizable(true)
.default_width(400.0) .default_width(400.0)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -61,48 +52,47 @@ const NUM_MANUAL_ROWS: usize = 20;
impl super::View for TableDemo { impl super::View for TableDemo {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
{ {
let mut data = self.data.write().unwrap();
ui.vertical(|ui| { ui.vertical(|ui| {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.checkbox(&mut data.striped, "Striped"); ui.checkbox(&mut self.striped, "Striped");
ui.checkbox(&mut data.resizable, "Resizable columns"); ui.checkbox(&mut self.resizable, "Resizable columns");
}); });
ui.label("Table type:"); ui.label("Table type:");
ui.radio_value(&mut data.demo, DemoType::Manual, "Few, manual rows"); ui.radio_value(&mut self.demo, DemoType::Manual, "Few, manual rows");
ui.radio_value( ui.radio_value(
&mut data.demo, &mut self.demo,
DemoType::ManyHomogeneous, DemoType::ManyHomogeneous,
"Thousands of rows of same height", "Thousands of rows of same height",
); );
ui.radio_value( ui.radio_value(
&mut data.demo, &mut self.demo,
DemoType::ManyHeterogenous, DemoType::ManyHeterogenous,
"Thousands of rows of differing heights", "Thousands of rows of differing heights",
); );
if data.demo != DemoType::Manual { if self.demo != DemoType::Manual {
ui.add( ui.add(
egui::Slider::new(&mut data.num_rows, 0..=100_000) egui::Slider::new(&mut self.num_rows, 0..=100_000)
.logarithmic(true) .logarithmic(true)
.text("Num rows"), .text("Num rows"),
); );
} }
{ {
let max_rows = if data.demo == DemoType::Manual { let max_rows = if self.demo == DemoType::Manual {
NUM_MANUAL_ROWS NUM_MANUAL_ROWS
} else { } else {
data.num_rows self.num_rows
}; };
let slider_response = ui.add( let slider_response = ui.add(
egui::Slider::new(&mut data.scroll_to_row_slider, 0..=max_rows) egui::Slider::new(&mut self.scroll_to_row_slider, 0..=max_rows)
.logarithmic(true) .logarithmic(true)
.text("Row to scroll to"), .text("Row to scroll to"),
); );
if slider_response.changed() { if slider_response.changed() {
data.scroll_to_row = Some(data.scroll_to_row_slider); self.scroll_to_row = Some(self.scroll_to_row_slider);
} }
} }
}); });
@@ -135,11 +125,10 @@ impl TableDemo {
use egui_extras::{Column, TableBuilder}; use egui_extras::{Column, TableBuilder};
let text_height = egui::TextStyle::Body.resolve(ui.style()).size; let text_height = egui::TextStyle::Body.resolve(ui.style()).size;
let mut data = self.data.write().unwrap();
let mut table = TableBuilder::new(ui) let mut table = TableBuilder::new(ui)
.striped(data.striped) .striped(self.striped)
.resizable(data.resizable) .resizable(self.resizable)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center)) .cell_layout(egui::Layout::left_to_right(egui::Align::Center))
.column(Column::auto()) .column(Column::auto())
.column(Column::initial(100.0).range(40.0..=300.0)) .column(Column::initial(100.0).range(40.0..=300.0))
@@ -147,7 +136,7 @@ impl TableDemo {
.column(Column::remainder()) .column(Column::remainder())
.min_scrolled_height(0.0); .min_scrolled_height(0.0);
if let Some(row_nr) = data.scroll_to_row.take() { if let Some(row_nr) = self.scroll_to_row.take() {
table = table.scroll_to_row(row_nr, None); table = table.scroll_to_row(row_nr, None);
} }
@@ -166,7 +155,7 @@ impl TableDemo {
ui.strong("Content"); ui.strong("Content");
}); });
}) })
.body(|mut body| match data.demo { .body(|mut body| match self.demo {
DemoType::Manual => { DemoType::Manual => {
for row_index in 0..NUM_MANUAL_ROWS { for row_index in 0..NUM_MANUAL_ROWS {
let is_thick = thick_row(row_index); let is_thick = thick_row(row_index);
@@ -193,7 +182,7 @@ impl TableDemo {
} }
} }
DemoType::ManyHomogeneous => { DemoType::ManyHomogeneous => {
body.rows(text_height, data.num_rows, |row_index, mut row| { body.rows(text_height, self.num_rows, |row_index, mut row| {
row.col(|ui| { row.col(|ui| {
ui.label(row_index.to_string()); ui.label(row_index.to_string());
}); });
@@ -219,7 +208,7 @@ impl TableDemo {
} }
} }
body.heterogeneous_rows( body.heterogeneous_rows(
(0..data.num_rows).map(row_thickness), (0..self.num_rows).map(row_thickness),
|row_index, mut row| { |row_index, mut row| {
row.col(|ui| { row.col(|ui| {
ui.label(row_index.to_string()); ui.label(row_index.to_string());

View File

@@ -97,13 +97,14 @@ enum WidgetType {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct ManualLayoutTestData { pub struct ManualLayoutTest {
widget_offset: egui::Vec2, widget_offset: egui::Vec2,
widget_size: egui::Vec2, widget_size: egui::Vec2,
widget_type: WidgetType, widget_type: WidgetType,
text_edit_contents: String, text_edit_contents: String,
} }
impl Default for ManualLayoutTestData {
impl Default for ManualLayoutTest {
fn default() -> Self { fn default() -> Self {
Self { Self {
widget_offset: egui::Vec2::splat(150.0), widget_offset: egui::Vec2::splat(150.0),
@@ -114,30 +115,18 @@ impl Default for ManualLayoutTestData {
} }
} }
#[derive(Clone, Debug, Default)]
pub struct ManualLayoutTest {
data: Arc<RwLock<ManualLayoutTestData>>,
}
impl PartialEq for ManualLayoutTest {
fn eq(&self, other: &Self) -> bool {
*self.data.read().unwrap() == *other.data.read().unwrap()
}
}
impl super::Demo for ManualLayoutTest { impl super::Demo for ManualLayoutTest {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
"Manual Layout Test" "Manual Layout Test"
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.resizable(false) .resizable(false)
.open(open) .open(open)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -146,12 +135,12 @@ impl super::View for ManualLayoutTest {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
egui::reset_button(ui, self); egui::reset_button(ui, self);
let ManualLayoutTestData { let ManualLayoutTest {
widget_offset, widget_offset,
widget_size, widget_size,
widget_type, widget_type,
text_edit_contents, text_edit_contents,
} = &mut *self.data.write().unwrap(); } = self;
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Test widget:"); ui.label("Test widget:");
ui.radio_value(widget_type, WidgetType::Button, "Button"); ui.radio_value(widget_type, WidgetType::Button, "Button");
@@ -192,7 +181,7 @@ impl super::View for ManualLayoutTest {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct TableTestData { pub struct TableTest {
num_cols: usize, num_cols: usize,
num_rows: usize, num_rows: usize,
min_col_width: f32, min_col_width: f32,
@@ -200,18 +189,7 @@ pub struct TableTestData {
text_length: usize, text_length: usize,
} }
#[derive(Default, Clone)] impl Default for TableTest {
pub struct TableTest {
data: Arc<RwLock<TableTestData>>,
}
impl PartialEq for TableTest {
fn eq(&self, other: &Self) -> bool {
*self.data.read().unwrap() == *other.data.read().unwrap()
}
}
impl Default for TableTestData {
fn default() -> Self { fn default() -> Self {
Self { Self {
num_cols: 4, num_cols: 4,
@@ -229,12 +207,11 @@ impl super::Demo for TableTest {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -242,17 +219,16 @@ impl super::Demo for TableTest {
impl super::View for TableTest { impl super::View for TableTest {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
{ {
let mut data = self.data.write().unwrap();
ui.add( ui.add(
egui::Slider::new(&mut data.min_col_width, 0.0..=400.0) egui::Slider::new(&mut self.min_col_width, 0.0..=400.0)
.text("Minimum column width"), .text("Minimum column width"),
); );
ui.add( ui.add(
egui::Slider::new(&mut data.max_col_width, 0.0..=400.0) egui::Slider::new(&mut self.max_col_width, 0.0..=400.0)
.text("Maximum column width"), .text("Maximum column width"),
); );
ui.add(egui::Slider::new(&mut data.num_cols, 0..=5).text("Columns")); ui.add(egui::Slider::new(&mut self.num_cols, 0..=5).text("Columns"));
ui.add(egui::Slider::new(&mut data.num_rows, 0..=20).text("Rows")); ui.add(egui::Slider::new(&mut self.num_rows, 0..=20).text("Rows"));
ui.separator(); ui.separator();
@@ -263,11 +239,11 @@ impl super::View for TableTest {
egui::Grid::new("my_grid") egui::Grid::new("my_grid")
.striped(true) .striped(true)
.min_col_width(data.min_col_width) .min_col_width(self.min_col_width)
.max_col_width(data.max_col_width) .max_col_width(self.max_col_width)
.show(ui, |ui| { .show(ui, |ui| {
for row in 0..data.num_rows { for row in 0..self.num_rows {
for col in 0..data.num_cols { for col in 0..self.num_cols {
if col == 0 { if col == 0 {
ui.label(format!("row {}", row)); ui.label(format!("row {}", row));
} else { } else {
@@ -286,7 +262,7 @@ impl super::View for TableTest {
}); });
ui.separator(); ui.separator();
ui.add(egui::Slider::new(&mut data.text_length, 1..=40).text("Text length")); ui.add(egui::Slider::new(&mut self.text_length, 1..=40).text("Text length"));
egui::Grid::new("parent grid").striped(true).show(ui, |ui| { egui::Grid::new("parent grid").striped(true).show(ui, |ui| {
ui.vertical(|ui| { ui.vertical(|ui| {
ui.label("Vertical nest1"); ui.label("Vertical nest1");
@@ -321,7 +297,7 @@ impl super::View for TableTest {
ui.end_row(); ui.end_row();
let mut dyn_text = String::from("O"); let mut dyn_text = String::from("O");
dyn_text.extend(std::iter::repeat('h').take(data.text_length)); dyn_text.extend(std::iter::repeat('h').take(self.text_length));
ui.label(dyn_text); ui.label(dyn_text);
ui.label("Fifth row, second column"); ui.label("Fifth row, second column");
ui.end_row(); ui.end_row();
@@ -338,9 +314,9 @@ impl super::View for TableTest {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Default, Clone)] #[derive(Default)]
pub struct InputTest { pub struct InputTest {
info: Arc<RwLock<String>>, info: String,
} }
impl super::Demo for InputTest { impl super::Demo for InputTest {
@@ -349,13 +325,12 @@ impl super::Demo for InputTest {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.resizable(false) .resizable(false)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -401,10 +376,10 @@ impl super::View for InputTest {
} }
} }
if !new_info.is_empty() { if !new_info.is_empty() {
*self.info.write().unwrap() = new_info; self.info = new_info;
} }
ui.label(&*self.info.write().unwrap()); ui.label(&self.info);
} }
} }

View File

@@ -1,23 +1,14 @@
use std::sync::{Arc, RwLock};
/// Showcase [`TextEdit`]. /// Showcase [`TextEdit`].
#[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))]
#[derive(Clone)]
pub struct TextEdit { pub struct TextEdit {
pub text: Arc<RwLock<String>>, pub text: String,
}
impl PartialEq for TextEdit {
fn eq(&self, other: &Self) -> bool {
*self.text.read().unwrap() == *other.text.read().unwrap()
}
} }
impl Default for TextEdit { impl Default for TextEdit {
fn default() -> Self { fn default() -> Self {
Self { Self {
text: Arc::new(RwLock::new("Edit this text".to_owned())), text: "Edit this text".to_owned(),
} }
} }
} }
@@ -28,13 +19,12 @@ impl super::Demo for TextEdit {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.resizable(false) .resizable(false)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
@@ -42,7 +32,6 @@ impl super::Demo for TextEdit {
impl super::View for TextEdit { impl super::View for TextEdit {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
let Self { text } = self; let Self { text } = self;
let text = &mut *text.write().unwrap();
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 0.0; ui.spacing_mut().item_spacing.x = 0.0;

View File

@@ -1,5 +1,3 @@
use std::sync::{Arc, RwLock};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
enum Enum { enum Enum {
@@ -8,8 +6,9 @@ enum Enum {
Third, Third,
} }
/// Shows off one example of each major type of widget.
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WidgetGalleryData { pub struct WidgetGallery {
enabled: bool, enabled: bool,
visible: bool, visible: bool,
boolean: bool, boolean: bool,
@@ -27,14 +26,7 @@ pub struct WidgetGalleryData {
texture: Option<egui::TextureHandle>, texture: Option<egui::TextureHandle>,
} }
/// Shows off one example of each major type of widget. impl Default for WidgetGallery {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Default)]
pub struct WidgetGallery {
data: Arc<RwLock<WidgetGalleryData>>,
}
impl Default for WidgetGalleryData {
fn default() -> Self { fn default() -> Self {
Self { Self {
enabled: true, enabled: true,
@@ -58,24 +50,21 @@ impl super::Demo for WidgetGallery {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let clone = self.clone();
egui::Window::new(self.name()) egui::Window::new(self.name())
.open(open) .open(open)
.resizable(true) .resizable(true)
.default_width(280.0) .default_width(280.0)
.show(ctx, move |ui| { .show(ctx, move |ui| {
use super::View as _; use super::View as _;
clone.clone().ui(ui); self.ui(ui);
}); });
} }
} }
impl super::View for WidgetGallery { impl super::View for WidgetGallery {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
let enabled = self.data.read().unwrap().enabled; ui.add_enabled_ui(self.enabled, |ui| {
let visible = self.data.read().unwrap().visible; ui.set_visible(self.visible);
ui.add_enabled_ui(enabled, |ui| {
ui.set_visible(visible);
egui::Grid::new("my_grid") egui::Grid::new("my_grid")
.num_columns(2) .num_columns(2)
@@ -85,14 +74,13 @@ impl super::View for WidgetGallery {
self.gallery_grid_contents(ui); self.gallery_grid_contents(ui);
}); });
}); });
let data = &mut *self.data.write().unwrap();
ui.separator(); ui.separator();
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.checkbox(&mut data.visible, "Visible") ui.checkbox(&mut self.visible, "Visible")
.on_hover_text("Uncheck to hide all the widgets."); .on_hover_text("Uncheck to hide all the widgets.");
if data.visible { if self.visible {
ui.checkbox(&mut data.enabled, "Interactive") ui.checkbox(&mut self.enabled, "Interactive")
.on_hover_text("Uncheck to inspect how the widgets look when disabled."); .on_hover_text("Uncheck to inspect how the widgets look when disabled.");
} }
}); });
@@ -111,7 +99,7 @@ impl super::View for WidgetGallery {
impl WidgetGallery { impl WidgetGallery {
fn gallery_grid_contents(&mut self, ui: &mut egui::Ui) { fn gallery_grid_contents(&mut self, ui: &mut egui::Ui) {
let WidgetGalleryData { let WidgetGallery {
enabled: _, enabled: _,
visible: _, visible: _,
boolean, boolean,
@@ -123,7 +111,7 @@ impl WidgetGallery {
#[cfg(feature = "chrono")] #[cfg(feature = "chrono")]
date, date,
texture, texture,
} = &mut *self.data.write().unwrap(); } = self;
let texture: &egui::TextureHandle = texture.get_or_insert_with(|| { let texture: &egui::TextureHandle = texture.get_or_insert_with(|| {
ui.ctx() ui.ctx()

View File

@@ -1,8 +1,6 @@
use std::sync::{Arc, RwLock};
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WindowOptionsData { pub struct WindowOptions {
title: String, title: String,
title_bar: bool, title_bar: bool,
closable: bool, closable: bool,
@@ -15,19 +13,8 @@ pub struct WindowOptionsData {
anchor: egui::Align2, anchor: egui::Align2,
anchor_offset: egui::Vec2, anchor_offset: egui::Vec2,
} }
#[derive(Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct WindowOptions {
data: Arc<RwLock<WindowOptionsData>>,
}
impl PartialEq for WindowOptions { impl Default for WindowOptions {
fn eq(&self, other: &Self) -> bool {
*self.data.read().unwrap() == *other.data.read().unwrap()
}
}
impl Default for WindowOptionsData {
fn default() -> Self { fn default() -> Self {
Self { Self {
title: "🗖 Window Options".to_owned(), title: "🗖 Window Options".to_owned(),
@@ -50,7 +37,7 @@ impl super::Demo for WindowOptions {
} }
fn show(&mut self, ctx: &egui::Context, open: &mut bool) { fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
let WindowOptionsData { let WindowOptions {
title, title,
title_bar, title_bar,
closable, closable,
@@ -61,7 +48,7 @@ impl super::Demo for WindowOptions {
anchored, anchored,
anchor, anchor,
anchor_offset, anchor_offset,
} = self.data.read().unwrap().clone(); } = self.clone();
let enabled = ctx.input(|i| i.time) - disabled_time > 2.0; let enabled = ctx.input(|i| i.time) - disabled_time > 2.0;
if !enabled { if !enabled {
@@ -82,76 +69,70 @@ impl super::Demo for WindowOptions {
if anchored { if anchored {
window = window.anchor(anchor, anchor_offset); window = window.anchor(anchor, anchor_offset);
} }
let clone = self.clone(); window.show(ctx, move |ui| self.ui(ui));
window.show(ctx, move |ui| {
let mut clone = clone.clone();
clone.ui(ui)
});
} }
} }
impl super::View for WindowOptions { impl super::View for WindowOptions {
fn ui(&mut self, ui: &mut egui::Ui) { fn ui(&mut self, ui: &mut egui::Ui) {
{ let WindowOptions {
let WindowOptionsData { title,
title, title_bar,
title_bar, closable,
closable, collapsible,
collapsible, resizable,
resizable, scroll2,
scroll2, disabled_time: _,
disabled_time: _, anchored,
anchored, anchor,
anchor, anchor_offset,
anchor_offset, } = self;
} = &mut *self.data.write().unwrap(); ui.horizontal(|ui| {
ui.horizontal(|ui| { ui.label("title:");
ui.label("title:"); ui.text_edit_singleline(title);
ui.text_edit_singleline(title); });
});
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.group(|ui| { ui.group(|ui| {
ui.vertical(|ui| { ui.vertical(|ui| {
ui.checkbox(title_bar, "title_bar"); ui.checkbox(title_bar, "title_bar");
ui.checkbox(closable, "closable"); ui.checkbox(closable, "closable");
ui.checkbox(collapsible, "collapsible"); ui.checkbox(collapsible, "collapsible");
ui.checkbox(resizable, "resizable"); ui.checkbox(resizable, "resizable");
ui.checkbox(&mut scroll2[0], "hscroll"); ui.checkbox(&mut scroll2[0], "hscroll");
ui.checkbox(&mut scroll2[1], "vscroll"); ui.checkbox(&mut scroll2[1], "vscroll");
});
}); });
ui.group(|ui| { });
ui.vertical(|ui| { ui.group(|ui| {
ui.checkbox(anchored, "anchored"); ui.vertical(|ui| {
ui.set_enabled(*anchored); ui.checkbox(anchored, "anchored");
ui.horizontal(|ui| { ui.set_enabled(*anchored);
ui.label("x:"); ui.horizontal(|ui| {
ui.selectable_value(&mut anchor[0], egui::Align::LEFT, "Left"); ui.label("x:");
ui.selectable_value(&mut anchor[0], egui::Align::Center, "Center"); ui.selectable_value(&mut anchor[0], egui::Align::LEFT, "Left");
ui.selectable_value(&mut anchor[0], egui::Align::RIGHT, "Right"); ui.selectable_value(&mut anchor[0], egui::Align::Center, "Center");
}); ui.selectable_value(&mut anchor[0], egui::Align::RIGHT, "Right");
ui.horizontal(|ui| { });
ui.label("y:"); ui.horizontal(|ui| {
ui.selectable_value(&mut anchor[1], egui::Align::TOP, "Top"); ui.label("y:");
ui.selectable_value(&mut anchor[1], egui::Align::Center, "Center"); ui.selectable_value(&mut anchor[1], egui::Align::TOP, "Top");
ui.selectable_value(&mut anchor[1], egui::Align::BOTTOM, "Bottom"); ui.selectable_value(&mut anchor[1], egui::Align::Center, "Center");
}); ui.selectable_value(&mut anchor[1], egui::Align::BOTTOM, "Bottom");
ui.horizontal(|ui| { });
ui.label("Offset:"); ui.horizontal(|ui| {
ui.add(egui::DragValue::new(&mut anchor_offset.x)); ui.label("Offset:");
ui.add(egui::DragValue::new(&mut anchor_offset.y)); ui.add(egui::DragValue::new(&mut anchor_offset.x));
}); ui.add(egui::DragValue::new(&mut anchor_offset.y));
}); });
}); });
}); });
} });
ui.separator(); ui.separator();
ui.horizontal(|ui| { ui.horizontal(|ui| {
if ui.button("Disable for 2 seconds").clicked() { if ui.button("Disable for 2 seconds").clicked() {
self.data.write().unwrap().disabled_time = ui.input(|i| i.time); self.disabled_time = ui.input(|i| i.time);
} }
egui::reset_button(ui, self); egui::reset_button(ui, self);
ui.add(crate::egui_github_link_file!()); ui.add(crate::egui_github_link_file!());