Skip to content

Commit

Permalink
Proper UI for collapsing/uncollapsing instances
Browse files Browse the repository at this point in the history
  • Loading branch information
abey79 committed Sep 11, 2024
1 parent 327791b commit d80ef25
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1947,7 +1947,7 @@ dependencies = [
[[package]]
name = "egui_table"
version = "0.28.1"
source = "git+https://github.com/rerun-io/egui_table.git?rev=36887f386bdd5a324c0ae06f1cae5d73524c9b77#36887f386bdd5a324c0ae06f1cae5d73524c9b77"
source = "git+https://github.com/rerun-io/egui_table.git?rev=a3efe0bddfdb7c684cdaa478b5c0e979d238ea98#a3efe0bddfdb7c684cdaa478b5c0e979d238ea98"
dependencies = [
"egui",
"serde",
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_space_view_dataframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ re_viewport_blueprint.workspace = true

anyhow.workspace = true
egui_extras.workspace = true
egui_table = { git = "https://github.com/rerun-io/egui_table.git", rev = "36887f386bdd5a324c0ae06f1cae5d73524c9b77" } # PR #14 as of 2024-09-11
egui_table = { git = "https://github.com/rerun-io/egui_table.git", rev = "a3efe0bddfdb7c684cdaa478b5c0e979d238ea98" } # PR #14 as of 2024-09-11
egui.workspace = true
itertools.workspace = true
thiserror.workspace = true
110 changes: 94 additions & 16 deletions crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> {
}
};

//TODO: this is getting wild, refactor in some functions
let cell_ui = |ui: &mut egui::Ui| {
if let Some(BatchRef { batch_idx, row_idx }) =
display_data.batch_ref_from_row.get(&cell.row_nr).copied()
Expand Down Expand Up @@ -311,26 +312,47 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> {
let mut sub_cell_ui =
ui.new_child(egui::UiBuilder::new().max_rect(sub_cell_rect));

if instance_index == None && instance_count > 1 {
if sub_cell_ui
.button(format!("{instance_count} instances"))
.clicked()
{
if instance_index.is_none() && instance_count > 1 {
let cell_clicked = cell_with_hover_button_ui(
&mut sub_cell_ui,
Some(&re_ui::icons::EXPAND),
|ui| {
ui.label(format!("{instance_count} instances"));
},
);

if cell_clicked {
if instance_count == row_expansion {
self.expanded_rows.expend_row(cell.row_nr, 0);
self.expanded_rows.expand_row(cell.row_nr, 0);
} else {
self.expanded_rows.expend_row(cell.row_nr, instance_count)
self.expanded_rows.expand_row(cell.row_nr, instance_count);
}
}
} else {
column.data_ui(
self.ctx,
let has_collapse_button = if let Some(instance_index) = instance_index {
instance_index < instance_count
} else {
false
};

let cell_clicked = cell_with_hover_button_ui(
&mut sub_cell_ui,
row_id,
&latest_at_query,
row_idx,
instance_index,
has_collapse_button.then_some(&re_ui::icons::COLLAPSE),
|ui| {
column.data_ui(
self.ctx,
ui,
row_id,
&latest_at_query,
row_idx,
instance_index,
);
},
);

if cell_clicked {
self.expanded_rows.expand_row(cell.row_nr, 0);
}
}
}
} else {
Expand All @@ -346,9 +368,8 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> {
.show(ui, cell_ui);
}

fn row_top_offset(&self, ctx: &egui::Context, table_id_salt: egui::Id, row_nr: u64) -> f32 {
self.expanded_rows
.row_top_offset(ctx, table_id_salt, row_nr)
fn row_top_offset(&self, ctx: &egui::Context, table_id: egui::Id, row_nr: u64) -> f32 {
self.expanded_rows.row_top_offset(ctx, table_id, row_nr)
}

fn default_row_height(&self) -> f32 {
Expand Down Expand Up @@ -453,3 +474,60 @@ fn error_ui(ui: &mut egui::Ui, error: impl AsRef<str>) {
ui.error_label(error);
re_log::warn_once!("{error}");
}

/// Draw some cell content with an optional, right-aligned, on-hover button.
///
/// If no icon is provided, no button is shown. Returns true if the button was shown and the cell
/// was clicked.
// TODO(ab, emilk): ideally, egui::Sides should work for that, but it doesn't yet support the
// symmetric behaviour (left variable width, right fixed width).

Check warning on line 483 in crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs

View workflow job for this annotation

GitHub Actions / Checks / Spell Check

"behaviour" should be "behavior".
fn cell_with_hover_button_ui(
ui: &mut egui::Ui,
icon: Option<&'static re_ui::Icon>,
cell_content: impl FnOnce(&mut egui::Ui),
) -> bool {
let Some(icon) = icon else {
cell_content(ui);
return false;
};

let (is_hovering_cell, is_clicked) = ui.input(|i| {
(
i.pointer
.interact_pos()
.is_some_and(|pos| ui.max_rect().contains(pos)),
i.pointer.button_clicked(egui::PointerButton::Primary),
)
});

if is_hovering_cell {
let mut content_rect = ui.max_rect();
content_rect.max.x = (content_rect.max.x
- re_ui::DesignTokens::small_icon_size().x
- re_ui::DesignTokens::text_to_icon_padding())
.at_least(content_rect.min.x);

let button_rect = egui::Rect::from_x_y_ranges(
(content_rect.max.x + re_ui::DesignTokens::text_to_icon_padding())
..=ui.max_rect().max.x,
ui.max_rect().y_range(),
);

let mut content_ui = ui.new_child(egui::UiBuilder::new().max_rect(content_rect));
cell_content(&mut content_ui);

let mut button_ui = ui.new_child(egui::UiBuilder::new().max_rect(button_rect));
button_ui.visuals_mut().widgets.hovered.weak_bg_fill = egui::Color32::TRANSPARENT;
button_ui.visuals_mut().widgets.active.weak_bg_fill = egui::Color32::TRANSPARENT;
button_ui.add(egui::Button::image(
icon.as_image()
.fit_to_exact_size(re_ui::DesignTokens::small_icon_size())
.tint(button_ui.visuals().widgets.hovered.text_color()),
));

is_clicked
} else {
cell_content(ui);
false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ impl ComponentData {
) {
let data = match self {
Self::Null => {
ui.label("null");
// don't repeat the null value when expanding instances
if instance_index.is_none() {
ui.label("null");
}
return;
}
Self::ListArray(list_array) => list_array
Expand Down
16 changes: 10 additions & 6 deletions crates/viewer/re_space_view_dataframe/src/expanded_rows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,24 +75,28 @@ impl<'a> ExpandedRows<'a> {
pub(crate) fn row_top_offset(
&self,
ctx: &egui::Context,
id_salt: egui::Id,
table_id: egui::Id,
row_nr: u64,
) -> f32 {
self.cache
.expanded_rows
.range(0..row_nr)
.map(|(expanded_row_nr, expanded)| {
let how_expanded = ctx.animate_bool(id_salt.with(expanded_row_nr), *expanded > 0);
let how_expanded = ctx.animate_bool(table_id.with(expanded_row_nr), *expanded > 0);
how_expanded * *expanded as f32 * self.row_height
})
.sum::<f32>()
+ row_nr as f32 * self.row_height
}

pub(crate) fn expend_row(&mut self, row_nr: u64, additional_row_space: u64) {
self.cache
.expanded_rows
.insert(row_nr, additional_row_space);
pub(crate) fn expand_row(&mut self, row_nr: u64, additional_row_space: u64) {
if additional_row_space == 0 {
self.cache.expanded_rows.remove(&row_nr);
} else {
self.cache
.expanded_rows
.insert(row_nr, additional_row_space);
}
}

/// Return by how much row space this row is expended.
Expand Down
Binary file added crates/viewer/re_ui/data/icons/collapse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added crates/viewer/re_ui/data/icons/expand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions crates/viewer/re_ui/src/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ pub const LEFT_PANEL_TOGGLE: Icon = icon_from_path!("../data/icons/left_panel_to
pub const MINIMIZE: Icon = icon_from_path!("../data/icons/minimize.png");
pub const MAXIMIZE: Icon = icon_from_path!("../data/icons/maximize.png");

pub const COLLAPSE: Icon = icon_from_path!("../data/icons/collapse.png");
pub const EXPAND: Icon = icon_from_path!("../data/icons/expand.png");

pub const VISIBLE: Icon = icon_from_path!("../data/icons/visible.png");
pub const INVISIBLE: Icon = icon_from_path!("../data/icons/invisible.png");

Expand Down

0 comments on commit d80ef25

Please sign in to comment.