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

Selectable text in Labels (#3814)

* Closes https://github.com/emilk/egui/issues/3804

Add ability to select the text in labels with mouse-drag, double-click,
and keyboard (once clicked).
Hit Cmd+C to copy the text. If everything of a label with elided text is
selected, the copy command will copy the full non-elided text. IME and
accesskit _should_ work, but is untested.

You can control wether or not text in labels is selected globally in
`style.interaction.selectable_labels` or on a per-label basis in
`Label::selectable`. The default is ON.

This also cleans up the `TextEdit` code somewhat, fixing a couple
smaller bugs along the way.

This does _not_ implement selecting text across multiple widgets. Text
selection is only supported within a single `Label`, `TextEdit`, `Link`
or `Hyperlink`.


![label-text-selection](https://github.com/emilk/egui/assets/1148717/c161e819-50da-4b97-9686-042e6abf3564)


## TODO
* [x] Test
This commit is contained in:
Emil Ernerfeldt
2024-01-14 15:17:55 +01:00
committed by GitHub
parent 301c72ba22
commit 5d2e192927
18 changed files with 1031 additions and 632 deletions

View File

@@ -205,21 +205,13 @@ fn ui_resource(ui: &mut egui::Ui, resource: &Resource) {
} else if let Some(colored_text) = colored_text {
colored_text.ui(ui);
} else if let Some(text) = &text {
selectable_text(ui, text);
ui.add(egui::Label::new(text).selectable(true));
} else {
ui.monospace("[binary]");
}
});
}
fn selectable_text(ui: &mut egui::Ui, mut text: &str) {
ui.add(
egui::TextEdit::multiline(&mut text)
.desired_width(f32::INFINITY)
.font(egui::TextStyle::Monospace),
);
}
// ----------------------------------------------------------------------------
// Syntax highlighting:
@@ -240,31 +232,9 @@ struct ColoredText(egui::text::LayoutJob);
impl ColoredText {
pub fn ui(&self, ui: &mut egui::Ui) {
if true {
// Selectable text:
let mut layouter = |ui: &egui::Ui, _string: &str, wrap_width: f32| {
let mut layout_job = self.0.clone();
layout_job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(layout_job))
};
let mut text = self.0.text.as_str();
ui.add(
egui::TextEdit::multiline(&mut text)
.font(egui::TextStyle::Monospace)
.desired_width(f32::INFINITY)
.layouter(&mut layouter),
);
} else {
let mut job = self.0.clone();
job.wrap.max_width = ui.available_width();
let galley = ui.fonts(|f| f.layout_job(job));
let (response, painter) = ui.allocate_painter(galley.size(), egui::Sense::hover());
painter.add(egui::Shape::galley(
response.rect.min,
galley,
ui.visuals().text_color(),
));
}
let mut job = self.0.clone();
job.wrap.max_width = ui.available_width();
let galley = ui.fonts(|f| f.layout_job(job));
ui.add(egui::Label::new(galley).selectable(true));
}
}