Skip to content

Commit 49b426f

Browse files
authored
Better looking tabs (#1011)
* Move egui_dock styling to re_ui * Add egui_dock example to re_ui_example * No context-menu on right-click * Improve the look of tabs * Use the space icon in the tab name
1 parent d37a498 commit 49b426f

File tree

7 files changed

+92
-25
lines changed

7 files changed

+92
-25
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ epaint = { git = "https://github.com/emilk/egui", rev = "f222ee044edf8beebfaf5dd
8484
# epaint = { path = "../../egui/crates/epaint" }
8585

8686
# Forks of 3rd party egui crates, tracking latest egui/master:
87-
egui_dock = { git = "https://github.com/rerun-io/egui_dock", rev = "1355a9f24e99518ef7b9546872a0f25ffe1f91d2" } # https://github.com/Adanos020/egui_dock/pull/93
87+
egui_dock = { git = "https://github.com/rerun-io/egui_dock", rev = "69f52c752695165243d8900b8e11a84df812d67f" } # https://github.com/Adanos020/egui_dock/pull/93
8888
egui-notify = { git = "https://github.com/rerun-io/egui-notify", rev = "a158c2b81ca69ac78e3c61a705f478e8af76fd7d" } # https://github.com/ItsEthra/egui-notify/pull/10
8989
# egui_dock = { path = "../../forks/egui_dock" }
9090
# egui-notify = { path = "../../forks/egui-notify" }

crates/re_ui/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ include = [
1515

1616

1717
[features]
18-
default = []
18+
default = ["egui_dock"]
19+
20+
egui_dock = ["dep:egui_dock"]
1921

2022

2123
[dependencies]
@@ -29,6 +31,8 @@ strum = { version = "0.24", features = ["derive"] }
2931
strum_macros = "0.24"
3032
sublime_fuzzy = "0.7"
3133

34+
## Optional dependencies:
35+
egui_dock = { version = "0.3", optional = true, features = ["serde"] }
3236

3337
[dev-dependencies]
3438
eframe = { workspace = true, default-features = false, features = ["wgpu"] }

crates/re_ui/examples/re_ui_example.rs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ fn main() -> eframe::Result<()> {
1212
..Default::default()
1313
};
1414

15+
let tree = egui_dock::Tree::new(vec![1, 2, 3]);
16+
1517
eframe::run_native(
1618
"re_ui example app",
1719
native_options,
@@ -20,6 +22,8 @@ fn main() -> eframe::Result<()> {
2022
Box::new(ExampleApp {
2123
re_ui,
2224

25+
tree,
26+
2327
left_panel: true,
2428
right_panel: true,
2529
bottom_panel: true,
@@ -37,6 +41,8 @@ fn main() -> eframe::Result<()> {
3741
pub struct ExampleApp {
3842
re_ui: re_ui::ReUi,
3943

44+
tree: egui_dock::Tree<Tab>,
45+
4046
left_panel: bool,
4147
right_panel: bool,
4248
bottom_panel: bool,
@@ -60,31 +66,34 @@ impl eframe::App for ExampleApp {
6066
self.top_bar(egui_ctx, frame);
6167

6268
egui::SidePanel::left("left_panel").show_animated(egui_ctx, self.left_panel, |ui| {
63-
ui.label("Left panel");
69+
ui.strong("Left panel");
6470
ui.horizontal(|ui| {
6571
ui.label("Toggle switch:");
6672
ui.add(re_ui::toggle_switch(&mut self.dummy_bool));
6773
});
74+
ui.label(format!("Latest command: {}", self.latest_cmd));
6875
});
6976
egui::SidePanel::right("right_panel").show_animated(egui_ctx, self.right_panel, |ui| {
70-
ui.label("Right panel");
77+
ui.strong("Right panel");
7178
selection_buttons(ui);
7279
});
7380
egui::TopBottomPanel::bottom("bottom_panel").show_animated(
7481
egui_ctx,
7582
self.bottom_panel,
7683
|ui| {
77-
ui.label("Bottom panel");
84+
ui.strong("Bottom panel");
7885
},
7986
);
8087

81-
egui::CentralPanel::default().show(egui_ctx, |ui| {
82-
egui::warn_if_debug_build(ui);
83-
ui.label("Hover me for a tooltip")
84-
.on_hover_text("This is a tooltip");
85-
86-
ui.label(format!("Latest command: {}", self.latest_cmd));
87-
});
88+
let central_panel_frame = egui::Frame {
89+
fill: egui_ctx.style().visuals.panel_fill,
90+
..Default::default()
91+
};
92+
egui::CentralPanel::default()
93+
.frame(central_panel_frame)
94+
.show(egui_ctx, |ui| {
95+
tabs_ui(ui, &mut self.tree);
96+
});
8897

8998
if let Some(cmd) = self.cmd_palette.show(egui_ctx) {
9099
self.pending_commands.push(cmd);
@@ -205,3 +214,28 @@ fn selection_buttons(ui: &mut egui::Ui) {
205214
});
206215
});
207216
}
217+
218+
fn tabs_ui(ui: &mut egui::Ui, tree: &mut egui_dock::Tree<Tab>) {
219+
let mut my_tab_viewer = MyTabViewer {};
220+
egui_dock::DockArea::new(tree)
221+
.style(re_ui::egui_dock_style(ui.style()))
222+
.show_inside(ui, &mut my_tab_viewer);
223+
}
224+
225+
pub type Tab = i32;
226+
227+
struct MyTabViewer {}
228+
229+
impl egui_dock::TabViewer for MyTabViewer {
230+
type Tab = Tab;
231+
232+
fn ui(&mut self, ui: &mut egui::Ui, _tab: &mut Self::Tab) {
233+
egui::warn_if_debug_build(ui);
234+
ui.label("Hover me for a tooltip")
235+
.on_hover_text("This is a tooltip");
236+
}
237+
238+
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
239+
format!("This is tab {tab}").into()
240+
}
241+
}

crates/re_ui/src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,35 @@ impl ReUi {
313313
self.large_button_impl(ui, icon, bg_fill, tint)
314314
}
315315
}
316+
317+
// ----------------------------------------------------------------------------
318+
319+
#[cfg(feature = "egui_dock")]
320+
pub fn egui_dock_style(style: &egui::Style) -> egui_dock::Style {
321+
let mut dock_style = egui_dock::Style::from_egui(style);
322+
dock_style.separator_width = 2.0;
323+
dock_style.default_inner_margin = 0.0.into();
324+
dock_style.show_close_buttons = false;
325+
dock_style.tab_include_scrollarea = false;
326+
dock_style.show_context_menu = false;
327+
dock_style.expand_tabs = false; // expand_tabs looks good, but decreases readability
328+
329+
// Tabs can be "focused", meaning it was the last clicked (of any tab). We don't care about that.
330+
// Tabs can also be "active", meaning it is the selected tab within its sibling tabs. We want to highlight that.
331+
let inactive_text_color = style.visuals.widgets.noninteractive.text_color();
332+
let active_text_color = style.visuals.widgets.active.text_color();
333+
334+
dock_style.tab_text_color_unfocused = inactive_text_color;
335+
dock_style.tab_text_color_focused = inactive_text_color;
336+
dock_style.tab_text_color_active_unfocused = active_text_color;
337+
dock_style.tab_text_color_active_focused = active_text_color;
338+
339+
// Don't show tabs
340+
dock_style.tab_bar_background_color = style.visuals.panel_fill;
341+
dock_style.tab_background_color = style.visuals.panel_fill;
342+
343+
// The active tab has no special outline:
344+
dock_style.tab_outline_color = Color32::TRANSPARENT;
345+
346+
dock_style
347+
}

crates/re_viewer/src/ui/space_view.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ impl SpaceView {
9797
}
9898
}
9999

100+
/// How to show the name in the ui
101+
pub fn display_text(&self) -> egui::WidgetText {
102+
format!("{} {}", self.category.icon(), &self.name).into()
103+
}
104+
100105
/// List of entities a space view queries by default for a given category.
101106
///
102107
/// These are all entities in the given space which have the requested category and are reachable by a transform.

crates/re_viewer/src/ui/viewport.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl Viewport {
142142
true,
143143
&mut is_space_view_visible,
144144
|ui| {
145-
let label = format!("{} {}", space_view.category.icon(), space_view.name);
145+
let label = space_view.display_text();
146146
let response = ctx.space_view_button_to(ui, label, *space_view_id);
147147
if response.clicked() {
148148
if let Some(tree) = self.trees.get_mut(&self.visible) {
@@ -388,15 +388,6 @@ impl Viewport {
388388
});
389389
}
390390
} else {
391-
let mut dock_style = egui_dock::Style::from_egui(ui.style().as_ref());
392-
dock_style.separator_width = 2.0;
393-
dock_style.default_inner_margin = 0.0.into();
394-
dock_style.show_close_buttons = false;
395-
dock_style.tab_include_scrollarea = false;
396-
// dock_style.expand_tabs = true; looks good, but decreases readability
397-
dock_style.tab_text_color_unfocused = dock_style.tab_text_color_focused; // We don't treat focused tabs differently
398-
dock_style.tab_background_color = ui.visuals().panel_fill;
399-
400391
let mut tab_viewer = TabViewer {
401392
ctx,
402393
spaces_info,
@@ -406,7 +397,7 @@ impl Viewport {
406397
};
407398

408399
egui_dock::DockArea::new(tree)
409-
.style(dock_style)
400+
.style(re_ui::egui_dock_style(ui.style()))
410401
.show_inside(ui, &mut tab_viewer);
411402
}
412403
}
@@ -748,7 +739,7 @@ impl<'a, 'b> egui_dock::TabViewer for TabViewer<'a, 'b> {
748739
.space_views
749740
.get_mut(tab)
750741
.expect("Should have been populated beforehand");
751-
space_view.name.clone().into()
742+
space_view.display_text()
752743
}
753744
}
754745

0 commit comments

Comments
 (0)