mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 05:40:03 -04:00
You can mandate that all leaves have tabs
This commit is contained in:
@@ -173,11 +173,13 @@ pub enum UiResponse {
|
|||||||
DragStarted,
|
DragStarted,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct SimplificationOptions {
|
pub struct SimplificationOptions {
|
||||||
pub prune_empty_tabs: bool,
|
pub prune_empty_tabs: bool,
|
||||||
pub prune_single_child_tabs: bool,
|
pub prune_single_child_tabs: bool,
|
||||||
pub prune_empty_layouts: bool,
|
pub prune_empty_layouts: bool,
|
||||||
pub prune_single_child_layouts: bool,
|
pub prune_single_child_layouts: bool,
|
||||||
|
pub all_leaves_must_have_tabs: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SimplificationOptions {
|
impl Default for SimplificationOptions {
|
||||||
@@ -187,6 +189,7 @@ impl Default for SimplificationOptions {
|
|||||||
prune_single_child_tabs: true,
|
prune_single_child_tabs: true,
|
||||||
prune_empty_layouts: true,
|
prune_empty_layouts: true,
|
||||||
prune_single_child_layouts: true,
|
prune_single_child_layouts: true,
|
||||||
|
all_leaves_must_have_tabs: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,7 +413,12 @@ impl<Leaf> Dock<Leaf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui(&mut self, behavior: &mut dyn Behavior<Leaf>, ui: &mut Ui) {
|
pub fn ui(&mut self, behavior: &mut dyn Behavior<Leaf>, ui: &mut Ui) {
|
||||||
self.simplify(&behavior.simplification_options());
|
let options = behavior.simplification_options();
|
||||||
|
self.simplify(&options);
|
||||||
|
if options.all_leaves_must_have_tabs {
|
||||||
|
self.nodes
|
||||||
|
.make_all_leaves_children_of_tabs(false, self.root);
|
||||||
|
}
|
||||||
self.nodes.gc_root(behavior, self.root);
|
self.nodes.gc_root(behavior, self.root);
|
||||||
|
|
||||||
self.nodes.layout_node(
|
self.nodes.layout_node(
|
||||||
@@ -1020,12 +1028,18 @@ impl<Leaf> Nodes<Leaf> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if options.prune_empty_tabs && children.is_empty() {
|
if options.prune_empty_tabs && children.is_empty() {
|
||||||
log::debug!("Simplify: removing empty tabs");
|
log::debug!("Simplify: removing empty tabs node");
|
||||||
return SimplifyAction::Remove;
|
return SimplifyAction::Remove;
|
||||||
}
|
}
|
||||||
if options.prune_single_child_tabs && children.len() == 1 {
|
if options.prune_single_child_tabs && children.len() == 1 {
|
||||||
log::debug!("Simplify: removing single-child tabs");
|
if options.all_leaves_must_have_tabs
|
||||||
return SimplifyAction::Replace(children[0]);
|
&& matches!(self.get(children[0]), Some(NodeLayout::Leaf(_)))
|
||||||
|
{
|
||||||
|
// Keep it
|
||||||
|
} else {
|
||||||
|
log::debug!("Simplify: collapsing single-child tabs node");
|
||||||
|
return SimplifyAction::Replace(children[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1042,11 +1056,11 @@ impl<Leaf> Nodes<Leaf> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if options.prune_empty_layouts && children.is_empty() {
|
if options.prune_empty_layouts && children.is_empty() {
|
||||||
log::debug!("Simplify: removing empty layout");
|
log::debug!("Simplify: removing empty layout node");
|
||||||
return SimplifyAction::Remove;
|
return SimplifyAction::Remove;
|
||||||
}
|
}
|
||||||
if options.prune_single_child_layouts && children.len() == 1 {
|
if options.prune_single_child_layouts && children.len() == 1 {
|
||||||
log::debug!("Simplify: removing single-child layout");
|
log::debug!("Simplify: collapsing single-child layout node");
|
||||||
return SimplifyAction::Replace(children[0]);
|
return SimplifyAction::Replace(children[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1056,3 +1070,39 @@ impl<Leaf> Nodes<Leaf> {
|
|||||||
SimplifyAction::Keep
|
SimplifyAction::Keep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Leaf> Nodes<Leaf> {
|
||||||
|
fn make_all_leaves_children_of_tabs(&mut self, parent_is_tabs: bool, it: NodeId) {
|
||||||
|
let Some(mut node) = self.nodes.remove(&it) else { return; };
|
||||||
|
|
||||||
|
match &mut node.layout {
|
||||||
|
NodeLayout::Leaf(_) => {
|
||||||
|
if !parent_is_tabs {
|
||||||
|
// Add tabs to this leaf:
|
||||||
|
let new_id = NodeId::random();
|
||||||
|
self.nodes.insert(new_id, node);
|
||||||
|
let tabs = NodeState::from(NodeLayout::Tabs(Tabs {
|
||||||
|
children: vec![new_id],
|
||||||
|
active: new_id,
|
||||||
|
}));
|
||||||
|
self.nodes.insert(it, tabs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NodeLayout::Tabs(Tabs { children, .. }) => {
|
||||||
|
for child in children {
|
||||||
|
self.make_all_leaves_children_of_tabs(true, *child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeLayout::Horizontal(Horizontal { children, .. })
|
||||||
|
| NodeLayout::Vertical(Vertical { children, .. }) => {
|
||||||
|
for child in children {
|
||||||
|
self.make_all_leaves_children_of_tabs(false, *child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.nodes.insert(it, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ impl View {
|
|||||||
|
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> dock::UiResponse {
|
pub fn ui(&mut self, ui: &mut egui::Ui) -> dock::UiResponse {
|
||||||
ui.painter().rect_filled(ui.max_rect(), 0.0, self.color);
|
ui.painter().rect_filled(ui.max_rect(), 0.0, self.color);
|
||||||
ui.label(&self.title);
|
|
||||||
let dragged = ui
|
let dragged = ui
|
||||||
.add(egui::Button::new("Drag me to drag view").sense(egui::Sense::drag()))
|
.add(
|
||||||
|
egui::Button::new(format!("Contents of {}. Drag me!", self.title))
|
||||||
|
.sense(egui::Sense::drag()),
|
||||||
|
)
|
||||||
.on_hover_cursor(egui::CursorIcon::Grab)
|
.on_hover_cursor(egui::CursorIcon::Grab)
|
||||||
.dragged();
|
.dragged();
|
||||||
if dragged {
|
if dragged {
|
||||||
@@ -42,8 +44,33 @@ impl View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct DockBehavior {
|
||||||
|
simplification_options: dock::SimplificationOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dock::Behavior<View> for DockBehavior {
|
||||||
|
fn leaf_ui(
|
||||||
|
&mut self,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
_node_id: dock::NodeId,
|
||||||
|
view: &mut View,
|
||||||
|
) -> dock::UiResponse {
|
||||||
|
view.ui(ui)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tab_text_for_leaf(&mut self, view: &View) -> egui::WidgetText {
|
||||||
|
view.title.clone().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplification_options(&self) -> dock::SimplificationOptions {
|
||||||
|
self.simplification_options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct MyApp {
|
struct MyApp {
|
||||||
dock: dock::Dock<View>,
|
dock: dock::Dock<View>,
|
||||||
|
behavior: DockBehavior,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MyApp {
|
impl Default for MyApp {
|
||||||
@@ -66,32 +93,43 @@ impl Default for MyApp {
|
|||||||
let tab2 = {
|
let tab2 = {
|
||||||
let a = nodes.insert_leaf(gen_view());
|
let a = nodes.insert_leaf(gen_view());
|
||||||
let b = nodes.insert_leaf(gen_view());
|
let b = nodes.insert_leaf(gen_view());
|
||||||
nodes.insert_horizontal_node(vec![a, b])
|
let c = nodes.insert_leaf(gen_view());
|
||||||
|
let d = nodes.insert_leaf(gen_view());
|
||||||
|
let e = nodes.insert_leaf(gen_view());
|
||||||
|
nodes.insert_horizontal_node(vec![a, b, c, d, e])
|
||||||
};
|
};
|
||||||
|
|
||||||
let root = nodes.insert_tab_node(vec![tab0, tab1, tab2]);
|
let root = nodes.insert_tab_node(vec![tab0, tab1, tab2]);
|
||||||
|
|
||||||
let dock = dock::Dock::new(root, nodes);
|
let dock = dock::Dock::new(root, nodes);
|
||||||
|
|
||||||
Self { dock }
|
Self {
|
||||||
|
dock,
|
||||||
|
behavior: Default::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl eframe::App for MyApp {
|
impl eframe::App for MyApp {
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
let mut behavior = DockBehavior {};
|
|
||||||
|
|
||||||
egui::SidePanel::left("tree").show(ctx, |ui| {
|
egui::SidePanel::left("tree").show(ctx, |ui| {
|
||||||
if ui.button("Reset").clicked() {
|
if ui.button("Reset").clicked() {
|
||||||
*self = Default::default();
|
*self = Default::default();
|
||||||
}
|
}
|
||||||
|
ui.checkbox(
|
||||||
|
&mut self
|
||||||
|
.behavior
|
||||||
|
.simplification_options
|
||||||
|
.all_leaves_must_have_tabs,
|
||||||
|
"All views have tabs",
|
||||||
|
);
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
tree_ui(ui, &mut behavior, &self.dock.nodes, self.dock.root);
|
tree_ui(ui, &mut self.behavior, &self.dock.nodes, self.dock.root);
|
||||||
});
|
});
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
self.dock.ui(&mut behavior, ui);
|
self.dock.ui(&mut self.behavior, ui);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,20 +174,3 @@ fn tree_ui(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DockBehavior {}
|
|
||||||
|
|
||||||
impl dock::Behavior<View> for DockBehavior {
|
|
||||||
fn leaf_ui(
|
|
||||||
&mut self,
|
|
||||||
ui: &mut egui::Ui,
|
|
||||||
_node_id: dock::NodeId,
|
|
||||||
view: &mut View,
|
|
||||||
) -> dock::UiResponse {
|
|
||||||
view.ui(ui)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tab_text_for_leaf(&mut self, view: &View) -> egui::WidgetText {
|
|
||||||
view.title.clone().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user