Hide all other series when alt-clicking in the legend (#4549)

https://github.com/emilk/egui/assets/49431240/75d32f53-4c1c-4713-b25e-e1787e465a48

* Closes #4548
This commit is contained in:
Antoine Beyeler 2024-05-27 18:56:16 +02:00 committed by GitHub
parent ff7a3832b6
commit 192a111272
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 46 additions and 8 deletions

View File

@ -99,11 +99,11 @@ impl LegendEntry {
}
}
fn ui(&mut self, ui: &mut Ui, text: String, text_style: &TextStyle) -> Response {
fn ui(&self, ui: &mut Ui, text: String, text_style: &TextStyle) -> Response {
let Self {
color,
checked,
hovered,
hovered: _,
} = self;
let font_id = text_style.resolve(ui.style());
@ -162,9 +162,6 @@ impl LegendEntry {
let text_position = pos2(text_position_x, rect.center().y - 0.5 * galley.size().y);
painter.galley(text_position, galley, visuals.text_color());
*checked ^= response.clicked_by(PointerButton::Primary);
*hovered = response.hovered();
response
}
}
@ -267,14 +264,55 @@ impl Widget for &mut LegendWidget {
.multiply_with_opacity(config.background_alpha);
background_frame
.show(ui, |ui| {
entries
let mut focus_on_item = None;
let response_union = entries
.iter_mut()
.map(|(name, entry)| entry.ui(ui, name.clone(), &config.text_style))
.map(|(name, entry)| {
let response = entry.ui(ui, name.clone(), &config.text_style);
// Handle interactions. Alt-clicking must be deferred to end of loop
// since it may affect all entries.
handle_interaction_on_legend_item(&response, entry);
if response.clicked() && ui.input(|r| r.modifiers.alt) {
focus_on_item = Some(name.clone());
}
response
})
.reduce(|r1, r2| r1.union(r2))
.unwrap()
.unwrap();
if let Some(focus_on_item) = focus_on_item {
handle_focus_on_legend_item(&focus_on_item, entries);
}
response_union
})
.inner
})
.inner
}
}
/// Handle per-entry interactions.
fn handle_interaction_on_legend_item(response: &Response, entry: &mut LegendEntry) {
entry.checked ^= response.clicked_by(PointerButton::Primary);
entry.hovered = response.hovered();
}
/// Handle alt-click interaction (which may affect all entries).
fn handle_focus_on_legend_item(
clicked_entry_name: &str,
entries: &mut BTreeMap<String, LegendEntry>,
) {
// if all other items are already hidden, we show everything
let is_focus_item_only_visible = entries
.iter()
.all(|(name, entry)| !entry.checked || (clicked_entry_name == name));
// either show everything or show only the focus item
for (name, entry) in entries.iter_mut() {
entry.checked = is_focus_item_only_visible || clicked_entry_name == name;
}
}