Skip to content

Commit 2b188cc

Browse files
committed
Add DataFusionTableWidget::column_visibility and use it to improve visibility defaults for the partition table
Also fixes the column ordering, which was wrongly based on their id.
1 parent 278e085 commit 2b188cc

File tree

7 files changed

+75
-24
lines changed

7 files changed

+75
-24
lines changed

crates/store/re_log_types/src/path/entity_path_part.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use re_string_interner::InternedString;
33
use crate::PathParseError;
44

55
pub const RESERVED_NAMESPACE_PREFIX: &str = "__";
6-
const PROPERTIES_PART: &str = "__properties";
6+
pub const PROPERTIES_PART: &str = "__properties";
77
const RECORDING_PART: &str = "recording";
88

99
/// The different parts that make up an [`EntityPath`][crate::EntityPath].

crates/store/re_log_types/src/path/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub use entity_path_filter::{
1818
EntityPathFilter, EntityPathFilterError, EntityPathRule, EntityPathSubs,
1919
ResolvedEntityPathFilter, ResolvedEntityPathRule, RuleEffect,
2020
};
21-
pub use entity_path_part::EntityPathPart;
21+
pub use entity_path_part::{EntityPathPart, PROPERTIES_PART};
2222
pub use parse_path::{tokenize_by, PathParseError};
2323

2424
// ----------------------------------------------------------------------------

crates/store/re_sorbet/src/column_descriptor_ref.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use re_log_types::EntityPath;
2+
13
use crate::{
24
BatchType, ColumnDescriptor, ComponentColumnDescriptor, IndexColumnDescriptor,
35
RowIdColumnDescriptor,
@@ -31,6 +33,13 @@ impl ColumnDescriptorRef<'_> {
3133
Self::Component(descr) => descr.component_name.short_name(),
3234
}
3335
}
36+
37+
pub fn entity_path(&self) -> Option<EntityPath> {
38+
match self {
39+
Self::RowId(_) | Self::Time(_) => None,
40+
Self::Component(descr) => Some(descr.entity_path.clone()),
41+
}
42+
}
3443
}
3544

3645
impl<'a> From<&'a ColumnDescriptor> for ColumnDescriptorRef<'a> {

crates/viewer/re_dataframe_ui/src/datafusion_table_widget.rs

+38-18
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ impl<'a> Columns<'a> {
4141
}
4242

4343
impl Columns<'_> {
44-
fn descriptors(&self) -> impl Iterator<Item = &ColumnDescriptorRef<'_>> {
45-
self.inner.values().map(|(_, desc)| desc)
46-
}
47-
4844
fn index_from_id(&self, id: Option<egui::Id>) -> Option<usize> {
4945
id.and_then(|id| self.inner.get(&id).map(|(index, _)| *index))
5046
}
@@ -57,7 +53,9 @@ impl Columns<'_> {
5753
}
5854
}
5955

60-
type ColumnRenamerFn<'a> = Option<Box<dyn Fn(&ColumnDescriptorRef<'_>) -> String + 'a>>;
56+
pub type ColumnNameFn<'a> = Option<Box<dyn Fn(&ColumnDescriptorRef<'_>) -> String + 'a>>;
57+
58+
pub type ColumnVisibilityFn<'a> = Option<Box<dyn Fn(&ColumnDescriptorRef<'_>) -> bool + 'a>>;
6159

6260
pub struct DataFusionTableWidget<'a> {
6361
session_ctx: Arc<SessionContext>,
@@ -73,7 +71,10 @@ pub struct DataFusionTableWidget<'a> {
7371
/// Closure used to determine the display name of the column.
7472
///
7573
/// Defaults to using [`ColumnDescriptorRef::name`].
76-
column_renamer: ColumnRenamerFn<'a>,
74+
column_name_fn: ColumnNameFn<'a>,
75+
76+
/// Closure used to determine the visibility of the column
77+
column_visibility_fn: ColumnVisibilityFn<'a>,
7778

7879
/// The blueprint used the first time the table is queried.
7980
initial_blueprint: TableBlueprint,
@@ -99,7 +100,8 @@ impl<'a> DataFusionTableWidget<'a> {
99100

100101
title: None,
101102
title_button: None,
102-
column_renamer: None,
103+
column_name_fn: None,
104+
column_visibility_fn: None,
103105
initial_blueprint: Default::default(),
104106
}
105107
}
@@ -116,11 +118,22 @@ impl<'a> DataFusionTableWidget<'a> {
116118
self
117119
}
118120

119-
pub fn column_renamer(
121+
pub fn column_name(
120122
mut self,
121-
renamer: impl Fn(&ColumnDescriptorRef<'_>) -> String + 'a,
123+
column_name_fn: impl Fn(&ColumnDescriptorRef<'_>) -> String + 'a,
122124
) -> Self {
123-
self.column_renamer = Some(Box::new(renamer));
125+
self.column_name_fn = Some(Box::new(column_name_fn));
126+
127+
self
128+
}
129+
130+
// TODO(ab): this should best be expressed as part of the `TableBlueprint`, but we need better
131+
// column selector first.
132+
pub fn column_visibility(
133+
mut self,
134+
column_visibility_fn: impl Fn(&ColumnDescriptorRef<'_>) -> bool + 'a,
135+
) -> Self {
136+
self.column_visibility_fn = Some(Box::new(column_visibility_fn));
124137

125138
self
126139
}
@@ -153,7 +166,8 @@ impl<'a> DataFusionTableWidget<'a> {
153166
table_ref,
154167
title,
155168
title_button,
156-
column_renamer,
169+
column_name_fn,
170+
column_visibility_fn,
157171
initial_blueprint,
158172
} = self;
159173

@@ -256,14 +270,20 @@ impl<'a> DataFusionTableWidget<'a> {
256270
let mut table_config = TableConfig::get_with_columns(
257271
ui.ctx(),
258272
id,
259-
columns.descriptors().map(|c| {
260-
let name = if let Some(renamer) = &column_renamer {
261-
renamer(c)
273+
sorbet_schema.columns.descriptors().map(|c| {
274+
let name = if let Some(column_name_fn) = &column_name_fn {
275+
column_name_fn(&c)
262276
} else {
263277
c.name(BatchType::Dataframe)
264278
};
265279

266-
ColumnConfig::new(Id::new(c), name)
280+
let visible = if let Some(column_visibility_fn) = &column_visibility_fn {
281+
column_visibility_fn(&c)
282+
} else {
283+
true
284+
};
285+
286+
ColumnConfig::new_with_visible(Id::new(c), name, visible)
267287
}),
268288
);
269289

@@ -280,7 +300,7 @@ impl<'a> DataFusionTableWidget<'a> {
280300
fields,
281301
display_record_batches: &display_record_batches,
282302
columns: &columns,
283-
column_renamer: &column_renamer,
303+
column_name_fn: &column_name_fn,
284304
blueprint: table_state.blueprint(),
285305
new_blueprint: &mut new_blueprint,
286306
table_config,
@@ -348,7 +368,7 @@ struct DataFusionTableDelegate<'a> {
348368
fields: &'a Fields,
349369
display_record_batches: &'a Vec<DisplayRecordBatch>,
350370
columns: &'a Columns<'a>,
351-
column_renamer: &'a ColumnRenamerFn<'a>,
371+
column_name_fn: &'a ColumnNameFn<'a>,
352372
blueprint: &'a TableBlueprint,
353373
new_blueprint: &'a mut TableBlueprint,
354374
table_config: TableConfig,
@@ -362,7 +382,7 @@ impl egui_table::TableDelegate for DataFusionTableDelegate<'_> {
362382

363383
if let Some((index, desc)) = self.columns.index_and_descriptor_from_id(id) {
364384
let column_name = self.fields[index].name();
365-
let name = if let Some(renamer) = self.column_renamer {
385+
let name = if let Some(renamer) = self.column_name_fn {
366386
renamer(desc)
367387
} else {
368388
desc.name(BatchType::Dataframe)

crates/viewer/re_dataframe_ui/src/table_utils.rs

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ impl ColumnConfig {
8282
visible: true,
8383
}
8484
}
85+
86+
pub fn new_with_visible(id: Id, name: String, visible: bool) -> Self {
87+
Self { id, name, visible }
88+
}
8589
}
8690

8791
// TODO(lucasmerlin): It would be nice to have this in egui_table, so egui_table could do the work

crates/viewer/re_redap_browser/src/servers.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use std::sync::mpsc::{Receiver, Sender};
44
use egui::{Frame, Margin, RichText};
55

66
use re_log_types::EntryId;
7-
use re_protos::manifest_registry::v1alpha1::DATASET_MANIFEST_ID_FIELD_NAME;
7+
use re_protos::manifest_registry::v1alpha1::{
8+
DATASET_MANIFEST_ID_FIELD_NAME, DATASET_MANIFEST_REGISTRATION_TIME_FIELD_NAME,
9+
};
810
use re_ui::list_item::ItemActionButton;
911
use re_ui::{icons, list_item, UiExt as _};
1012
use re_viewer_context::{
@@ -115,6 +117,8 @@ impl Server {
115117
ui: &mut egui::Ui,
116118
dataset: &Dataset,
117119
) {
120+
const RECORDING_LINK_FIELD_NAME: &str = "recording link";
121+
118122
re_dataframe_ui::DataFusionTableWidget::new(
119123
self.tables_session_ctx.ctx.clone(),
120124
dataset.name(),
@@ -125,16 +129,30 @@ impl Server {
125129
.command_sender
126130
.send(Command::RefreshCollection(self.origin.clone()));
127131
}))
128-
.column_renamer(|desc| {
132+
.column_name(|desc| {
129133
//TODO(ab): with this strategy, we do not display relevant entity path if any.
130134
let name = desc.short_name();
131135

132136
name.strip_prefix("rerun_")
133137
.unwrap_or(name)
134138
.replace('_', " ")
135139
})
140+
.column_visibility(|desc| {
141+
if desc.entity_path().is_some_and(|entity_path| {
142+
entity_path.starts_with(&re_log_types::PROPERTIES_PART.into())
143+
}) {
144+
true
145+
} else {
146+
matches!(
147+
desc.short_name(),
148+
RECORDING_LINK_FIELD_NAME
149+
| DATASET_MANIFEST_ID_FIELD_NAME
150+
| DATASET_MANIFEST_REGISTRATION_TIME_FIELD_NAME
151+
)
152+
}
153+
})
136154
.generate_partition_links(
137-
"recording link",
155+
RECORDING_LINK_FIELD_NAME,
138156
DATASET_MANIFEST_ID_FIELD_NAME,
139157
self.origin.clone(),
140158
dataset.id(),

crates/viewer/re_viewer/src/app_state.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ fn table_ui(
745745
) {
746746
re_dataframe_ui::DataFusionTableWidget::new(store.session_context(), TableStore::TABLE_NAME)
747747
.title(table_id.as_str())
748-
.column_renamer(|desc| match desc {
748+
.column_name(|desc| match desc {
749749
ColumnDescriptorRef::RowId(_) | ColumnDescriptorRef::Time(_) => {
750750
desc.short_name().to_owned()
751751
}

0 commit comments

Comments
 (0)