Skip to content

Commit

Permalink
Improve input test
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Jan 25, 2024
1 parent d190df7 commit e574eaa
Showing 1 changed file with 136 additions and 36 deletions.
172 changes: 136 additions & 36 deletions crates/egui_demo_lib/src/demo/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,58 @@ impl super::View for TableTest {

// ----------------------------------------------------------------------------

struct HistoryEntry {
text: String,
repeated: usize,
}

#[derive(Default)]
struct DeduplicatedHistory {
history: std::collections::VecDeque<HistoryEntry>,
}

impl DeduplicatedHistory {
fn add(&mut self, text: String) {
if let Some(entry) = self.history.back_mut() {
if entry.text == text {
entry.repeated += 1;
return;
}
}
self.history.push_back(HistoryEntry { text, repeated: 1 });
if self.history.len() > 100 {
self.history.pop_front();
}
}

fn ui(&self, ui: &mut egui::Ui) {
egui::ScrollArea::vertical()
.auto_shrink(false)
.show(ui, |ui| {
ui.spacing_mut().item_spacing.y = 4.0;
for HistoryEntry { text, repeated } in self.history.iter().rev() {
ui.horizontal(|ui| {
if text.is_empty() {
ui.weak("(empty)");
} else {
ui.label(text);
}
if 1 < *repeated {
ui.weak(format!(" x{repeated}"));
}
});
}
});
}
}

#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Default)]
pub struct InputTest {
info: String,
#[cfg_attr(feature = "serde", serde(skip))]
history: [DeduplicatedHistory; 4],

show_hovers: bool,
}

impl super::Demo for InputTest {
Expand All @@ -319,8 +367,10 @@ impl super::Demo for InputTest {

fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
egui::Window::new(self.name())
.default_width(800.0)
.open(open)
.resizable(false)
.resizable(true)
.scroll2(false)
.show(ctx, |ui| {
use super::View as _;
self.ui(ui);
Expand All @@ -330,50 +380,100 @@ impl super::Demo for InputTest {

impl super::View for InputTest {
fn ui(&mut self, ui: &mut egui::Ui) {
ui.spacing_mut().item_spacing.y = 8.0;

ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file!());
});

let response = ui.add(
egui::Button::new("Click, double-click, triple-click or drag me with any mouse button")
.sense(egui::Sense::click_and_drag()),
);

let mut new_info = String::new();
for &button in &[
egui::PointerButton::Primary,
egui::PointerButton::Secondary,
egui::PointerButton::Middle,
egui::PointerButton::Extra1,
egui::PointerButton::Extra2,
] {
use std::fmt::Write as _;

if response.clicked_by(button) {
writeln!(new_info, "Clicked by {button:?} button").ok();
}
if response.double_clicked_by(button) {
writeln!(new_info, "Double-clicked by {button:?} button").ok();
}
if response.triple_clicked_by(button) {
writeln!(new_info, "Triple-clicked by {button:?} button").ok();
ui.horizontal(|ui| {
if ui.button("Clear").clicked() {
*self = Default::default();
}
if response.dragged_by(button) {
writeln!(
new_info,
"Dragged by {:?} button, delta: {:?}",
button,
response.drag_delta()
)
.ok();

ui.checkbox(&mut self.show_hovers, "Show hover state");
});

ui.label("This tests how egui::Response reports events.\n\
The different buttons are sensitive to different things.\n\
Try interacting with them with any mouse button by clicking, double-clicking, triple-clicking, or dragging them.");

ui.columns(4, |columns| {
for (i, (sense_name, sense)) in [
("Sense::hover", egui::Sense::hover()),
("Sense::click", egui::Sense::click()),
("Sense::drag", egui::Sense::drag()),
("Sense::click_and_drag", egui::Sense::click_and_drag()),
]
.into_iter()
.enumerate()
{
columns[i].push_id(i, |ui| {
let response = ui.add(egui::Button::new(sense_name).sense(sense));
let info = response_summary(&response, self.show_hovers);
self.history[i].add(info.trim().to_owned());
self.history[i].ui(ui);
});
}
});
}
}

fn response_summary(response: &egui::Response, show_hovers: bool) -> String {
use std::fmt::Write as _;

let mut new_info = String::new();

if show_hovers {
if response.hovered() {
writeln!(new_info, "hovered").ok();
}
if response.contains_pointer() {
writeln!(new_info, "contains_pointer").ok();
}
if response.is_pointer_button_down_on() {
writeln!(new_info, "pointer_down_on").ok();
}
}

for &button in &[
egui::PointerButton::Primary,
egui::PointerButton::Secondary,
egui::PointerButton::Middle,
egui::PointerButton::Extra1,
egui::PointerButton::Extra2,
] {
let button_suffix = if button == egui::PointerButton::Primary {
// Reduce visual clutter in common case:
String::default()
} else {
format!(" by {button:?} button")
};

// These are in inverse logical/chonological order, because we show them in the ui that way:

if response.triple_clicked_by(button) {
writeln!(new_info, "Triple-clicked{button_suffix}").ok();
}
if response.double_clicked_by(button) {
writeln!(new_info, "Double-clicked{button_suffix}").ok();
}
if !new_info.is_empty() {
self.info = new_info;
if response.clicked_by(button) {
writeln!(new_info, "Clicked{button_suffix}").ok();
}

ui.label(&self.info);
if response.drag_released_by(button) {
writeln!(new_info, "Drag ended{button_suffix}").ok();
}
if response.dragged_by(button) {
writeln!(new_info, "Dragged{button_suffix}").ok();
}
if response.drag_started_by(button) {
writeln!(new_info, "Drag started{button_suffix}").ok();
}
}

new_info
}

// ----------------------------------------------------------------------------
Expand Down

0 comments on commit e574eaa

Please sign in to comment.