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

Rewrite the ui.large_collapsing_header into re_ui::SectionCollapsingHeader using re_ui::ListItem #6657

Merged
merged 6 commits into from
Jun 27, 2024
Merged
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
2 changes: 2 additions & 0 deletions crates/re_blueprint_tree/src/blueprint_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ impl BlueprintTree {
let list_item::ShowCollapsingResponse {
item_response: response,
body_response,
..
} = ui
.list_item()
.selected(ctx.selection().contains_item(&item))
Expand Down Expand Up @@ -363,6 +364,7 @@ impl BlueprintTree {
let list_item::ShowCollapsingResponse {
item_response: mut response,
body_response,
..
} = ui
.list_item()
.selected(ctx.selection().contains_item(&item))
Expand Down
6 changes: 4 additions & 2 deletions crates/re_selection_panel/src/defaults_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ pub fn view_components_defaults_section_ui(
db,
);
};
ui.large_collapsing_header_with_button("Component defaults", true, body, add_button);
ui.section_collapsing_header("Component defaults")
.button(add_button)
.show(ui, body);
}

fn active_default_ui(
Expand All @@ -83,7 +85,7 @@ fn active_default_ui(
ui.spacing_mut().item_spacing.y = 0.0;

if sorted_overrides.is_empty() {
ui.list_item_flat_noninteractive(LabelContent::new("(none)").weak(true));
ui.list_item_flat_noninteractive(LabelContent::new("none").weak(true).italics(true));
}

for component_name in sorted_overrides {
Expand Down
160 changes: 79 additions & 81 deletions crates/re_selection_panel/src/selection_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ impl SelectionPanel {
}

if let Some(data_ui_item) = data_section_ui(item) {
ui.large_collapsing_header("Data", true, |ui| {
ui.section_collapsing_header("Data").show(ui, |ui| {
// TODO(#6075): Because `list_item_scope` changes it. Temporary until everything is `ListItem`.
ui.spacing_mut().item_spacing.y = ui.ctx().style().spacing.item_spacing.y;

Expand Down Expand Up @@ -319,74 +319,6 @@ impl SelectionPanel {
view_id: &SpaceViewId,
view_states: &mut ViewStates,
) {
clone_space_view_button_ui(ctx, ui, blueprint, *view_id);

if let Some(view) = blueprint.view(view_id) {
ui.large_collapsing_header("Entity path filter", true, |ui| {
// TODO(#6075): Because `list_item_scope` changes it. Temporary until everything is `ListItem`.
ui.spacing_mut().item_spacing.y = ui.ctx().style().spacing.item_spacing.y;

if let Some(new_entity_path_filter) = self.entity_path_filter_ui(
ctx,
ui,
*view_id,
&view.contents.entity_path_filter,
&view.space_origin,
) {
view.contents
.set_entity_path_filter(ctx, &new_entity_path_filter);
}
})
.header_response
.on_hover_text(
"The entity path query consists of a list of include/exclude rules \
that determines what entities are part of this view",
);
}

if let Some(view) = blueprint.view(view_id) {
let view_class = view.class(ctx.space_view_class_registry);
let view_state = view_states.get_mut_or_create(view.id, view_class);

ui.large_collapsing_header("View properties", true, |ui| {
// TODO(#6075): Because `list_item_scope` changes it. Temporary until everything is `ListItem`.
ui.spacing_mut().item_spacing.y = ui.ctx().style().spacing.item_spacing.y;

let cursor = ui.cursor();

if let Err(err) =
view_class.selection_ui(ctx, ui, view_state, &view.space_origin, view.id)
{
re_log::error_once!(
"Error in view selection UI (class: {}, display name: {}): {err}",
view.class_identifier(),
view_class.display_name(),
);
}

if cursor == ui.cursor() {
ui.weak("(none)");
}
});

let view_ctx = view.bundle_context_with_state(ctx, view_state);
view_components_defaults_section_ui(&view_ctx, ui, view);
}

if let Some(view) = blueprint.view(view_id) {
visible_time_range_ui_for_view(ctx, ui, view);
}
}

/// Returns a new filter when the editing is done, and there has been a change.
fn entity_path_filter_ui(
&mut self,
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
view_id: SpaceViewId,
filter: &EntityPathFilter,
origin: &EntityPath,
) -> Option<EntityPathFilter> {
fn entity_path_filter_help_ui(ui: &mut egui::Ui) {
let markdown = r#"
# Entity path query syntax
Expand Down Expand Up @@ -428,6 +360,77 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included.
ui.markdown_ui(egui::Id::new("entity_path_filter_help_ui"), markdown);
}

clone_space_view_button_ui(ctx, ui, blueprint, *view_id);

if let Some(view) = blueprint.view(view_id) {
ui.section_collapsing_header("Entity path filter")
.help_ui(entity_path_filter_help_ui)
.show(ui, |ui| {
// TODO(#6075): Because `list_item_scope` changes it. Temporary until everything is `ListItem`.
ui.spacing_mut().item_spacing.y = ui.ctx().style().spacing.item_spacing.y;

if let Some(new_entity_path_filter) = self.entity_path_filter_ui(
ctx,
ui,
*view_id,
&view.contents.entity_path_filter,
&view.space_origin,
) {
view.contents
.set_entity_path_filter(ctx, &new_entity_path_filter);
}
})
.header_response
.on_hover_text(
"The entity path query consists of a list of include/exclude rules \
that determines what entities are part of this view",
);
}

if let Some(view) = blueprint.view(view_id) {
let view_class = view.class(ctx.space_view_class_registry);
let view_state = view_states.get_mut_or_create(view.id, view_class);

ui.section_collapsing_header("View properties")
.show(ui, |ui| {
// TODO(#6075): Because `list_item_scope` changes it. Temporary until everything is `ListItem`.
ui.spacing_mut().item_spacing.y = ui.ctx().style().spacing.item_spacing.y;

let cursor = ui.cursor();

if let Err(err) =
view_class.selection_ui(ctx, ui, view_state, &view.space_origin, view.id)
{
re_log::error_once!(
"Error in view selection UI (class: {}, display name: {}): {err}",
view.class_identifier(),
view_class.display_name(),
);
}

if cursor == ui.cursor() {
ui.weak("(none)");
}
});

let view_ctx = view.bundle_context_with_state(ctx, view_state);
view_components_defaults_section_ui(&view_ctx, ui, view);
}

if let Some(view) = blueprint.view(view_id) {
visible_time_range_ui_for_view(ctx, ui, view);
}
}

/// Returns a new filter when the editing is done, and there has been a change.
fn entity_path_filter_ui(
&mut self,
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
view_id: SpaceViewId,
filter: &EntityPathFilter,
origin: &EntityPath,
) -> Option<EntityPathFilter> {
fn syntax_highlight_entity_path_filter(
style: &egui::Style,
mut string: &str,
Expand Down Expand Up @@ -506,18 +509,13 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included.
));
}

ui.horizontal(|ui| {
ui.help_hover_button()
.on_hover_ui(entity_path_filter_help_ui);

if ui
.button("Edit")
.on_hover_text("Modify the entity query using the editor")
.clicked()
{
self.space_view_entity_modal.open(view_id);
}
});
if ui
.button("Edit")
.on_hover_text("Modify the entity query using the editor")
.clicked()
{
self.space_view_entity_modal.open(view_id);
}

// Apply the edit.
let new_filter = EntityPathFilter::parse_forgiving(&filter_string, &Default::default());
Expand Down
3 changes: 1 addition & 2 deletions crates/re_selection_panel/src/space_view_space_origin_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ fn space_view_space_origin_widget_editing_ui(

let excluded_count = space_view_suggestions.len() - filtered_space_view_suggestions.len();
if excluded_count > 0 {
ui.list_item().interactive(false).show_flat(
ui,
ui.list_item_flat_noninteractive(
list_item::LabelContent::new(format!("{excluded_count} hidden suggestions"))
.weak(true)
.italics(true),
Expand Down
7 changes: 4 additions & 3 deletions crates/re_selection_panel/src/visible_time_range_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,10 @@ fn query_range_ui(

let mut interacting_with_controls = false;

let default_open = false;
let collapsing_response =
ui.large_collapsing_header("Visible time range", default_open, |ui| {
let collapsing_response = ui
.section_collapsing_header("Visible time range")
.default_open(false)
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.re_radio_value(has_individual_time_range, false, "Default")
.on_hover_text(if is_space_view {
Expand Down
43 changes: 24 additions & 19 deletions crates/re_selection_panel/src/visualizer_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,24 @@ pub fn visualizer_ui(
&active_visualizers,
);

ui.large_collapsing_header_with_button(
"Visualizers",
true,
|ui| {
let button = re_ui::HeaderMenuButton::new(&re_ui::icons::ADD, |ui| {
menu_add_new_visualizer(
ctx,
ui,
&data_result,
&active_visualizers,
&available_inactive_visualizers,
);
})
.enabled(!available_inactive_visualizers.is_empty())
.hover_text("Add additional visualizers")
.disabled_hover_text("No additional visualizers available");

ui.section_collapsing_header("Visualizers")
.button(button)
.show(ui, |ui| {
visualizer_ui_impl(ctx, ui, &data_result, &active_visualizers);
},
re_ui::HeaderMenuButton::new(&re_ui::icons::ADD, |ui| {
menu_add_new_visualizer(
ctx,
ui,
&data_result,
&active_visualizers,
&available_inactive_visualizers,
);
})
.enabled(!available_inactive_visualizers.is_empty())
.hover_text("Add additional visualizers")
.disabled_hover_text("No additional visualizers available"),
);
});
}

pub fn visualizer_ui_impl(
Expand Down Expand Up @@ -88,7 +87,13 @@ pub fn visualizer_ui_impl(
};

list_item::list_item_scope(ui, "visualizers", |ui| {
ui.spacing_mut().item_spacing.y = 0.0;
if active_visualizers.is_empty() {
ui.list_item_flat_noninteractive(
list_item::LabelContent::new("none")
.weak(true)
.italics(true),
);
}

for &visualizer_id in active_visualizers {
let default_open = true;
Expand Down
1 change: 1 addition & 0 deletions crates/re_time_panel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ impl TimePanel {
let list_item::ShowCollapsingResponse {
item_response: response,
body_response,
..
} = ui
.list_item()
.selected(is_selected)
Expand Down
17 changes: 7 additions & 10 deletions crates/re_ui/examples/re_ui_example/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,17 +243,14 @@ impl eframe::App for ExampleApp {

// ---

ui.large_collapsing_header_with_button(
"Data",
true,
|ui| {
ui.label("Some data here");
},
re_ui::HeaderMenuButton::new(&re_ui::icons::ADD, |ui| {
ui.section_collapsing_header("Data")
.button(re_ui::HeaderMenuButton::new(&re_ui::icons::ADD, |ui| {
ui.weak("empty");
}),
);
ui.large_collapsing_header("Blueprint", true, |ui| {
}))
.show(ui, |ui| {
ui.label("Some data here");
});
ui.section_collapsing_header("Blueprint").show(ui, |ui| {
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
ui.label("Some blueprint stuff here, that might be wide.");
ui.re_checkbox(&mut self.dummy_bool, "Checkbox");
Expand Down
6 changes: 6 additions & 0 deletions crates/re_ui/src/design_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,12 @@ impl DesignTokens {
Self::small_icon_size()
}

/// The color for the background of [`crate::SectionCollapsingHeader`].
pub fn section_collapsing_header_color() -> egui::Color32 {
// same as visuals.widgets.inactive.bg_fill
egui::Color32::from_gray(50)
}

/// The color we use to mean "loop this selection"
pub fn loop_selection_color() -> egui::Color32 {
egui::Color32::from_rgb(1, 37, 105) // from figma 2023-02-09
Expand Down
4 changes: 3 additions & 1 deletion crates/re_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod drag_and_drop;
pub mod icons;
pub mod list_item;
pub mod modal;
mod section_collapsing_header;
pub mod toasts;
mod ui_ext;

Expand All @@ -21,8 +22,9 @@ pub use self::{
design_tokens::DesignTokens,
icons::Icon,
layout_job_builder::LayoutJobBuilder,
section_collapsing_header::{HeaderMenuButton, SectionCollapsingHeader},
syntax_highlighting::SyntaxHighlighting,
ui_ext::{HeaderMenuButton, UiExt},
ui_ext::UiExt,
};

// ---------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions crates/re_ui/src/list_item/label_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct LabelContent<'a> {
italics: bool,

label_style: LabelStyle,
icon_fn: Option<Box<dyn FnOnce(&egui::Ui, egui::Rect, egui::style::WidgetVisuals) + 'a>>,
icon_fn: Option<Box<dyn FnOnce(&mut egui::Ui, egui::Rect, egui::style::WidgetVisuals) + 'a>>,
buttons_fn: Option<Box<dyn FnOnce(&mut egui::Ui) -> egui::Response + 'a>>,
always_show_buttons: bool,

Expand Down Expand Up @@ -115,7 +115,7 @@ impl<'a> LabelContent<'a> {
#[inline]
pub fn with_icon_fn(
mut self,
icon_fn: impl FnOnce(&egui::Ui, egui::Rect, egui::style::WidgetVisuals) + 'a,
icon_fn: impl FnOnce(&mut egui::Ui, egui::Rect, egui::style::WidgetVisuals) + 'a,
) -> Self {
self.icon_fn = Some(Box::new(icon_fn));
self
Expand Down
Loading
Loading