Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow TextLog body to display as immutable TextEdit rather than Label #4716

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 57 additions & 12 deletions crates/re_space_view_text_log/src/space_view_class.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use egui::Widget;
use re_entity_db::EntityProperties;
use std::collections::BTreeMap;

Expand All @@ -24,6 +25,8 @@ pub struct TextSpaceViewState {
pub filters: ViewTextFilters,

monospace: bool,

selectable: bool,
}

impl SpaceViewState for TextSpaceViewState {
Expand Down Expand Up @@ -125,6 +128,7 @@ impl SpaceViewClass for TextSpaceView {
.radio_value(ui, &mut state.monospace, false, "Proportional");
ctx.re_ui
.radio_value(ui, &mut state.monospace, true, "Monospace");
ctx.re_ui.checkbox(ui, &mut state.selectable, "Selectable");
});
ui.end_row();
});
Expand Down Expand Up @@ -402,16 +406,60 @@ fn table_ui(

// body
row.col(|ui| {
let mut text = egui::RichText::new(entry.body.as_str());
if state.selectable {
// Use a &str with TextEdit so body is selectable but immutable.
let entry_text_rows = entry.num_body_lines;
let mut binding = entry.body.as_str();
let mut text = egui::TextEdit::multiline(&mut binding)
.min_size([0.0, 0.0].into())
.desired_rows(entry_text_rows)
.desired_width(f32::INFINITY);
// Font information for LayoutJob, based on default_layouter in `egui::TextEdit::show_contents`
let font_id = if state.monospace {
egui::TextStyle::Monospace.into()
} else {
egui::FontSelection::default()
}
.resolve(ui.style());
let text_color = if let Some(color) = entry.color {
color.into()
} else {
// TODO(lupickup): Understand why TextEdit text color is white instead of gray like the RichText version.
ui.visuals()
.override_text_color
.unwrap_or_else(|| ui.visuals().widgets.inactive.text_color())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inactive.text_color is the text color of an interactive widget (that is not currently being interacted with). That's why you get white text: https://docs.rs/egui/latest/egui/style/struct.Widgets.html#structfield.inactive

Use noninteractive instead (we don't count text selection as interaction)

};
let mut layouter = |ui: &egui::Ui, string: &str, wrap_width: f32| {
let mut layout_job = egui::text::LayoutJob::simple(
string.to_owned(),
font_id.clone(),
text_color,
wrap_width,
);
layout_job.wrap.max_rows = entry_text_rows;
// Fill to end of body column instead of choosing a full "word" to ellide
layout_job.wrap.break_anywhere = true;
ui.fonts(|f| f.layout_job(layout_job))
Comment on lines +433 to +442
Copy link
Member

@emilk emilk Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest you compute this Galley once and copy into this layouter. The string you know (and is fixed), and wrap_width should be f32::INFINITY (no wrapping).

By computing the galley up-front you can pass the size of it to TextEdit::min_size.

};
text = text.layouter(&mut layouter);

let response = text.ui(ui);
if response.hovered() {
response.on_hover_text(entry.body.as_str());
}
} else {
let mut text = egui::RichText::new(entry.body.as_str());

if state.monospace {
text = text.monospace();
}
if let Some(color) = entry.color {
text = text.color(color);
}
if state.monospace {
text = text.monospace();
}

ui.label(text);
if let Some(color) = entry.color {
text = text.color(color);
}

ui.label(text);
}
});
});
});
Expand All @@ -428,8 +476,5 @@ fn table_ui(
}

fn calc_row_height(entry: &Entry) -> f32 {
// Simple, fast, ugly, and functional
let num_newlines = entry.body.bytes().filter(|&c| c == b'\n').count();
let num_rows = 1 + num_newlines;
num_rows as f32 * re_ui::ReUi::table_line_height()
entry.num_body_lines as f32 * re_ui::ReUi::table_line_height()
}
5 changes: 5 additions & 0 deletions crates/re_space_view_text_log/src/visualizer_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub struct Entry {

pub body: Text,

pub num_body_lines: usize,

pub level: Option<TextLogLevel>,
}

Expand Down Expand Up @@ -78,12 +80,15 @@ impl VisualizerSystem for TextLogSystem {
let colors = arch_view.iter_optional_component::<Color>()?;

for (body, level, color) in itertools::izip!(bodies, levels, colors) {
// Simple, fast, ugly, and functional
let num_body_lines = body.bytes().filter(|&c| c == b'\n').count() + 1;
self.entries.push(Entry {
row_id: arch_view.primary_row_id(),
entity_path: data_result.entity_path.clone(),
time: time.map(|time| time.as_i64()),
color,
body,
num_body_lines,
level,
});
}
Expand Down
Loading