Skip to content

Commit aa184bc

Browse files
dolezvo1anhosh
andauthored
Make TabViewer::id mandatory (#324)
* Make TabViewer::id mandatory * Fix example formatting * Fix missing id and Debug implementations --------- Co-authored-by: Adam Gąsior <adanos020@gmail.com>
1 parent f030b0f commit aa184bc

10 files changed

Lines changed: 64 additions & 24 deletions

File tree

examples/hello.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ struct MyApp {
9090
impl TabViewer for MyContext {
9191
type Tab = String;
9292

93+
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
94+
egui::Id::new(tab)
95+
}
96+
9397
fn title(&mut self, tab: &mut Self::Tab) -> WidgetText {
9498
tab.as_str().into()
9599
}

examples/reject_windows.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,37 @@ fn main() -> eframe::Result<()> {
1414

1515
struct TabViewer;
1616

17+
#[derive(Hash, Debug)]
18+
enum Opinion {
19+
Changing(bool),
20+
Fixed(bool),
21+
}
22+
#[derive(Hash, Debug)]
1723
struct OpinionatedTab {
18-
can_become_window: Result<bool, bool>,
24+
can_become_window: Opinion,
1925
title: String,
2026
content: String,
2127
}
2228

2329
impl egui_dock::TabViewer for TabViewer {
2430
type Tab = OpinionatedTab;
2531

32+
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
33+
egui::Id::new(tab)
34+
}
35+
2636
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
2737
(&tab.title).into()
2838
}
2939

3040
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
3141
ui.label(&tab.content);
3242
match &mut tab.can_become_window {
33-
Ok(changing_opinion) => {
34-
ui.add(egui::Checkbox::new(
35-
changing_opinion,
36-
"can be turned into window",
37-
));
43+
Opinion::Changing(opinion) => {
44+
ui.add(egui::Checkbox::new(opinion, "can be turned into window"));
3845
}
39-
Err(fixed_opinion) => {
40-
if *fixed_opinion {
46+
Opinion::Fixed(opinion) => {
47+
if *opinion {
4148
ui.small("this tab can exist in a window");
4249
} else {
4350
ui.small("this tab cannot exist in a window");
@@ -48,7 +55,7 @@ impl egui_dock::TabViewer for TabViewer {
4855

4956
fn allowed_in_windows(&self, tab: &mut Self::Tab) -> bool {
5057
match tab.can_become_window {
51-
Ok(opinion) | Err(opinion) => opinion,
58+
Opinion::Changing(opinion) | Opinion::Fixed(opinion) => opinion,
5259
}
5360
}
5461
}
@@ -61,12 +68,12 @@ impl Default for MyApp {
6168
fn default() -> Self {
6269
let mut tree = DockState::new(vec![
6370
OpinionatedTab {
64-
can_become_window: Ok(false),
71+
can_become_window: Opinion::Changing(false),
6572
title: "old tab".to_owned(),
6673
content: "since when could tabs become windows?".to_string(),
6774
},
6875
OpinionatedTab {
69-
can_become_window: Err(false),
76+
can_become_window: Opinion::Fixed(false),
7077
title: "grumpy tab".to_owned(),
7178
content: "I don't want to be a window!".to_string(),
7279
},
@@ -77,7 +84,7 @@ impl Default for MyApp {
7784
NodeIndex::root(),
7885
0.6,
7986
vec![OpinionatedTab {
80-
can_become_window: Ok(true),
87+
can_become_window: Opinion::Changing(true),
8188
title: "wise tab".to_owned(),
8289
content: "egui_dock 0.7!".to_string(),
8390
}],
@@ -86,7 +93,7 @@ impl Default for MyApp {
8693
a,
8794
0.4,
8895
vec![OpinionatedTab {
89-
can_become_window: Ok(true),
96+
can_become_window: Opinion::Changing(true),
9097
title: "instructional tab".to_owned(),
9198
content: "This demo is meant to showcase the ability for tabs to become/be placed inside windows.
9299
\nindividual tabs have the ability to accept/reject being put/turned into a window.
@@ -96,7 +103,7 @@ impl Default for MyApp {
96103
}],
97104
);
98105
let _ = tree.add_window(vec![OpinionatedTab {
99-
can_become_window: Err(true),
106+
can_become_window: Opinion::Fixed(true),
100107
title: "egotistical tab".to_owned(),
101108
content: "im above you all!".to_string(),
102109
}]);

examples/save_load_dock_state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ struct TabViewer {
2323
impl egui_dock::TabViewer for TabViewer {
2424
type Tab = String;
2525

26+
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
27+
egui::Id::new(tab)
28+
}
29+
2630
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
2731
(&*tab).into()
2832
}

examples/simple.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ struct TabViewer {}
1818
impl egui_dock::TabViewer for TabViewer {
1919
type Tab = String;
2020

21+
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
22+
egui::Id::new(tab)
23+
}
24+
2125
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
2226
(&*tab).into()
2327
}

examples/tab_add.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ struct TabViewer<'a> {
1919
impl egui_dock::TabViewer for TabViewer<'_> {
2020
type Tab = usize;
2121

22+
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
23+
egui::Id::new(tab)
24+
}
25+
2226
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
2327
format!("Tab {tab}").into()
2428
}

examples/tab_add_popup.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ fn main() -> eframe::Result<()> {
1313
)
1414
}
1515

16+
#[derive(Hash, Debug)]
1617
enum MyTabKind {
1718
Regular,
1819
Fancy,
1920
}
2021

22+
#[derive(Hash, Debug)]
2123
struct MyTab {
2224
kind: MyTabKind,
2325
path: NodePath,
@@ -68,6 +70,10 @@ struct TabViewer<'a> {
6870
impl egui_dock::TabViewer for TabViewer<'_> {
6971
type Tab = MyTab;
7072

73+
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
74+
egui::Id::new(tab)
75+
}
76+
7177
fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
7278
tab.title().into()
7379
}

examples/text_editor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ struct Buffers {
2424
impl TabViewer for Buffers {
2525
type Tab = Title;
2626

27+
fn id(&mut self, tab: &mut Self::Tab) -> egui::Id {
28+
egui::Id::new(tab)
29+
}
30+
2731
fn title(&mut self, title: &mut Title) -> egui::WidgetText {
2832
egui::WidgetText::from(&*title)
2933
}

src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//!
1616
//! ```rust
1717
//! use egui_dock::{DockArea, DockState, NodeIndex, Style, TabViewer};
18-
//! use egui::{Ui, WidgetText};
18+
//! use egui::{Id, Ui, WidgetText};
1919
//!
2020
//! // First, let's pick a type that we'll use to attach some data to each tab.
2121
//! // It can be any type.
@@ -30,6 +30,11 @@
3030
//! // This associated type is used to attach some data to each tab.
3131
//! type Tab = Tab;
3232
//!
33+
//! // Returns the unique ID for the `tab`.
34+
//! fn id(&mut self, tab: &mut Self::Tab) -> Id {
35+
//! Id::new(tab)
36+
//! }
37+
//!
3338
//! // Returns the current `tab`'s title.
3439
//! fn title(&mut self, tab: &mut Self::Tab) -> WidgetText {
3540
//! tab.as_str().into()
@@ -86,10 +91,11 @@
8691
//!
8792
//! ```rust
8893
//! # use egui_dock::{DockArea, DockState, OverlayType, Style, TabAddAlign, TabViewer};
89-
//! # use egui::{Ui, WidgetText};
94+
//! # use egui::{Id, Ui, WidgetText};
9095
//! # struct MyTabViewer;
9196
//! # impl TabViewer for MyTabViewer {
9297
//! # type Tab = ();
98+
//! # fn id(&mut self, tab: &mut Self::Tab) -> Id { Id::new(tab) }
9399
//! # fn title(&mut self, tab: &mut Self::Tab) -> WidgetText { WidgetText::default() }
94100
//! # fn ui(&mut self, ui: &mut Ui, tab: &mut Self::Tab) {}
95101
//! # }

src/style.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ pub enum TabAddAlign {
2020
///
2121
/// ```rust
2222
/// # use egui_dock::{DockArea, DockState, OverlayType, Style, TabAddAlign, TabViewer};
23-
/// # use egui::{Ui, WidgetText};
23+
/// # use egui::{Id, Ui, WidgetText};
2424
/// # struct MyTabViewer;
2525
/// # impl TabViewer for MyTabViewer {
2626
/// # type Tab = ();
27+
/// # fn id(&mut self, tab: &mut Self::Tab) -> Id { Id::new(tab) }
2728
/// # fn title(&mut self, tab: &mut Self::Tab) -> WidgetText { WidgetText::default() }
2829
/// # fn ui(&mut self, ui: &mut Ui, tab: &mut Self::Tab) {}
2930
/// # }

src/widgets/tab_viewer.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ pub trait TabViewer {
77
/// The type of tab in which you can store state to be drawn in your tabs.
88
type Tab;
99

10+
/// Unique ID for this tab.
11+
///
12+
/// Assuming `Tab` implements `Hash`, you can simply do `Id::new(tab)`.
13+
/// If that is not possible, but tab names are guaranteed to be unique,
14+
/// one could also implement this as `Id::new(self.title(tab).text())`.
15+
fn id(&mut self, tab: &mut Self::Tab) -> Id;
16+
1017
/// The title to be displayed in the tab bar.
1118
fn title(&mut self, tab: &mut Self::Tab) -> WidgetText;
1219

@@ -19,13 +26,6 @@ pub trait TabViewer {
1926
/// that this particular context menu belongs to.
2027
fn context_menu(&mut self, _ui: &mut Ui, _tab: &mut Self::Tab, _path: NodePath) {}
2128

22-
/// Unique ID for this tab.
23-
///
24-
/// If not implemented, uses tab title text as an ID source.
25-
fn id(&mut self, tab: &mut Self::Tab) -> Id {
26-
Id::new(self.title(tab).text())
27-
}
28-
2929
/// Called after each tab button is shown, so you can add a tooltip, check for clicks, etc.
3030
fn on_tab_button(&mut self, _tab: &mut Self::Tab, _response: &egui::Response) {}
3131

0 commit comments

Comments
 (0)