mirror of
https://github.com/emilk/egui.git
synced 2026-06-27 23:13:13 -04:00
Reverted the demos back
This commit is contained in:
@@ -14,7 +14,7 @@ impl super::Demo for About {
|
||||
.open(open)
|
||||
.show(ctx, |ui| {
|
||||
use super::View as _;
|
||||
Self::default().ui(ui);
|
||||
self.ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct CodeEditorData {
|
||||
pub struct CodeEditor {
|
||||
language: String,
|
||||
code: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct CodeEditor {
|
||||
data: Arc<RwLock<CodeEditorData>>,
|
||||
}
|
||||
|
||||
impl Default for CodeEditorData {
|
||||
impl Default for CodeEditor {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
language: "rs".into(),
|
||||
@@ -35,18 +26,17 @@ impl super::Demo for CodeEditor {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
use super::View as _;
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.default_height(500.0)
|
||||
.show(ctx, move |ui| clone.clone().ui(ui));
|
||||
.show(ctx, move |ui| self.ui(ui));
|
||||
}
|
||||
}
|
||||
|
||||
impl super::View for CodeEditor {
|
||||
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.set_height(0.0);
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CodeExampleData {
|
||||
pub struct CodeExample {
|
||||
name: String,
|
||||
age: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct CodeExample {
|
||||
data: Arc<RwLock<CodeExampleData>>,
|
||||
}
|
||||
|
||||
impl Default for CodeExampleData {
|
||||
impl Default for CodeExample {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: "Arthur".to_owned(),
|
||||
@@ -36,29 +29,28 @@ impl CodeExample {
|
||||
});"#,
|
||||
);
|
||||
// Putting things on the same line using ui.horizontal:
|
||||
let mut data = self.data.write().unwrap();
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Your name: ");
|
||||
ui.text_edit_singleline(&mut data.name);
|
||||
ui.text_edit_singleline(&mut self.name);
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
show_code(
|
||||
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();
|
||||
|
||||
show_code(
|
||||
ui,
|
||||
r#"
|
||||
if ui.button("Click each year").clicked() {
|
||||
data.age += 1;
|
||||
self.age += 1;
|
||||
}"#,
|
||||
);
|
||||
if ui.button("Click each year").clicked() {
|
||||
data.age += 1;
|
||||
self.age += 1;
|
||||
}
|
||||
ui.end_row();
|
||||
|
||||
@@ -66,7 +58,7 @@ impl CodeExample {
|
||||
ui,
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -77,14 +69,13 @@ impl super::Demo for CodeExample {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
use super::View;
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.default_size([800.0, 400.0])
|
||||
.vscroll(false)
|
||||
.hscroll(true)
|
||||
.show(ctx, move |ui| clone.clone().ui(ui));
|
||||
.show(ctx, move |ui| self.ui(ui));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
enum Plot {
|
||||
@@ -16,9 +14,10 @@ fn gaussian(x: f64) -> f64 {
|
||||
fn sigmoid(x: f64) -> f64 {
|
||||
-1.0 + 2.0 / (1.0 + f64::exp(-x))
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct ContextMenusData {
|
||||
pub struct ContextMenus {
|
||||
plot: Plot,
|
||||
show_axes: [bool; 2],
|
||||
allow_drag: bool,
|
||||
@@ -30,19 +29,7 @@ pub struct ContextMenusData {
|
||||
height: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[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 {
|
||||
impl Default for ContextMenus {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
plot: Plot::Sin,
|
||||
@@ -64,13 +51,12 @@ impl super::Demo for ContextMenus {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
use super::View;
|
||||
egui::Window::new(self.name())
|
||||
.vscroll(false)
|
||||
.resizable(false)
|
||||
.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.horizontal(|ui| {
|
||||
self.example_plot(ui).context_menu(|ui| {
|
||||
let data = &mut *self.data.write().unwrap();
|
||||
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
|
||||
.radio_value(&mut data.plot, Plot::Bell, "Gaussian")
|
||||
.radio_value(&mut self.plot, Plot::Bell, "Gaussian")
|
||||
.clicked()
|
||||
|| ui
|
||||
.radio_value(&mut data.plot, Plot::Sigmoid, "Sigmoid")
|
||||
.radio_value(&mut self.plot, Plot::Sigmoid, "Sigmoid")
|
||||
.clicked()
|
||||
{
|
||||
ui.close_menu();
|
||||
@@ -102,22 +87,22 @@ impl super::View for ContextMenus {
|
||||
});
|
||||
egui::Grid::new("button_grid").show(ui, |ui| {
|
||||
ui.add(
|
||||
egui::DragValue::new(&mut data.width)
|
||||
egui::DragValue::new(&mut self.width)
|
||||
.speed(1.0)
|
||||
.prefix("Width:"),
|
||||
);
|
||||
ui.add(
|
||||
egui::DragValue::new(&mut data.height)
|
||||
egui::DragValue::new(&mut self.height)
|
||||
.speed(1.0)
|
||||
.prefix("Height:"),
|
||||
);
|
||||
ui.end_row();
|
||||
ui.checkbox(&mut data.show_axes[0], "x-Axis");
|
||||
ui.checkbox(&mut data.show_axes[1], "y-Axis");
|
||||
ui.checkbox(&mut self.show_axes[0], "x-Axis");
|
||||
ui.checkbox(&mut self.show_axes[1], "y-Axis");
|
||||
ui.end_row();
|
||||
if ui.checkbox(&mut data.allow_drag, "Drag").changed()
|
||||
|| ui.checkbox(&mut data.allow_zoom, "Zoom").changed()
|
||||
|| ui.checkbox(&mut data.allow_scroll, "Scroll").changed()
|
||||
if ui.checkbox(&mut self.allow_drag, "Drag").changed()
|
||||
|| ui.checkbox(&mut self.allow_zoom, "Zoom").changed()
|
||||
|| ui.checkbox(&mut self.allow_scroll, "Scroll").changed()
|
||||
{
|
||||
ui.close_menu();
|
||||
}
|
||||
@@ -132,7 +117,6 @@ impl super::View for ContextMenus {
|
||||
|
||||
impl ContextMenus {
|
||||
fn example_plot(&self, ui: &mut egui::Ui) -> egui::Response {
|
||||
let data = &mut *self.data.write().unwrap();
|
||||
use egui::plot::{Line, PlotPoints};
|
||||
let n = 128;
|
||||
let line = Line::new(
|
||||
@@ -140,7 +124,7 @@ impl ContextMenus {
|
||||
.map(|i| {
|
||||
use std::f64::consts::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::Bell => [x, 10.0 * gaussian(x)],
|
||||
Plot::Sigmoid => [x, sigmoid(x)],
|
||||
@@ -149,14 +133,14 @@ impl ContextMenus {
|
||||
.collect::<PlotPoints>(),
|
||||
);
|
||||
egui::plot::Plot::new("example_plot")
|
||||
.show_axes(data.show_axes)
|
||||
.allow_drag(data.allow_drag)
|
||||
.allow_zoom(data.allow_zoom)
|
||||
.allow_scroll(data.allow_scroll)
|
||||
.center_x_axis(data.center_x_axis)
|
||||
.center_x_axis(data.center_y_axis)
|
||||
.width(data.width)
|
||||
.height(data.height)
|
||||
.show_axes(self.show_axes)
|
||||
.allow_drag(self.allow_drag)
|
||||
.allow_zoom(self.allow_zoom)
|
||||
.allow_scroll(self.allow_scroll)
|
||||
.center_x_axis(self.center_x_axis)
|
||||
.center_x_axis(self.center_y_axis)
|
||||
.width(self.width)
|
||||
.height(self.height)
|
||||
.data_aspect(1.0)
|
||||
.show(ui, |plot_ui| plot_ui.line(line))
|
||||
.response
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use egui::*;
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct DragAndDropDemo {
|
||||
/// columns with items
|
||||
columns: Arc<RwLock<Vec<Vec<String>>>>,
|
||||
}
|
||||
|
||||
impl PartialEq for DragAndDropDemo {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
*self.columns.read().unwrap() == *other.columns.read().unwrap()
|
||||
}
|
||||
columns: Vec<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Default for DragAndDropDemo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
columns: Arc::new(RwLock::new(
|
||||
vec![
|
||||
vec!["Item A", "Item B", "Item C"],
|
||||
vec!["Item D", "Item E"],
|
||||
vec!["Item F", "Item G", "Item H"],
|
||||
]
|
||||
.into_iter()
|
||||
.map(|v| v.into_iter().map(ToString::to_string).collect())
|
||||
.collect(),
|
||||
)),
|
||||
columns: vec![
|
||||
vec!["Item A", "Item B", "Item C"],
|
||||
vec!["Item D", "Item E"],
|
||||
vec!["Item F", "Item G", "Item H"],
|
||||
]
|
||||
.into_iter()
|
||||
.map(|v| v.into_iter().map(ToString::to_string).collect())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,14 +102,13 @@ impl super::Demo for DragAndDropDemo {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
use super::View as _;
|
||||
Window::new(self.name())
|
||||
.open(open)
|
||||
.default_size(vec2(256.0, 256.0))
|
||||
.vscroll(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 mut source_col_row = None;
|
||||
let mut drop_col = None;
|
||||
let mut columns = self.columns.write().unwrap();
|
||||
let columns = &mut self.columns;
|
||||
ui.columns(columns.len(), |uis| {
|
||||
for (col_idx, column) in columns.clone().into_iter().enumerate() {
|
||||
let ui = &mut uis[col_idx];
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
pub struct FontBookData {
|
||||
use std::collections::BTreeMap;
|
||||
pub struct FontBook {
|
||||
filter: String,
|
||||
font_id: egui::FontId,
|
||||
named_chars: BTreeMap<egui::FontFamily, BTreeMap<char, String>>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct FontBook {
|
||||
data: Arc<RwLock<FontBookData>>,
|
||||
}
|
||||
|
||||
impl Default for FontBookData {
|
||||
impl Default for FontBook {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
filter: Default::default(),
|
||||
@@ -29,12 +21,11 @@ impl super::Demo for FontBook {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.show(ctx, move |ui| {
|
||||
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!());
|
||||
});
|
||||
|
||||
let data = &mut *self.data.write().unwrap();
|
||||
|
||||
ui.label(format!(
|
||||
"The selected font supports {} characters.",
|
||||
data.named_chars
|
||||
.get(&data.font_id.family)
|
||||
self.named_chars
|
||||
.get(&self.font_id.family)
|
||||
.map(|map| map.len())
|
||||
.unwrap_or_default()
|
||||
));
|
||||
@@ -67,22 +56,22 @@ impl super::View for FontBook {
|
||||
|
||||
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.label("Filter:");
|
||||
ui.add(egui::TextEdit::singleline(&mut data.filter).desired_width(120.0));
|
||||
data.filter = data.filter.to_lowercase();
|
||||
ui.add(egui::TextEdit::singleline(&mut self.filter).desired_width(120.0));
|
||||
self.filter = self.filter.to_lowercase();
|
||||
if ui.button("x").clicked() {
|
||||
data.filter.clear();
|
||||
self.filter.clear();
|
||||
}
|
||||
});
|
||||
|
||||
let filter = &data.filter;
|
||||
let named_chars = data
|
||||
let filter = &self.filter;
|
||||
let named_chars = self
|
||||
.named_chars
|
||||
.entry(data.font_id.family.clone())
|
||||
.or_insert_with(|| available_characters(ui, data.font_id.family.clone()));
|
||||
.entry(self.font_id.family.clone())
|
||||
.or_insert_with(|| available_characters(ui, self.font_id.family.clone()));
|
||||
|
||||
ui.separator();
|
||||
|
||||
@@ -93,13 +82,13 @@ impl super::View for FontBook {
|
||||
for (&chr, name) in named_chars {
|
||||
if filter.is_empty() || name.contains(filter) || *filter == chr.to_string() {
|
||||
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);
|
||||
|
||||
let tooltip_ui = |ui: &mut egui::Ui| {
|
||||
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));
|
||||
};
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use egui::*;
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct LayoutTestData {
|
||||
pub struct LayoutTest {
|
||||
// Identical to contents of `egui::Layout`
|
||||
layout: LayoutSettings,
|
||||
|
||||
@@ -13,14 +11,7 @@ pub struct LayoutTestData {
|
||||
wrap_row_height: f32,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct LayoutTest {
|
||||
data: Arc<RwLock<LayoutTestData>>,
|
||||
}
|
||||
|
||||
impl Default for LayoutTestData {
|
||||
impl Default for LayoutTest {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
layout: LayoutSettings::top_down(),
|
||||
@@ -88,13 +79,12 @@ impl super::Demo for LayoutTest {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.resizable(false)
|
||||
.show(ctx, move |ui| {
|
||||
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) {
|
||||
ui.label("Tests and demonstrates the limits of the egui layouts");
|
||||
self.content_ui(ui);
|
||||
let data = self.data.write().unwrap();
|
||||
Resize::default()
|
||||
.default_size([150.0, 200.0])
|
||||
.show(ui, |ui| {
|
||||
if data.layout.main_wrap {
|
||||
if data.layout.main_dir.is_horizontal() {
|
||||
if self.layout.main_wrap {
|
||||
if self.layout.main_dir.is_horizontal() {
|
||||
ui.allocate_ui(
|
||||
vec2(ui.available_size_before_wrap().x, data.wrap_row_height),
|
||||
|ui| ui.with_layout(data.layout.layout(), demo_ui),
|
||||
vec2(ui.available_size_before_wrap().x, self.wrap_row_height),
|
||||
|ui| ui.with_layout(self.layout.layout(), demo_ui),
|
||||
);
|
||||
} else {
|
||||
ui.allocate_ui(
|
||||
vec2(data.wrap_column_width, ui.available_size_before_wrap().y),
|
||||
|ui| ui.with_layout(data.layout.layout(), demo_ui),
|
||||
vec2(self.wrap_column_width, ui.available_size_before_wrap().y),
|
||||
|ui| ui.with_layout(self.layout.layout(), demo_ui),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ui.with_layout(data.layout.layout(), demo_ui);
|
||||
ui.with_layout(self.layout.layout(), demo_ui);
|
||||
}
|
||||
});
|
||||
ui.label("Resize to see effect");
|
||||
@@ -129,16 +118,15 @@ impl super::View for LayoutTest {
|
||||
|
||||
impl LayoutTest {
|
||||
pub fn content_ui(&mut self, ui: &mut Ui) {
|
||||
let mut data = self.data.write().unwrap();
|
||||
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(
|
||||
&mut data.layout,
|
||||
&mut self.layout,
|
||||
LayoutSettings::top_down_justified_centered(),
|
||||
"Top-down, centered and justified",
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut data.layout,
|
||||
&mut self.layout,
|
||||
LayoutSettings::horizontal_wrapped(),
|
||||
"Horizontal wrapped",
|
||||
);
|
||||
@@ -152,20 +140,20 @@ impl LayoutTest {
|
||||
Direction::TopDown,
|
||||
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.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");
|
||||
|
||||
if data.layout.main_wrap {
|
||||
if data.layout.main_dir.is_horizontal() {
|
||||
ui.add(Slider::new(&mut data.wrap_row_height, 0.0..=200.0).text("Row height"));
|
||||
if self.layout.main_wrap {
|
||||
if self.layout.main_dir.is_horizontal() {
|
||||
ui.add(Slider::new(&mut self.wrap_row_height, 0.0..=200.0).text("Row height"));
|
||||
} else {
|
||||
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.label("Cross Align:");
|
||||
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)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use super::*;
|
||||
use crate::LOREM_IPSUM;
|
||||
use egui::{epaint::text::TextWrapping, *};
|
||||
|
||||
/// Showcase some ui code
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct MiscDemoWindowData {
|
||||
pub struct MiscDemoWindow {
|
||||
num_columns: usize,
|
||||
|
||||
break_anywhere: bool,
|
||||
@@ -22,17 +21,10 @@ pub struct MiscDemoWindowData {
|
||||
dummy_bool: bool,
|
||||
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 {
|
||||
fn default() -> MiscDemoWindowData {
|
||||
MiscDemoWindowData {
|
||||
impl Default for MiscDemoWindow {
|
||||
fn default() -> MiscDemoWindow {
|
||||
MiscDemoWindow {
|
||||
num_columns: 2,
|
||||
|
||||
max_rows: 2,
|
||||
@@ -57,12 +49,11 @@ impl Demo for MiscDemoWindow {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
Window::new(self.name())
|
||||
.open(open)
|
||||
.vscroll(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) {
|
||||
ui.set_min_width(250.0);
|
||||
|
||||
let mut data = self.data.write().unwrap();
|
||||
let data = &mut *data;
|
||||
|
||||
CollapsingHeader::new("Widgets")
|
||||
.default_open(true)
|
||||
.show(ui, |ui| {
|
||||
data.widgets.ui(ui);
|
||||
self.widgets.ui(ui);
|
||||
});
|
||||
|
||||
CollapsingHeader::new("Text layout")
|
||||
@@ -84,25 +72,25 @@ impl View for MiscDemoWindow {
|
||||
.show(ui, |ui| {
|
||||
text_layout_ui(
|
||||
ui,
|
||||
&mut data.max_rows,
|
||||
&mut data.break_anywhere,
|
||||
&mut data.overflow_character,
|
||||
&mut self.max_rows,
|
||||
&mut self.break_anywhere,
|
||||
&mut self.overflow_character,
|
||||
);
|
||||
});
|
||||
|
||||
CollapsingHeader::new("Colors")
|
||||
.default_open(false)
|
||||
.show(ui, |ui| {
|
||||
data.colors.ui(ui);
|
||||
self.colors.ui(ui);
|
||||
});
|
||||
|
||||
CollapsingHeader::new("Custom Collapsing Header")
|
||||
.default_open(false)
|
||||
.show(ui, |ui| data.custom_collapsing_header.ui(ui));
|
||||
.show(ui, |ui| self.custom_collapsing_header.ui(ui));
|
||||
|
||||
CollapsingHeader::new("Tree")
|
||||
.default_open(false)
|
||||
.show(ui, |ui| data.tree.ui(ui));
|
||||
.show(ui, |ui| self.tree.ui(ui));
|
||||
|
||||
CollapsingHeader::new("Checkboxes")
|
||||
.default_open(false)
|
||||
@@ -111,28 +99,28 @@ impl View for MiscDemoWindow {
|
||||
ui.spacing_mut().item_spacing = Vec2::ZERO;
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
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.spacing_mut().item_spacing = Vec2::ZERO;
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
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.add(Slider::new(&mut data.num_columns, 1..=10).text("Columns"));
|
||||
ui.columns(data.num_columns, |cols| {
|
||||
ui.add(Slider::new(&mut self.num_columns, 1..=10).text("Columns"));
|
||||
ui.columns(self.num_columns, |cols| {
|
||||
for (i, col) in cols.iter_mut().enumerate() {
|
||||
col.label(format!("Column {} out of {}", i + 1, data.num_columns));
|
||||
if i + 1 == data.num_columns && col.button("Delete this").clicked() {
|
||||
data.num_columns -= 1;
|
||||
col.label(format!("Column {} out of {}", i + 1, self.num_columns));
|
||||
if i + 1 == self.num_columns && col.button("Delete this").clicked() {
|
||||
self.num_columns -= 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -140,7 +128,7 @@ impl View for MiscDemoWindow {
|
||||
|
||||
CollapsingHeader::new("Test box rendering")
|
||||
.default_open(false)
|
||||
.show(ui, |ui| data.box_painting.ui(ui));
|
||||
.show(ui, |ui| self.box_painting.ui(ui));
|
||||
|
||||
CollapsingHeader::new("Resize")
|
||||
.default_open(false)
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use egui::{
|
||||
emath::{RectTransform, Rot2},
|
||||
vec2, Color32, Frame, Pos2, Rect, Sense, Stroke, Vec2,
|
||||
};
|
||||
|
||||
pub struct MultiTouchData {
|
||||
pub struct MultiTouch {
|
||||
rotation: f32,
|
||||
translation: Vec2,
|
||||
zoom: f32,
|
||||
last_touch_time: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct MultiTouch {
|
||||
data: Arc<RwLock<MultiTouchData>>,
|
||||
}
|
||||
|
||||
impl Default for MultiTouchData {
|
||||
impl Default for MultiTouch {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
rotation: 0.,
|
||||
@@ -34,14 +27,13 @@ impl super::Demo for MultiTouch {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.default_size(vec2(512.0, 512.0))
|
||||
.resizable(true)
|
||||
.show(ctx, move |ui| {
|
||||
use super::View as _;
|
||||
clone.clone().ui(ui);
|
||||
self.ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -91,24 +83,22 @@ impl super::View for MultiTouch {
|
||||
// color and width:
|
||||
let mut stroke_width = 1.;
|
||||
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
|
||||
// change (for the current frame) of the touch gesture:
|
||||
data.zoom *= multi_touch.zoom_delta;
|
||||
data.rotation += multi_touch.rotation_delta;
|
||||
self.zoom *= multi_touch.zoom_delta;
|
||||
self.rotation += multi_touch.rotation_delta;
|
||||
// the translation we get from `multi_touch` needs to be scaled down to the
|
||||
// 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):
|
||||
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 {
|
||||
self.slowly_reset(ui);
|
||||
}
|
||||
let data = self.data.read().unwrap();
|
||||
let zoom_and_rotate = data.zoom * Rot2::from_angle(data.rotation);
|
||||
let arrow_start_offset = data.translation + zoom_and_rotate * vec2(-0.5, 0.5);
|
||||
let zoom_and_rotate = self.zoom * Rot2::from_angle(self.rotation);
|
||||
let arrow_start_offset = self.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
|
||||
// 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
|
||||
// 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) - data.last_touch_time) as f32;
|
||||
let time_since_last_touch = (ui.input(|i| i.time) - self.last_touch_time) as f32;
|
||||
|
||||
let delay = 0.5;
|
||||
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);
|
||||
|
||||
if half_life <= 1e-3 {
|
||||
data.zoom = 1.0;
|
||||
data.rotation = 0.0;
|
||||
data.translation = Vec2::ZERO;
|
||||
self.zoom = 1.0;
|
||||
self.rotation = 0.0;
|
||||
self.translation = Vec2::ZERO;
|
||||
} else {
|
||||
let dt = ui.input(|i| i.unstable_dt);
|
||||
let half_life_factor = (-(2_f32.ln()) / half_life * dt).exp();
|
||||
data.zoom = 1. + ((data.zoom - 1.) * half_life_factor);
|
||||
data.rotation *= half_life_factor;
|
||||
data.translation *= half_life_factor;
|
||||
self.zoom = 1. + ((self.zoom - 1.) * half_life_factor);
|
||||
self.rotation *= half_life_factor;
|
||||
self.translation *= half_life_factor;
|
||||
ui.ctx().request_repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use egui::epaint::{CubicBezierShape, PathShape, QuadraticBezierShape};
|
||||
use egui::*;
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct PaintBezierData {
|
||||
pub struct PaintBezier {
|
||||
/// Bézier curve degree, it can be 3, 4.
|
||||
degree: usize,
|
||||
|
||||
@@ -24,14 +22,7 @@ pub struct PaintBezierData {
|
||||
bounding_box_stroke: Stroke,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct PaintBezier {
|
||||
data: Arc<RwLock<PaintBezierData>>,
|
||||
}
|
||||
|
||||
impl Default for PaintBezierData {
|
||||
impl Default for PaintBezier {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
degree: 4,
|
||||
@@ -51,15 +42,14 @@ impl Default for PaintBezierData {
|
||||
|
||||
impl PaintBezier {
|
||||
pub fn ui_control(&mut self, ui: &mut egui::Ui) {
|
||||
let mut data = self.data.write().unwrap();
|
||||
ui.collapsing("Colors", |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
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 data.aux_stroke, "Auxiliary Stroke");
|
||||
egui::stroke_ui(ui, &mut data.bounding_box_stroke, "Bounding Box Stroke");
|
||||
egui::stroke_ui(ui, &mut self.stroke, "Curve Stroke");
|
||||
egui::stroke_ui(ui, &mut self.aux_stroke, "Auxiliary Stroke");
|
||||
egui::stroke_ui(ui, &mut self.bounding_box_stroke, "Bounding Box Stroke");
|
||||
});
|
||||
|
||||
ui.collapsing("Global tessellation options", |ui| {
|
||||
@@ -69,8 +59,8 @@ impl PaintBezier {
|
||||
.tessellation_options_mut(|to| *to = tessellation_options);
|
||||
});
|
||||
|
||||
ui.radio_value(&mut data.degree, 3, "Quadratic Bézier");
|
||||
ui.radio_value(&mut data.degree, 4, "Cubic Bézier");
|
||||
ui.radio_value(&mut self.degree, 3, "Quadratic Bézier");
|
||||
ui.radio_value(&mut self.degree, 4, "Cubic Bézier");
|
||||
ui.label("Move the points by dragging them.");
|
||||
ui.small("Only convex curves can be accurately filled.");
|
||||
}
|
||||
@@ -85,14 +75,12 @@ impl PaintBezier {
|
||||
);
|
||||
|
||||
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
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.take(data.degree)
|
||||
.take(self.degree)
|
||||
.map(|(i, point)| {
|
||||
let size = Vec2::splat(2.0 * control_point_radius);
|
||||
|
||||
@@ -111,33 +99,33 @@ impl PaintBezier {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let points_in_screen: Vec<Pos2> = data
|
||||
let points_in_screen: Vec<Pos2> = self
|
||||
.control_points
|
||||
.iter()
|
||||
.take(data.degree)
|
||||
.take(self.degree)
|
||||
.map(|p| to_screen * *p)
|
||||
.collect();
|
||||
|
||||
match data.degree {
|
||||
match self.degree {
|
||||
3 => {
|
||||
let points = points_in_screen.clone().try_into().unwrap();
|
||||
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(
|
||||
shape.visual_bounding_rect(),
|
||||
0.0,
|
||||
data.bounding_box_stroke,
|
||||
self.bounding_box_stroke,
|
||||
));
|
||||
painter.add(shape);
|
||||
}
|
||||
4 => {
|
||||
let points = points_in_screen.clone().try_into().unwrap();
|
||||
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(
|
||||
shape.visual_bounding_rect(),
|
||||
0.0,
|
||||
data.bounding_box_stroke,
|
||||
self.bounding_box_stroke,
|
||||
));
|
||||
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);
|
||||
|
||||
response
|
||||
@@ -159,14 +147,13 @@ impl super::Demo for PaintBezier {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
use super::View as _;
|
||||
Window::new(self.name())
|
||||
.open(open)
|
||||
.vscroll(false)
|
||||
.resizable(false)
|
||||
.default_size([300.0, 350.0])
|
||||
.show(ctx, move |ui| clone.clone().ui(ui));
|
||||
.show(ctx, move |ui| self.ui(ui));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use egui::*;
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct PaintingData {
|
||||
pub struct Painting {
|
||||
/// in 0-1 normalized coordinates
|
||||
lines: Vec<Vec<Pos2>>,
|
||||
stroke: Stroke,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Painting {
|
||||
data: Arc<RwLock<PaintingData>>,
|
||||
}
|
||||
|
||||
impl Default for PaintingData {
|
||||
impl Default for Painting {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
lines: Default::default(),
|
||||
@@ -27,12 +19,11 @@ impl Default for PaintingData {
|
||||
|
||||
impl Painting {
|
||||
pub fn ui_control(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
||||
let mut data = self.data.write().unwrap();
|
||||
ui.horizontal(|ui| {
|
||||
egui::stroke_ui(ui, &mut data.stroke, "Stroke");
|
||||
egui::stroke_ui(ui, &mut self.stroke, "Stroke");
|
||||
ui.separator();
|
||||
if ui.button("Clear Painting").clicked() {
|
||||
data.lines.clear();
|
||||
self.lines.clear();
|
||||
}
|
||||
})
|
||||
.response
|
||||
@@ -48,13 +39,11 @@ impl Painting {
|
||||
);
|
||||
let from_screen = to_screen.inverse();
|
||||
|
||||
let mut data = self.data.write().unwrap();
|
||||
|
||||
if data.lines.is_empty() {
|
||||
data.lines.push(vec![]);
|
||||
if self.lines.is_empty() {
|
||||
self.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() {
|
||||
let canvas_pos = from_screen * pointer_pos;
|
||||
@@ -63,17 +52,17 @@ impl Painting {
|
||||
response.mark_changed();
|
||||
}
|
||||
} else if !current_line.is_empty() {
|
||||
data.lines.push(vec![]);
|
||||
self.lines.push(vec![]);
|
||||
response.mark_changed();
|
||||
}
|
||||
|
||||
let shapes = data
|
||||
let shapes = self
|
||||
.lines
|
||||
.iter()
|
||||
.filter(|line| line.len() >= 2)
|
||||
.map(|line| {
|
||||
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);
|
||||
@@ -88,13 +77,12 @@ impl super::Demo for Painting {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
use super::View as _;
|
||||
Window::new(self.name())
|
||||
.open(open)
|
||||
.default_size(vec2(512.0, 512.0))
|
||||
.vscroll(false)
|
||||
.show(ctx, move |ui| clone.clone().ui(ui));
|
||||
.show(ctx, move |ui| self.ui(ui));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::f64::consts::TAU;
|
||||
use std::ops::RangeInclusive;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use egui::plot::{AxisBools, GridInput, GridMark, PlotResponse};
|
||||
use egui::*;
|
||||
@@ -31,9 +30,8 @@ impl Default for Panel {
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[derive(PartialEq, Default)]
|
||||
pub struct PlotDemoData {
|
||||
#[derive(Default, PartialEq)]
|
||||
pub struct PlotDemo {
|
||||
line_demo: LineDemo,
|
||||
marker_demo: MarkerDemo,
|
||||
legend_demo: LegendDemo,
|
||||
@@ -45,30 +43,18 @@ pub struct PlotDemoData {
|
||||
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 {
|
||||
fn name(&self) -> &'static str {
|
||||
"🗠 Plot"
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
use super::View as _;
|
||||
Window::new(self.name())
|
||||
.open(open)
|
||||
.default_size(vec2(400.0, 400.0))
|
||||
.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!());
|
||||
});
|
||||
});
|
||||
let mut data = self.data.write().unwrap();
|
||||
ui.separator();
|
||||
ui.horizontal(|ui| {
|
||||
ui.selectable_value(&mut data.open_panel, Panel::Lines, "Lines");
|
||||
ui.selectable_value(&mut data.open_panel, Panel::Markers, "Markers");
|
||||
ui.selectable_value(&mut data.open_panel, Panel::Legend, "Legend");
|
||||
ui.selectable_value(&mut data.open_panel, Panel::Charts, "Charts");
|
||||
ui.selectable_value(&mut data.open_panel, Panel::Items, "Items");
|
||||
ui.selectable_value(&mut data.open_panel, Panel::Interaction, "Interaction");
|
||||
ui.selectable_value(&mut data.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::Lines, "Lines");
|
||||
ui.selectable_value(&mut self.open_panel, Panel::Markers, "Markers");
|
||||
ui.selectable_value(&mut self.open_panel, Panel::Legend, "Legend");
|
||||
ui.selectable_value(&mut self.open_panel, Panel::Charts, "Charts");
|
||||
ui.selectable_value(&mut self.open_panel, Panel::Items, "Items");
|
||||
ui.selectable_value(&mut self.open_panel, Panel::Interaction, "Interaction");
|
||||
ui.selectable_value(&mut self.open_panel, Panel::CustomAxes, "Custom Axes");
|
||||
ui.selectable_value(&mut self.open_panel, Panel::LinkedAxes, "Linked Axes");
|
||||
});
|
||||
ui.separator();
|
||||
|
||||
match data.open_panel {
|
||||
match self.open_panel {
|
||||
Panel::Lines => {
|
||||
data.line_demo.ui(ui);
|
||||
self.line_demo.ui(ui);
|
||||
}
|
||||
Panel::Markers => {
|
||||
data.marker_demo.ui(ui);
|
||||
self.marker_demo.ui(ui);
|
||||
}
|
||||
Panel::Legend => {
|
||||
data.legend_demo.ui(ui);
|
||||
self.legend_demo.ui(ui);
|
||||
}
|
||||
Panel::Charts => {
|
||||
data.charts_demo.ui(ui);
|
||||
self.charts_demo.ui(ui);
|
||||
}
|
||||
Panel::Items => {
|
||||
data.items_demo.ui(ui);
|
||||
self.items_demo.ui(ui);
|
||||
}
|
||||
Panel::Interaction => {
|
||||
data.interaction_demo.ui(ui);
|
||||
self.interaction_demo.ui(ui);
|
||||
}
|
||||
Panel::CustomAxes => {
|
||||
data.custom_axes_demo.ui(ui);
|
||||
self.custom_axes_demo.ui(ui);
|
||||
}
|
||||
Panel::LinkedAxes => {
|
||||
data.linked_axes_demo.ui(ui);
|
||||
self.linked_axes_demo.ui(ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use egui::*;
|
||||
|
||||
#[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", serde(default))]
|
||||
#[derive(Default, PartialEq)]
|
||||
pub struct ScrollingData {
|
||||
pub struct Scrolling {
|
||||
demo: ScrollDemo,
|
||||
scroll_to: ScrollTo,
|
||||
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 {
|
||||
fn name(&self) -> &'static str {
|
||||
"↕ Scrolling"
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.resizable(false)
|
||||
.show(ctx, move |ui| {
|
||||
use super::View as _;
|
||||
clone.clone().ui(ui);
|
||||
self.ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl super::View for Scrolling {
|
||||
fn ui(&mut self, ui: &mut Ui) {
|
||||
let mut data = self.data.write().unwrap();
|
||||
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(
|
||||
&mut data.demo,
|
||||
&mut self.demo,
|
||||
ScrollDemo::ManyLines,
|
||||
"Scroll a lot of lines",
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut data.demo,
|
||||
&mut self.demo,
|
||||
ScrollDemo::LargeCanvas,
|
||||
"Scroll a large canvas",
|
||||
);
|
||||
ui.selectable_value(&mut data.demo, ScrollDemo::StickToEnd, "Stick to end");
|
||||
ui.selectable_value(&mut data.demo, ScrollDemo::Bidirectional, "Bidirectional");
|
||||
ui.selectable_value(&mut self.demo, ScrollDemo::StickToEnd, "Stick to end");
|
||||
ui.selectable_value(&mut self.demo, ScrollDemo::Bidirectional, "Bidirectional");
|
||||
});
|
||||
ui.separator();
|
||||
match data.demo {
|
||||
match self.demo {
|
||||
ScrollDemo::ScrollTo => {
|
||||
data.scroll_to.ui(ui);
|
||||
self.scroll_to.ui(ui);
|
||||
}
|
||||
ScrollDemo::ManyLines => {
|
||||
huge_content_lines(ui);
|
||||
@@ -87,7 +70,7 @@ impl super::View for Scrolling {
|
||||
huge_content_painter(ui);
|
||||
}
|
||||
ScrollDemo::StickToEnd => {
|
||||
data.scroll_stick_to.ui(ui);
|
||||
self.scroll_stick_to.ui(ui);
|
||||
}
|
||||
ScrollDemo::Bidirectional => {
|
||||
egui::ScrollArea::both().show(ui, |ui| {
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
use egui::*;
|
||||
use std::{
|
||||
f64::INFINITY,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use std::f64::INFINITY;
|
||||
|
||||
/// Showcase sliders
|
||||
#[derive(PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
pub struct SlidersData {
|
||||
pub struct Sliders {
|
||||
pub min: f64,
|
||||
pub max: f64,
|
||||
pub logarithmic: bool,
|
||||
@@ -22,20 +19,7 @@ pub struct SlidersData {
|
||||
pub trailing_fill: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[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 {
|
||||
impl Default for Sliders {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
min: 0.0,
|
||||
@@ -59,13 +43,12 @@ impl super::Demo for Sliders {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.resizable(false)
|
||||
.show(ctx, move |ui| {
|
||||
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 {
|
||||
fn ui(&mut self, ui: &mut Ui) {
|
||||
{
|
||||
let SlidersData {
|
||||
let Sliders {
|
||||
min,
|
||||
max,
|
||||
logarithmic,
|
||||
@@ -85,7 +68,7 @@ impl super::View for Sliders {
|
||||
vertical,
|
||||
value,
|
||||
trailing_fill,
|
||||
} = &mut *self.data.write().unwrap();
|
||||
} = self;
|
||||
|
||||
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() {
|
||||
self.data.write().unwrap().value = std::f64::consts::PI;
|
||||
self.value = std::f64::consts::PI;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
enum DemoType {
|
||||
@@ -8,8 +6,9 @@ enum DemoType {
|
||||
ManyHeterogenous,
|
||||
}
|
||||
|
||||
/// Shows off a table with dynamic layout
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct TableDemoData {
|
||||
pub struct TableDemo {
|
||||
demo: DemoType,
|
||||
striped: bool,
|
||||
resizable: bool,
|
||||
@@ -18,14 +17,7 @@ pub struct TableDemoData {
|
||||
scroll_to_row: Option<usize>,
|
||||
}
|
||||
|
||||
/// Shows off a table with dynamic layout
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct TableDemo {
|
||||
data: Arc<RwLock<TableDemoData>>,
|
||||
}
|
||||
|
||||
impl Default for TableDemoData {
|
||||
impl Default for TableDemo {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
demo: DemoType::Manual,
|
||||
@@ -44,14 +36,13 @@ impl super::Demo for TableDemo {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.resizable(true)
|
||||
.default_width(400.0)
|
||||
.show(ctx, move |ui| {
|
||||
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 {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
{
|
||||
let mut data = self.data.write().unwrap();
|
||||
ui.vertical(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.checkbox(&mut data.striped, "Striped");
|
||||
ui.checkbox(&mut data.resizable, "Resizable columns");
|
||||
ui.checkbox(&mut self.striped, "Striped");
|
||||
ui.checkbox(&mut self.resizable, "Resizable columns");
|
||||
});
|
||||
|
||||
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(
|
||||
&mut data.demo,
|
||||
&mut self.demo,
|
||||
DemoType::ManyHomogeneous,
|
||||
"Thousands of rows of same height",
|
||||
);
|
||||
ui.radio_value(
|
||||
&mut data.demo,
|
||||
&mut self.demo,
|
||||
DemoType::ManyHeterogenous,
|
||||
"Thousands of rows of differing heights",
|
||||
);
|
||||
|
||||
if data.demo != DemoType::Manual {
|
||||
if self.demo != DemoType::Manual {
|
||||
ui.add(
|
||||
egui::Slider::new(&mut data.num_rows, 0..=100_000)
|
||||
egui::Slider::new(&mut self.num_rows, 0..=100_000)
|
||||
.logarithmic(true)
|
||||
.text("Num rows"),
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
let max_rows = if data.demo == DemoType::Manual {
|
||||
let max_rows = if self.demo == DemoType::Manual {
|
||||
NUM_MANUAL_ROWS
|
||||
} else {
|
||||
data.num_rows
|
||||
self.num_rows
|
||||
};
|
||||
|
||||
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)
|
||||
.text("Row to scroll to"),
|
||||
);
|
||||
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};
|
||||
|
||||
let text_height = egui::TextStyle::Body.resolve(ui.style()).size;
|
||||
let mut data = self.data.write().unwrap();
|
||||
|
||||
let mut table = TableBuilder::new(ui)
|
||||
.striped(data.striped)
|
||||
.resizable(data.resizable)
|
||||
.striped(self.striped)
|
||||
.resizable(self.resizable)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.column(Column::auto())
|
||||
.column(Column::initial(100.0).range(40.0..=300.0))
|
||||
@@ -147,7 +136,7 @@ impl TableDemo {
|
||||
.column(Column::remainder())
|
||||
.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);
|
||||
}
|
||||
|
||||
@@ -166,7 +155,7 @@ impl TableDemo {
|
||||
ui.strong("Content");
|
||||
});
|
||||
})
|
||||
.body(|mut body| match data.demo {
|
||||
.body(|mut body| match self.demo {
|
||||
DemoType::Manual => {
|
||||
for row_index in 0..NUM_MANUAL_ROWS {
|
||||
let is_thick = thick_row(row_index);
|
||||
@@ -193,7 +182,7 @@ impl TableDemo {
|
||||
}
|
||||
}
|
||||
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| {
|
||||
ui.label(row_index.to_string());
|
||||
});
|
||||
@@ -219,7 +208,7 @@ impl TableDemo {
|
||||
}
|
||||
}
|
||||
body.heterogeneous_rows(
|
||||
(0..data.num_rows).map(row_thickness),
|
||||
(0..self.num_rows).map(row_thickness),
|
||||
|row_index, mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label(row_index.to_string());
|
||||
|
||||
@@ -97,13 +97,14 @@ enum WidgetType {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ManualLayoutTestData {
|
||||
pub struct ManualLayoutTest {
|
||||
widget_offset: egui::Vec2,
|
||||
widget_size: egui::Vec2,
|
||||
widget_type: WidgetType,
|
||||
text_edit_contents: String,
|
||||
}
|
||||
impl Default for ManualLayoutTestData {
|
||||
|
||||
impl Default for ManualLayoutTest {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
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 {
|
||||
fn name(&self) -> &'static str {
|
||||
"Manual Layout Test"
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.resizable(false)
|
||||
.open(open)
|
||||
.show(ctx, move |ui| {
|
||||
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) {
|
||||
egui::reset_button(ui, self);
|
||||
|
||||
let ManualLayoutTestData {
|
||||
let ManualLayoutTest {
|
||||
widget_offset,
|
||||
widget_size,
|
||||
widget_type,
|
||||
text_edit_contents,
|
||||
} = &mut *self.data.write().unwrap();
|
||||
} = self;
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Test widget:");
|
||||
ui.radio_value(widget_type, WidgetType::Button, "Button");
|
||||
@@ -192,7 +181,7 @@ impl super::View for ManualLayoutTest {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#[derive(PartialEq)]
|
||||
pub struct TableTestData {
|
||||
pub struct TableTest {
|
||||
num_cols: usize,
|
||||
num_rows: usize,
|
||||
min_col_width: f32,
|
||||
@@ -200,18 +189,7 @@ pub struct TableTestData {
|
||||
text_length: usize,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
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 {
|
||||
impl Default for TableTest {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
num_cols: 4,
|
||||
@@ -229,12 +207,11 @@ impl super::Demo for TableTest {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.show(ctx, move |ui| {
|
||||
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 {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
{
|
||||
let mut data = self.data.write().unwrap();
|
||||
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"),
|
||||
);
|
||||
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"),
|
||||
);
|
||||
ui.add(egui::Slider::new(&mut data.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_cols, 0..=5).text("Columns"));
|
||||
ui.add(egui::Slider::new(&mut self.num_rows, 0..=20).text("Rows"));
|
||||
|
||||
ui.separator();
|
||||
|
||||
@@ -263,11 +239,11 @@ impl super::View for TableTest {
|
||||
|
||||
egui::Grid::new("my_grid")
|
||||
.striped(true)
|
||||
.min_col_width(data.min_col_width)
|
||||
.max_col_width(data.max_col_width)
|
||||
.min_col_width(self.min_col_width)
|
||||
.max_col_width(self.max_col_width)
|
||||
.show(ui, |ui| {
|
||||
for row in 0..data.num_rows {
|
||||
for col in 0..data.num_cols {
|
||||
for row in 0..self.num_rows {
|
||||
for col in 0..self.num_cols {
|
||||
if col == 0 {
|
||||
ui.label(format!("row {}", row));
|
||||
} else {
|
||||
@@ -286,7 +262,7 @@ impl super::View for TableTest {
|
||||
});
|
||||
|
||||
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| {
|
||||
ui.vertical(|ui| {
|
||||
ui.label("Vertical nest1");
|
||||
@@ -321,7 +297,7 @@ impl super::View for TableTest {
|
||||
ui.end_row();
|
||||
|
||||
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("Fifth row, second column");
|
||||
ui.end_row();
|
||||
@@ -338,9 +314,9 @@ impl super::View for TableTest {
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default)]
|
||||
pub struct InputTest {
|
||||
info: Arc<RwLock<String>>,
|
||||
info: String,
|
||||
}
|
||||
|
||||
impl super::Demo for InputTest {
|
||||
@@ -349,13 +325,12 @@ impl super::Demo for InputTest {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.resizable(false)
|
||||
.show(ctx, move |ui| {
|
||||
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() {
|
||||
*self.info.write().unwrap() = new_info;
|
||||
self.info = new_info;
|
||||
}
|
||||
|
||||
ui.label(&*self.info.write().unwrap());
|
||||
ui.label(&self.info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
/// Showcase [`TextEdit`].
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(default))]
|
||||
#[derive(Clone)]
|
||||
pub struct TextEdit {
|
||||
pub text: Arc<RwLock<String>>,
|
||||
}
|
||||
|
||||
impl PartialEq for TextEdit {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
*self.text.read().unwrap() == *other.text.read().unwrap()
|
||||
}
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
impl Default for TextEdit {
|
||||
fn default() -> 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) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.resizable(false)
|
||||
.show(ctx, move |ui| {
|
||||
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 {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
let Self { text } = self;
|
||||
let text = &mut *text.write().unwrap();
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 0.0;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
enum Enum {
|
||||
@@ -8,8 +6,9 @@ enum Enum {
|
||||
Third,
|
||||
}
|
||||
|
||||
/// Shows off one example of each major type of widget.
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct WidgetGalleryData {
|
||||
pub struct WidgetGallery {
|
||||
enabled: bool,
|
||||
visible: bool,
|
||||
boolean: bool,
|
||||
@@ -27,14 +26,7 @@ pub struct WidgetGalleryData {
|
||||
texture: Option<egui::TextureHandle>,
|
||||
}
|
||||
|
||||
/// Shows off one example of each major type of widget.
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct WidgetGallery {
|
||||
data: Arc<RwLock<WidgetGalleryData>>,
|
||||
}
|
||||
|
||||
impl Default for WidgetGalleryData {
|
||||
impl Default for WidgetGallery {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: true,
|
||||
@@ -58,24 +50,21 @@ impl super::Demo for WidgetGallery {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let clone = self.clone();
|
||||
egui::Window::new(self.name())
|
||||
.open(open)
|
||||
.resizable(true)
|
||||
.default_width(280.0)
|
||||
.show(ctx, move |ui| {
|
||||
use super::View as _;
|
||||
clone.clone().ui(ui);
|
||||
self.ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl super::View for WidgetGallery {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
let enabled = self.data.read().unwrap().enabled;
|
||||
let visible = self.data.read().unwrap().visible;
|
||||
ui.add_enabled_ui(enabled, |ui| {
|
||||
ui.set_visible(visible);
|
||||
ui.add_enabled_ui(self.enabled, |ui| {
|
||||
ui.set_visible(self.visible);
|
||||
|
||||
egui::Grid::new("my_grid")
|
||||
.num_columns(2)
|
||||
@@ -85,14 +74,13 @@ impl super::View for WidgetGallery {
|
||||
self.gallery_grid_contents(ui);
|
||||
});
|
||||
});
|
||||
let data = &mut *self.data.write().unwrap();
|
||||
ui.separator();
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.checkbox(&mut data.visible, "Visible")
|
||||
ui.checkbox(&mut self.visible, "Visible")
|
||||
.on_hover_text("Uncheck to hide all the widgets.");
|
||||
if data.visible {
|
||||
ui.checkbox(&mut data.enabled, "Interactive")
|
||||
if self.visible {
|
||||
ui.checkbox(&mut self.enabled, "Interactive")
|
||||
.on_hover_text("Uncheck to inspect how the widgets look when disabled.");
|
||||
}
|
||||
});
|
||||
@@ -111,7 +99,7 @@ impl super::View for WidgetGallery {
|
||||
|
||||
impl WidgetGallery {
|
||||
fn gallery_grid_contents(&mut self, ui: &mut egui::Ui) {
|
||||
let WidgetGalleryData {
|
||||
let WidgetGallery {
|
||||
enabled: _,
|
||||
visible: _,
|
||||
boolean,
|
||||
@@ -123,7 +111,7 @@ impl WidgetGallery {
|
||||
#[cfg(feature = "chrono")]
|
||||
date,
|
||||
texture,
|
||||
} = &mut *self.data.write().unwrap();
|
||||
} = self;
|
||||
|
||||
let texture: &egui::TextureHandle = texture.get_or_insert_with(|| {
|
||||
ui.ctx()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct WindowOptionsData {
|
||||
pub struct WindowOptions {
|
||||
title: String,
|
||||
title_bar: bool,
|
||||
closable: bool,
|
||||
@@ -15,19 +13,8 @@ pub struct WindowOptionsData {
|
||||
anchor: egui::Align2,
|
||||
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 {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
*self.data.read().unwrap() == *other.data.read().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for WindowOptionsData {
|
||||
impl Default for WindowOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
title: "🗖 Window Options".to_owned(),
|
||||
@@ -50,7 +37,7 @@ impl super::Demo for WindowOptions {
|
||||
}
|
||||
|
||||
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
|
||||
let WindowOptionsData {
|
||||
let WindowOptions {
|
||||
title,
|
||||
title_bar,
|
||||
closable,
|
||||
@@ -61,7 +48,7 @@ impl super::Demo for WindowOptions {
|
||||
anchored,
|
||||
anchor,
|
||||
anchor_offset,
|
||||
} = self.data.read().unwrap().clone();
|
||||
} = self.clone();
|
||||
|
||||
let enabled = ctx.input(|i| i.time) - disabled_time > 2.0;
|
||||
if !enabled {
|
||||
@@ -82,76 +69,70 @@ impl super::Demo for WindowOptions {
|
||||
if anchored {
|
||||
window = window.anchor(anchor, anchor_offset);
|
||||
}
|
||||
let clone = self.clone();
|
||||
window.show(ctx, move |ui| {
|
||||
let mut clone = clone.clone();
|
||||
clone.ui(ui)
|
||||
});
|
||||
window.show(ctx, move |ui| self.ui(ui));
|
||||
}
|
||||
}
|
||||
|
||||
impl super::View for WindowOptions {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
{
|
||||
let WindowOptionsData {
|
||||
title,
|
||||
title_bar,
|
||||
closable,
|
||||
collapsible,
|
||||
resizable,
|
||||
scroll2,
|
||||
disabled_time: _,
|
||||
anchored,
|
||||
anchor,
|
||||
anchor_offset,
|
||||
} = &mut *self.data.write().unwrap();
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("title:");
|
||||
ui.text_edit_singleline(title);
|
||||
});
|
||||
let WindowOptions {
|
||||
title,
|
||||
title_bar,
|
||||
closable,
|
||||
collapsible,
|
||||
resizable,
|
||||
scroll2,
|
||||
disabled_time: _,
|
||||
anchored,
|
||||
anchor,
|
||||
anchor_offset,
|
||||
} = self;
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("title:");
|
||||
ui.text_edit_singleline(title);
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.group(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.checkbox(title_bar, "title_bar");
|
||||
ui.checkbox(closable, "closable");
|
||||
ui.checkbox(collapsible, "collapsible");
|
||||
ui.checkbox(resizable, "resizable");
|
||||
ui.checkbox(&mut scroll2[0], "hscroll");
|
||||
ui.checkbox(&mut scroll2[1], "vscroll");
|
||||
});
|
||||
ui.horizontal(|ui| {
|
||||
ui.group(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.checkbox(title_bar, "title_bar");
|
||||
ui.checkbox(closable, "closable");
|
||||
ui.checkbox(collapsible, "collapsible");
|
||||
ui.checkbox(resizable, "resizable");
|
||||
ui.checkbox(&mut scroll2[0], "hscroll");
|
||||
ui.checkbox(&mut scroll2[1], "vscroll");
|
||||
});
|
||||
ui.group(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.checkbox(anchored, "anchored");
|
||||
ui.set_enabled(*anchored);
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("x:");
|
||||
ui.selectable_value(&mut anchor[0], egui::Align::LEFT, "Left");
|
||||
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.selectable_value(&mut anchor[1], egui::Align::TOP, "Top");
|
||||
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.add(egui::DragValue::new(&mut anchor_offset.x));
|
||||
ui.add(egui::DragValue::new(&mut anchor_offset.y));
|
||||
});
|
||||
});
|
||||
ui.group(|ui| {
|
||||
ui.vertical(|ui| {
|
||||
ui.checkbox(anchored, "anchored");
|
||||
ui.set_enabled(*anchored);
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("x:");
|
||||
ui.selectable_value(&mut anchor[0], egui::Align::LEFT, "Left");
|
||||
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.selectable_value(&mut anchor[1], egui::Align::TOP, "Top");
|
||||
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.add(egui::DragValue::new(&mut anchor_offset.x));
|
||||
ui.add(egui::DragValue::new(&mut anchor_offset.y));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
ui.separator();
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
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);
|
||||
ui.add(crate::egui_github_link_file!());
|
||||
|
||||
Reference in New Issue
Block a user