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

Make `TabViewer::{on_add,add_popup} accept corresponding surface index #167

Merged
merged 4 commits into from
Aug 27, 2023
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ provide a guide of how to use the library.
- Renamed `Style::border` to `Style::main_surface_border_stroke`.
- Moved `Style::selection_color` to `OverlayStyle::selection_color`.
- `DockArea::new` now takes in a `DockState` instead of a `Tree`.
- Removed `DockArea::scroll_area_in_tabs`. (([#160](https://github.com/Adanos020/egui_dock/pull/160)))
- Removed `DockArea::scroll_area_in_tabs`. ([#160](https://github.com/Adanos020/egui_dock/pull/160))
- `TabViewer::{context_menu,on_add,add_popup}` now take in an additional `SurfaceIndex` parameter. ([#167](https://github.com/Adanos020/egui_dock/pull/167))

## 0.6.3 - 2023-06-16

Expand Down
16 changes: 11 additions & 5 deletions examples/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ struct MyApp {
impl TabViewer for MyContext {
type Tab = String;

fn title(&mut self, tab: &mut Self::Tab) -> WidgetText {
tab.as_str().into()
}

fn ui(&mut self, ui: &mut Ui, tab: &mut Self::Tab) {
match tab.as_str() {
"Simple Demo" => self.simple_demo(ui),
Expand All @@ -95,7 +99,13 @@ impl TabViewer for MyContext {
}
}

fn context_menu(&mut self, ui: &mut Ui, tab: &mut Self::Tab, _node: NodeIndex) {
fn context_menu(
&mut self,
ui: &mut Ui,
tab: &mut Self::Tab,
_surface: SurfaceIndex,
_node: NodeIndex,
) {
match tab.as_str() {
"Simple Demo" => self.simple_demo_menu(ui),
_ => {
Expand All @@ -105,10 +115,6 @@ impl TabViewer for MyContext {
}
}

fn title(&mut self, tab: &mut Self::Tab) -> WidgetText {
tab.as_str().into()
}

fn closeable(&mut self, tab: &mut Self::Tab) -> bool {
["Inspector", "Style Editor"].contains(&tab.as_str())
}
Expand Down
8 changes: 4 additions & 4 deletions examples/reject_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ struct OpinionatedTab {
impl egui_dock::TabViewer for TabViewer {
type Tab = OpinionatedTab;

fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
(&tab.title).into()
}

fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
ui.label(&tab.content);
match &mut tab.can_become_window {
Expand All @@ -43,10 +47,6 @@ impl egui_dock::TabViewer for TabViewer {
}
}

fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
(&tab.title).into()
}

fn allowed_in_windows(&self, tab: &mut Self::Tab) -> bool {
match tab.can_become_window {
Ok(opinion) | Err(opinion) => opinion,
Expand Down
8 changes: 4 additions & 4 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ struct TabViewer {}
impl egui_dock::TabViewer for TabViewer {
type Tab = String;

fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
ui.label(format!("Content of {tab}"));
}

fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
(&*tab).into()
}

fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
ui.label(format!("Content of {tab}"));
}
}

struct MyApp {
Expand Down
20 changes: 10 additions & 10 deletions examples/tab_add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use eframe::{egui, NativeOptions};

use egui_dock::{DockArea, DockState, NodeIndex, Style};
use egui_dock::{DockArea, DockState, NodeIndex, Style, SurfaceIndex};

fn main() -> eframe::Result<()> {
let options = NativeOptions::default();
Expand All @@ -14,22 +14,22 @@ fn main() -> eframe::Result<()> {
}

struct TabViewer<'a> {
added_nodes: &'a mut Vec<NodeIndex>,
added_nodes: &'a mut Vec<(SurfaceIndex, NodeIndex)>,
}

impl egui_dock::TabViewer for TabViewer<'_> {
type Tab = usize;

fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
ui.label(format!("Content of tab {tab}"));
}

fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
format!("Tab {tab}").into()
}

fn on_add(&mut self, node: NodeIndex) {
self.added_nodes.push(node);
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
ui.label(format!("Content of tab {tab}"));
}

fn on_add(&mut self, surface: SurfaceIndex, node: NodeIndex) {
self.added_nodes.push((surface, node));
}
}

Expand Down Expand Up @@ -70,8 +70,8 @@ impl eframe::App for MyApp {
},
);

added_nodes.drain(..).for_each(|node| {
self.tree.main_surface_mut().set_focused_node(node);
added_nodes.drain(..).for_each(|(surface, node)| {
self.tree.set_focused_node_and_surface((surface, node));
self.tree.push_to_focused_leaf(self.counter);
self.counter += 1;
});
Expand Down
74 changes: 46 additions & 28 deletions examples/tab_add_popup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use eframe::{egui, NativeOptions};

use egui::{Color32, RichText};
use egui_dock::{DockArea, DockState, NodeIndex, Style};
use egui_dock::{DockArea, DockState, NodeIndex, Style, SurfaceIndex};

fn main() -> eframe::Result<()> {
let options = NativeOptions::default();
Expand All @@ -21,20 +21,24 @@ enum MyTabKind {

struct MyTab {
kind: MyTabKind,
surface: SurfaceIndex,
node: NodeIndex,
}

impl MyTab {
fn regular(node_index: usize) -> Self {
fn regular(surface: SurfaceIndex, node: NodeIndex) -> Self {
Self {
kind: MyTabKind::Regular,
node: NodeIndex(node_index),
surface,
node,
}
}

fn fancy(node_index: usize) -> Self {
fn fancy(surface: SurfaceIndex, node: NodeIndex) -> Self {
Self {
kind: MyTabKind::Fancy,
node: NodeIndex(node_index),
surface,
node,
}
}

Expand Down Expand Up @@ -68,56 +72,68 @@ struct TabViewer<'a> {
impl egui_dock::TabViewer for TabViewer<'_> {
type Tab = MyTab;

fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
ui.label(tab.content());
}

fn title(&mut self, tab: &mut Self::Tab) -> egui::WidgetText {
tab.title().into()
}

fn add_popup(&mut self, ui: &mut egui::Ui, node: NodeIndex) {
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
ui.label(tab.content());
}

fn add_popup(&mut self, ui: &mut egui::Ui, surface: SurfaceIndex, node: NodeIndex) {
ui.set_min_width(120.0);
ui.style_mut().visuals.button_frame = false;

if ui.button("Regular tab").clicked() {
self.added_nodes.push(MyTab::regular(node.0));
self.added_nodes.push(MyTab::regular(surface, node));
}

if ui.button("Fancy tab").clicked() {
self.added_nodes.push(MyTab::fancy(node.0));
self.added_nodes.push(MyTab::fancy(surface, node));
}
}
}

struct MyApp {
tree: DockState<MyTab>,
dock_state: DockState<MyTab>,
counter: usize,
}

impl Default for MyApp {
fn default() -> Self {
let mut tree = DockState::new(vec![MyTab::regular(1), MyTab::fancy(2)]);
let mut tree = DockState::new(vec![
MyTab::regular(SurfaceIndex::main(), NodeIndex(1)),
MyTab::fancy(SurfaceIndex::main(), NodeIndex(2)),
]);

// You can modify the tree before constructing the dock
let [a, b] =
tree.main_surface_mut()
.split_left(NodeIndex::root(), 0.3, vec![MyTab::fancy(3)]);
let [_, _] = tree
.main_surface_mut()
.split_below(a, 0.7, vec![MyTab::fancy(4)]);
let [_, _] = tree
.main_surface_mut()
.split_below(b, 0.5, vec![MyTab::regular(5)]);

Self { tree, counter: 6 }
let [a, b] = tree.main_surface_mut().split_left(
NodeIndex::root(),
0.3,
vec![MyTab::fancy(SurfaceIndex::main(), NodeIndex(3))],
);
let [_, _] = tree.main_surface_mut().split_below(
a,
0.7,
vec![MyTab::fancy(SurfaceIndex::main(), NodeIndex(4))],
);
let [_, _] = tree.main_surface_mut().split_below(
b,
0.5,
vec![MyTab::regular(SurfaceIndex::main(), NodeIndex(5))],
);

Self {
dock_state: tree,
counter: 6,
}
}
}

impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let mut added_nodes = Vec::new();
DockArea::new(&mut self.tree)
DockArea::new(&mut self.dock_state)
.show_add_buttons(true)
.show_add_popup(true)
.style(Style::from_egui(ctx.style().as_ref()))
Expand All @@ -129,9 +145,11 @@ impl eframe::App for MyApp {
);

added_nodes.drain(..).for_each(|node| {
self.tree.main_surface_mut().set_focused_node(node.node);
self.tree.push_to_focused_leaf(MyTab {
self.dock_state
.set_focused_node_and_surface((node.surface, node.node));
self.dock_state.push_to_focused_leaf(MyTab {
kind: node.kind,
surface: node.surface,
node: NodeIndex(self.counter),
});
self.counter += 1;
Expand Down
8 changes: 4 additions & 4 deletions examples/text_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ struct Buffers {
impl egui_dock::TabViewer for Buffers {
type Tab = Title;

fn title(&mut self, title: &mut Title) -> egui::WidgetText {
egui::WidgetText::from(&*title)
}

fn ui(&mut self, ui: &mut egui::Ui, title: &mut Title) {
let text = self.buffers.entry(title.clone()).or_default();
egui::TextEdit::multiline(text)
.desired_width(f32::INFINITY)
.show(ui);
}

fn title(&mut self, title: &mut Title) -> egui::WidgetText {
egui::WidgetText::from(&*title)
}
}

struct MyApp {
Expand Down
9 changes: 6 additions & 3 deletions src/widgets/dock_area/show/leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ impl<'tree, Tab> DockArea<'tree, Tab> {
};
self.tab_plus(
ui,
surface_index,
node_index,
tab_viewer,
tabbar_outer_rect,
Expand Down Expand Up @@ -307,7 +308,7 @@ impl<'tree, Tab> DockArea<'tree, Tab> {

if self.tab_context_menus {
response = response.context_menu(|ui| {
tab_viewer.context_menu(ui, tab, node_index);
tab_viewer.context_menu(ui, tab, surface_index, node_index);
if (surface_index.is_main() || !is_lonely_tab)
&& ui.button("Eject").clicked()
{
Expand Down Expand Up @@ -394,9 +395,11 @@ impl<'tree, Tab> DockArea<'tree, Tab> {
}
}

#[allow(clippy::too_many_arguments)]
fn tab_plus(
&mut self,
ui: &mut Ui,
surface_index: SurfaceIndex,
node_index: NodeIndex,
tab_viewer: &mut impl TabViewer<Tab = Tab>,
tabbar_outer_rect: Rect,
Expand Down Expand Up @@ -452,14 +455,14 @@ impl<'tree, Tab> DockArea<'tree, Tab> {

let popup_id = ui.id().with("tab_add_popup");
popup_under_widget(ui, popup_id, &response, |ui| {
tab_viewer.add_popup(ui, node_index);
tab_viewer.add_popup(ui, surface_index, node_index);
});

if response.clicked() {
if self.show_add_popup {
ui.memory_mut(|mem| mem.toggle_popup(popup_id));
}
tab_viewer.on_add(node_index);
tab_viewer.on_add(surface_index, node_index);
}
}

Expand Down
22 changes: 15 additions & 7 deletions src/widgets/tab_viewer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{NodeIndex, TabStyle};
use crate::{NodeIndex, SurfaceIndex, TabStyle};
use egui::{Id, Ui, WidgetText};

/// Defines how to display a tab inside a [`Tree`](crate::Tree).
Expand All @@ -14,9 +14,16 @@ pub trait TabViewer {

/// Content inside the context menu shown when the tab is right-clicked.
///
/// The `_node` specifies which [`Node`](crate::Node) or split of the tree that this particular context menu
/// belongs to.
fn context_menu(&mut self, _ui: &mut Ui, _tab: &mut Self::Tab, _node: NodeIndex) {}
/// `_surface` and `_node` specify which [`Surface`](crate::Surface) and [`Node`](crate::Node) that this particular
/// context menu belongs to.
fn context_menu(
&mut self,
_ui: &mut Ui,
_tab: &mut Self::Tab,
_surface: SurfaceIndex,
_node: NodeIndex,
) {
}

/// Unique ID for this tab.
///
Expand Down Expand Up @@ -47,14 +54,15 @@ pub trait TabViewer {
/// This is called when the tabs add button is pressed and if the dock [`Style`](crate::Style)'s
/// `show_add_buttons` is set to `true`.
///
/// `_node` specifies which [`Node`](crate::Node) or split of the tree this particular add button was pressed on.
fn on_add(&mut self, _node: NodeIndex) {}
/// `_surface` and `_node` specify which surface and which [`Node`](crate::Node) this particular add button was
/// pressed on.
fn on_add(&mut self, _surface: SurfaceIndex, _node: NodeIndex) {}

/// Content of the popup under the add button. Useful for selecting what type of tab to add.
///
/// This requires that [`DockArea::show_add_buttons`](crate::DockArea::show_add_buttons) and
/// [`DockArea::show_add_popup`](crate::DockArea::show_add_popup) are set to `true`.
fn add_popup(&mut self, _ui: &mut Ui, _node: NodeIndex) {}
fn add_popup(&mut self, _ui: &mut Ui, _surface: SurfaceIndex, _node: NodeIndex) {}

/// This is called every frame after [`ui`](Self::ui) is called, if the `_tab` is active.
///
Expand Down