Skip to content

Commit ff248a4

Browse files
authored
Improve error message style slightly (#8092)
### What Before, the error style was inconsistent and ugly: ![image](https://github.com/user-attachments/assets/8ebb82ae-8e40-441e-ae1f-553a7be95028) Now it is consistent and ever so slightly less ugly: ![image](https://github.com/user-attachments/assets/949d7efa-decf-4629-b28c-89d9b3cc756c) We can do better though, in * #8091 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/8092?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/8092?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/8092) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`.
1 parent baba6a5 commit ff248a4

File tree

13 files changed

+65
-34
lines changed

13 files changed

+65
-34
lines changed

crates/viewer/re_chunk_store_ui/src/arrow_ui.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,7 @@ pub(crate) fn arrow_ui(ui: &mut egui::Ui, array: &dyn arrow2::array::Array) {
4343
let mut string = String::new();
4444
match display(&mut string, 0) {
4545
Ok(_) => ui.monospace(&string),
46-
Err(err) => ui.error_with_details_on_hover("error").on_hover_ui(|ui| {
47-
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Wrap);
48-
ui.error_with_details_on_hover(&format!("{err}"));
49-
}),
46+
Err(err) => ui.error_with_details_on_hover(&err.to_string()),
5047
};
5148
return;
5249
} else {

crates/viewer/re_chunk_store_ui/src/chunk_ui.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,7 @@ impl ChunkUi {
146146
crate::arrow_ui::arrow_ui(ui, &*data);
147147
}
148148
Some(Err(err)) => {
149-
ui.error_with_details_on_hover("error").on_hover_ui(|ui| {
150-
ui.label(format!("{err}"));
151-
});
149+
ui.error_with_details_on_hover(&err.to_string());
152150
}
153151
None => {
154152
ui.weak("-");

crates/viewer/re_component_ui/src/datatype_uis/singleline_string.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub fn display_text_ui(
8989
let text = match Text::from_arrow(data) {
9090
Ok(text) => text.first().cloned(),
9191
Err(err) => {
92-
ui.error_with_details_on_hover("failed to deserialize")
92+
ui.error_label("Failed to deserialize")
9393
.on_hover_text(err.to_string());
9494
return;
9595
}
@@ -118,7 +118,7 @@ pub fn display_name_ui(
118118
let name = match Name::from_arrow(data) {
119119
Ok(name) => name.first().cloned(),
120120
Err(err) => {
121-
ui.error_with_details_on_hover("failed to deserialize")
121+
ui.error_label("Failed to deserialize")
122122
.on_hover_text(err.to_string());
123123
return;
124124
}

crates/viewer/re_data_ui/src/video.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ pub fn show_video_blob_info(
116116
// See also `MediaTypeIsNotAVideo` case above.
117117
}
118118
Err(err) => {
119+
let error_message = format!("Failed to load video: {err}");
119120
if ui_layout.is_single_line() {
120-
ui.error_with_details_on_hover(&format!("Failed to load video: {err}"));
121+
ui.error_with_details_on_hover(&error_message);
121122
} else {
122-
ui.error_label(&format!("Failed to load video: {err}"));
123+
ui.error_label(&error_message);
123124
}
124125
}
125126
}

crates/viewer/re_selection_panel/src/visualizer_ui.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn visualizer_ui(
2626
.lookup_result_by_path(entity_path)
2727
.cloned()
2828
else {
29-
ui.error_with_details_on_hover("Entity not found in view.");
29+
ui.error_label("Entity not found in view");
3030
return;
3131
};
3232
let active_visualizers: Vec<_> = data_result.visualizers.iter().sorted().copied().collect();

crates/viewer/re_space_view_dataframe/src/display_record_batch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ impl DisplayColumn {
254254
ui.label(timeline.typ().format(timestamp, ctx.app_options.time_zone));
255255
}
256256
Err(err) => {
257-
ui.error_with_details_on_hover(&format!("{err}"));
257+
ui.error_with_details_on_hover(&err.to_string());
258258
}
259259
}
260260
} else {

crates/viewer/re_space_view_spatial/src/ui.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use re_types::{
77
archetypes::Pinhole, blueprint::components::VisualBounds2D, components::ViewCoordinates,
88
image::ImageKind,
99
};
10-
use re_ui::UiExt as _;
10+
use re_ui::{ContextExt as _, UiExt as _};
1111
use re_viewer_context::{
1212
HoverHighlight, SelectionHighlight, SpaceViewHighlights, SpaceViewState, ViewerContext,
1313
};
@@ -18,7 +18,7 @@ use crate::{
1818
picking::{PickableUiRect, PickingResult},
1919
scene_bounding_boxes::SceneBoundingBoxes,
2020
view_kind::SpatialSpaceViewKind,
21-
visualizers::{SpatialViewVisualizerData, UiLabel, UiLabelTarget},
21+
visualizers::{SpatialViewVisualizerData, UiLabel, UiLabelStyle, UiLabelTarget},
2222
};
2323

2424
use super::{eye::Eye, ui_3d::View3DState};
@@ -214,13 +214,19 @@ pub fn create_labels(
214214
};
215215

216216
let font_id = egui::TextStyle::Body.resolve(parent_ui.style());
217+
let format = match label.style {
218+
UiLabelStyle::Color(color) => egui::TextFormat::simple(font_id, color),
219+
UiLabelStyle::Error => parent_ui.ctx().error_text_format(),
220+
};
221+
let text_color = format.color;
222+
217223
let galley = parent_ui.fonts(|fonts| {
218224
fonts.layout_job({
219225
egui::text::LayoutJob {
220226
sections: vec![egui::text::LayoutSection {
221227
leading_space: 0.0,
222228
byte_range: 0..label.text.len(),
223-
format: egui::TextFormat::simple(font_id, label.color),
229+
format,
224230
}],
225231
text: label.text.clone(),
226232
wrap: TextWrapping {
@@ -241,9 +247,9 @@ pub fn create_labels(
241247
let highlight = highlights
242248
.entity_highlight(label.labeled_instance.entity_path_hash)
243249
.index_highlight(label.labeled_instance.instance);
244-
let fill_color = match highlight.hover {
250+
let background_color = match highlight.hover {
245251
HoverHighlight::None => match highlight.selection {
246-
SelectionHighlight::None => parent_ui.style().visuals.widgets.inactive.bg_fill,
252+
SelectionHighlight::None => parent_ui.style().visuals.panel_fill,
247253
SelectionHighlight::SiblingSelection => {
248254
parent_ui.style().visuals.widgets.active.bg_fill
249255
}
@@ -252,11 +258,11 @@ pub fn create_labels(
252258
HoverHighlight::Hovered => parent_ui.style().visuals.widgets.hovered.bg_fill,
253259
};
254260

255-
label_shapes.push(egui::Shape::rect_filled(bg_rect, 3.0, fill_color));
261+
label_shapes.push(egui::Shape::rect_filled(bg_rect, 3.0, background_color));
256262
label_shapes.push(egui::Shape::galley(
257263
text_rect.center_top(),
258264
galley,
259-
label.color,
265+
text_color,
260266
));
261267

262268
ui_rects.push(PickableUiRect {

crates/viewer/re_space_view_spatial/src/visualizers/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub use depth_images::DepthImageVisualizer;
2626
pub use transform3d_arrows::{add_axis_arrows, AxisLengthDetector, Transform3DArrowsVisualizer};
2727
pub use utilities::{
2828
entity_iterator, process_labels_3d, textured_rect_from_image, SpatialViewVisualizerData,
29-
UiLabel, UiLabelTarget,
29+
UiLabel, UiLabelStyle, UiLabelTarget,
3030
};
3131

3232
/// Shows a loading animation in a spatial view.

crates/viewer/re_space_view_spatial/src/visualizers/utilities/labels.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,25 @@ pub enum UiLabelTarget {
2525
Position3D(glam::Vec3),
2626
}
2727

28+
#[derive(Clone)]
29+
pub enum UiLabelStyle {
30+
Color(egui::Color32),
31+
32+
/// Style it like an error message
33+
Error,
34+
}
35+
36+
impl From<egui::Color32> for UiLabelStyle {
37+
fn from(color: egui::Color32) -> Self {
38+
Self::Color(color)
39+
}
40+
}
41+
2842
#[derive(Clone)]
2943
pub struct UiLabel {
3044
pub text: String,
31-
pub color: egui::Color32,
45+
46+
pub style: UiLabelStyle,
3247

3348
/// The shape/position being labeled.
3449
pub target: UiLabelTarget,
@@ -181,7 +196,7 @@ pub fn process_labels<'a, P: 'a>(
181196
.filter_map(move |(i, (position, label, color))| {
182197
label.map(|label| UiLabel {
183198
text: label,
184-
color: *color,
199+
style: (*color).into(),
185200
target: target_from_position(position),
186201
labeled_instance: InstancePathHash::instance(
187202
entity_path,

crates/viewer/re_space_view_spatial/src/visualizers/utilities/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod textured_rect;
66

77
pub use labels::{
88
process_labels, process_labels_2d, process_labels_3d, show_labels_fallback, LabeledBatch,
9-
UiLabel, UiLabelTarget,
9+
UiLabel, UiLabelStyle, UiLabelTarget,
1010
};
1111
pub use proc_mesh_vis::{ProcMeshBatch, ProcMeshDrawableBuilder};
1212
pub use spatial_view_visualizer::SpatialViewVisualizerData;

crates/viewer/re_space_view_spatial/src/visualizers/videos.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ use crate::{
3030
};
3131

3232
use super::{
33-
entity_iterator::process_archetype, SpatialViewVisualizerData, UiLabel, UiLabelTarget,
33+
entity_iterator::process_archetype, SpatialViewVisualizerData, UiLabel, UiLabelStyle,
34+
UiLabelTarget,
3435
};
3536

3637
pub struct VideoFrameReferenceVisualizer {
@@ -365,7 +366,7 @@ impl VideoFrameReferenceVisualizer {
365366
);
366367
self.data.ui_labels.push(UiLabel {
367368
text: error_string,
368-
color: egui::Color32::LIGHT_RED,
369+
style: UiLabelStyle::Error,
369370
target: UiLabelTarget::Rect(label_target_rect),
370371
labeled_instance: re_entity_db::InstancePathHash::entity_all(entity_path),
371372
});

crates/viewer/re_ui/src/context_ext.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ use crate::{DesignTokens, TopBarStyle};
99
pub trait ContextExt {
1010
fn ctx(&self) -> &egui::Context;
1111

12+
// -----------------------------------------------------
13+
// Style-related stuff.
14+
// We could have this on a `StyleExt` trait, but we prefer to have it here on `Context`
15+
// so that it is the same style everywhere (instead of being specific to the parent `ui.style`).
16+
1217
/// Text format used for regular body.
1318
fn text_format_body(&self) -> egui::TextFormat {
1419
egui::TextFormat::simple(
@@ -56,17 +61,25 @@ pub trait ContextExt {
5661
#[must_use]
5762
fn warning_text(&self, text: impl Into<String>) -> egui::RichText {
5863
let style = self.ctx().style();
59-
egui::RichText::new(text)
60-
.italics()
61-
.color(style.visuals.warn_fg_color)
64+
egui::RichText::new(text).color(style.visuals.warn_fg_color)
6265
}
6366

67+
/// NOTE: duplicated in [`Self::error_text_format`]
6468
#[must_use]
6569
fn error_text(&self, text: impl Into<String>) -> egui::RichText {
6670
let style = self.ctx().style();
67-
egui::RichText::new(text)
68-
.italics()
69-
.color(style.visuals.error_fg_color)
71+
egui::RichText::new(text).color(style.visuals.error_fg_color)
72+
}
73+
74+
/// NOTE: duplicated in [`Self::error_text`]
75+
fn error_text_format(&self) -> egui::TextFormat {
76+
let style = self.ctx().style();
77+
let font_id = egui::TextStyle::Body.resolve(&style);
78+
egui::TextFormat {
79+
font_id,
80+
color: style.visuals.error_fg_color,
81+
..Default::default()
82+
}
7083
}
7184

7285
fn top_bar_style(&self, style_like_web: bool) -> TopBarStyle {

crates/viewer/re_viewer_context/src/selection_state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub enum ItemSpaceContext {
3838
}
3939

4040
/// Selection highlight, sorted from weakest to strongest.
41-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
41+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
4242
pub enum SelectionHighlight {
4343
/// No selection highlight at all.
4444
#[default]
@@ -53,7 +53,7 @@ pub enum SelectionHighlight {
5353
}
5454

5555
/// Hover highlight, sorted from weakest to strongest.
56-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
56+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
5757
pub enum HoverHighlight {
5858
/// No hover highlight.
5959
#[default]

0 commit comments

Comments
 (0)