Skip to content

Commit

Permalink
Hide all other series when alt-clicking in the legend (emilk#4549)
Browse files Browse the repository at this point in the history
  • Loading branch information
abey79 authored and hacknus committed Oct 30, 2024
1 parent 27aa50c commit 94e8e51
Showing 1 changed file with 46 additions and 8 deletions.
54 changes: 46 additions & 8 deletions crates/egui_plot/src/legend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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
}
}
Expand Down Expand Up @@ -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;
}
}

0 comments on commit 94e8e51

Please sign in to comment.