mirror of
https://github.com/emilk/egui.git
synced 2026-07-13 01:58:53 +00:00
187 lines
5.0 KiB
Rust
187 lines
5.0 KiB
Rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
|
|
|
use eframe::egui;
|
|
use egui::Color32;
|
|
|
|
use egui_extras::dock;
|
|
|
|
fn main() -> Result<(), eframe::Error> {
|
|
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
|
let options = eframe::NativeOptions {
|
|
initial_window_size: Some(egui::vec2(800.0, 600.0)),
|
|
..Default::default()
|
|
};
|
|
eframe::run_native(
|
|
"Dock",
|
|
options,
|
|
Box::new(|cc| {
|
|
let mut app = MyApp::default();
|
|
if let Some(storage) = cc.storage {
|
|
if let Some(state) = eframe::get_value(storage, eframe::APP_KEY) {
|
|
app = state;
|
|
}
|
|
}
|
|
Box::new(app)
|
|
}),
|
|
)
|
|
}
|
|
|
|
#[derive(serde::Deserialize, serde::Serialize)]
|
|
pub struct View {
|
|
title: String,
|
|
color: Color32,
|
|
}
|
|
|
|
impl View {
|
|
pub fn with_nr(i: usize) -> Self {
|
|
Self {
|
|
title: format!("View {i}"),
|
|
color: egui::epaint::Hsva::new(0.1 * i as f32, 0.5, 0.5, 1.0).into(),
|
|
}
|
|
}
|
|
|
|
pub fn ui(&mut self, ui: &mut egui::Ui) -> dock::UiResponse {
|
|
ui.painter().rect_filled(ui.max_rect(), 0.0, self.color);
|
|
let dragged = ui
|
|
.add(
|
|
egui::Button::new(format!("Contents of {}. Drag me!", self.title))
|
|
.sense(egui::Sense::drag()),
|
|
)
|
|
.on_hover_cursor(egui::CursorIcon::Grab)
|
|
.dragged();
|
|
if dragged {
|
|
dock::UiResponse::DragStarted
|
|
} else {
|
|
dock::UiResponse::None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[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
|
|
}
|
|
}
|
|
|
|
#[derive(serde::Deserialize, serde::Serialize)]
|
|
struct MyApp {
|
|
dock: dock::Dock<View>,
|
|
|
|
#[serde(skip, default)]
|
|
behavior: DockBehavior,
|
|
}
|
|
|
|
impl Default for MyApp {
|
|
fn default() -> Self {
|
|
let mut next_view_nr = 0;
|
|
let mut gen_view = || {
|
|
let view = View::with_nr(next_view_nr);
|
|
next_view_nr += 1;
|
|
view
|
|
};
|
|
|
|
let mut nodes = dock::Nodes::default();
|
|
|
|
let tab0 = { nodes.insert_leaf(gen_view()) };
|
|
let tab1 = {
|
|
let a = nodes.insert_leaf(gen_view());
|
|
let b = nodes.insert_leaf(gen_view());
|
|
nodes.insert_tab_node(vec![a, b])
|
|
};
|
|
let tab2 = {
|
|
let a = nodes.insert_leaf(gen_view());
|
|
let b = nodes.insert_leaf(gen_view());
|
|
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 dock = dock::Dock::new(root, nodes);
|
|
|
|
Self {
|
|
dock,
|
|
behavior: Default::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl eframe::App for MyApp {
|
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
|
egui::SidePanel::left("tree").show(ctx, |ui| {
|
|
if ui.button("Reset").clicked() {
|
|
*self = Default::default();
|
|
}
|
|
ui.checkbox(
|
|
&mut self
|
|
.behavior
|
|
.simplification_options
|
|
.all_leaves_must_have_tabs,
|
|
"All views have tabs",
|
|
);
|
|
ui.separator();
|
|
|
|
tree_ui(ui, &mut self.behavior, &self.dock.nodes, self.dock.root);
|
|
});
|
|
|
|
egui::CentralPanel::default().show(ctx, |ui| {
|
|
self.dock.ui(&mut self.behavior, ui);
|
|
});
|
|
}
|
|
|
|
fn save(&mut self, storage: &mut dyn eframe::Storage) {
|
|
eframe::set_value(storage, eframe::APP_KEY, &self);
|
|
}
|
|
}
|
|
|
|
fn tree_ui(
|
|
ui: &mut egui::Ui,
|
|
behavior: &mut dyn dock::Behavior<View>,
|
|
nodes: &dock::Nodes<View>,
|
|
node_id: dock::NodeId,
|
|
) {
|
|
let Some(node) = nodes.get(node_id) else { return; };
|
|
|
|
// if let dock::NodeLayout::Leaf(view) = node {
|
|
// ui.label(&view.title);
|
|
// return;
|
|
// }
|
|
|
|
let text = format!(
|
|
"{} - {node_id:?}",
|
|
behavior.tab_text_for_node(nodes, node_id).text()
|
|
);
|
|
|
|
egui::CollapsingHeader::new(text)
|
|
.id_source((node_id, "tree"))
|
|
.default_open(true)
|
|
.show(ui, |ui| match node {
|
|
dock::Node::Leaf(_) => {}
|
|
dock::Node::Branch(branch) => {
|
|
for &child in &branch.children {
|
|
tree_ui(ui, behavior, nodes, child);
|
|
}
|
|
}
|
|
});
|
|
}
|