init
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
//! Runnable demo: `cargo run --example grimdemo`
|
||||
//!
|
||||
//! Opens a window with a pre-built split layout. Tabs can be dragged between
|
||||
//! panes, panes can be resized by dragging the handle between them.
|
||||
|
||||
use eframe::egui;
|
||||
use grimdock::{
|
||||
AddTabEntry, ChildSide, DropPolicy, Node, PaneBuilder, PaneStyleOverride, PanelContext,
|
||||
PanelStyle, PanelTree, SplitDir, Tab, TabStyleOverride,
|
||||
};
|
||||
|
||||
fn main() -> eframe::Result<()> {
|
||||
let options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default()
|
||||
.with_title("grimdock demo")
|
||||
.with_inner_size([1024.0, 680.0]),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
"grimdock demo",
|
||||
options,
|
||||
Box::new(|_cc| Ok(Box::new(App::new()))),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
enum TabId {
|
||||
Editor(u32),
|
||||
FileTree,
|
||||
Terminal,
|
||||
Search,
|
||||
Problems,
|
||||
Output,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for TabId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
TabId::Editor(n) => write!(f, "editor_{n}"),
|
||||
TabId::FileTree => write!(f, "file_tree"),
|
||||
TabId::Terminal => write!(f, "terminal"),
|
||||
TabId::Search => write!(f, "search"),
|
||||
TabId::Problems => write!(f, "problems"),
|
||||
TabId::Output => write!(f, "output"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct App {
|
||||
tree: PanelTree<TabId>,
|
||||
tick: u64,
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn new() -> Self {
|
||||
let mut tree = PanelTree::new(vec![
|
||||
Tab::new("editor_1", TabId::Editor(1))
|
||||
.with_leading_visual(">")
|
||||
.with_style_override(TabStyleOverride {
|
||||
active_bg: Some(egui::Color32::from_rgb(62, 73, 50)),
|
||||
inactive_bg: Some(egui::Color32::from_rgb(44, 52, 38)),
|
||||
hovered_bg: Some(egui::Color32::from_rgb(55, 65, 45)),
|
||||
text_color: Some(egui::Color32::from_rgb(221, 231, 200)),
|
||||
accent_color: Some(egui::Color32::from_rgb(164, 196, 92)),
|
||||
icon_color: None,
|
||||
max_width: None,
|
||||
}),
|
||||
Tab::new("editor_2", TabId::Editor(2)).with_leading_visual("+"),
|
||||
]);
|
||||
|
||||
let _file_tree_pane = tree.split_leaf_with(
|
||||
0,
|
||||
SplitDir::Horizontal,
|
||||
PaneBuilder::new(Tab::new("file_tree", TabId::FileTree).with_leading_visual("#"))
|
||||
.with_options(grimdock::PaneOptions {
|
||||
style_override: Some(PaneStyleOverride {
|
||||
header_bg: Some(egui::Color32::from_rgb(27, 47, 44)),
|
||||
content_bg: Some(egui::Color32::from_rgb(21, 36, 34)),
|
||||
border_color: Some(egui::Color32::from_rgb(52, 90, 84)),
|
||||
accent_color: Some(egui::Color32::from_rgb(85, 188, 162)),
|
||||
}),
|
||||
drop_policy: DropPolicy::merge_only(),
|
||||
..Default::default()
|
||||
}),
|
||||
ChildSide::First,
|
||||
);
|
||||
|
||||
let editors_pane = tree
|
||||
.find_pane_containing(&TabId::Editor(1))
|
||||
.expect("editor pane should exist after initial split");
|
||||
let bottom_pane = {
|
||||
let mut pane = tree
|
||||
.pane_mut(editors_pane)
|
||||
.expect("editor pane should exist");
|
||||
pane.split_with(
|
||||
SplitDir::Vertical,
|
||||
PaneBuilder::new(Tab::new("terminal", TabId::Terminal).with_leading_visual("$")),
|
||||
ChildSide::Second,
|
||||
)
|
||||
};
|
||||
|
||||
let mut bottom = tree
|
||||
.pane_mut(bottom_pane)
|
||||
.expect("bottom pane should exist");
|
||||
bottom.push_tab(Tab::new("output", TabId::Output).with_leading_visual("!"));
|
||||
bottom.push_tab(Tab::new("problems", TabId::Problems).with_leading_visual("x"));
|
||||
bottom.push_tab(Tab::new("search", TabId::Search).with_leading_visual("?"));
|
||||
|
||||
if let Node::Split { ratio, .. } = tree.node_mut(0) {
|
||||
*ratio = 0.22;
|
||||
}
|
||||
|
||||
if let Node::Split { ratio, .. } = tree.node_mut(2) {
|
||||
*ratio = 0.65;
|
||||
}
|
||||
|
||||
Self { tree, tick: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for App {
|
||||
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
|
||||
self.tick += 1;
|
||||
|
||||
let ctx = ui.ctx().clone();
|
||||
|
||||
egui::CentralPanel::default()
|
||||
.frame(egui::Frame::NONE)
|
||||
.show_inside(ui, |ui| {
|
||||
let tree = &mut self.tree;
|
||||
let mut style = PanelStyle::from_egui_style(ui.style().as_ref());
|
||||
style.content_inset = 4.0;
|
||||
style.tabs.rounding = egui::CornerRadius::same(5);
|
||||
style.header.button.rounding = egui::CornerRadius::same(5);
|
||||
let tick = self.tick;
|
||||
let add_tab_entries = vec![
|
||||
AddTabEntry::new(
|
||||
"Editor 3",
|
||||
Tab::new("editor_3", TabId::Editor(3))
|
||||
.with_leading_visual("*")
|
||||
.with_closable(true),
|
||||
),
|
||||
AddTabEntry::new(
|
||||
"Terminal",
|
||||
Tab::new("terminal", TabId::Terminal)
|
||||
.with_leading_visual("$")
|
||||
.with_closable(true),
|
||||
),
|
||||
AddTabEntry::new(
|
||||
"Search",
|
||||
Tab::new("search", TabId::Search)
|
||||
.with_leading_visual("?")
|
||||
.with_closable(true),
|
||||
),
|
||||
AddTabEntry::new(
|
||||
"Problems",
|
||||
Tab::new("problems", TabId::Problems)
|
||||
.with_leading_visual("x")
|
||||
.with_closable(true),
|
||||
),
|
||||
];
|
||||
|
||||
PanelContext::new(ui, tree, &style)
|
||||
.with_add_tab_entries(&add_tab_entries)
|
||||
.show(|ui, tab_id| {
|
||||
render_tab(ui, tab_id, tick);
|
||||
});
|
||||
});
|
||||
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
|
||||
fn render_tab(ui: &mut egui::Ui, tab_id: &TabId, tick: u64) {
|
||||
egui::ScrollArea::vertical().show(ui, |ui| match tab_id {
|
||||
TabId::Editor(n) => {
|
||||
ui.add_space(8.0);
|
||||
ui.label(
|
||||
egui::RichText::new(format!(
|
||||
"// Editor {n}\n\nfn main() {{\n println!(\"Hello, world!\");\n}}"
|
||||
))
|
||||
.monospace()
|
||||
.size(13.0),
|
||||
);
|
||||
ui.add_space(8.0);
|
||||
ui.label("Drag a tab to a different pane to rearrange.");
|
||||
ui.label("Drag the handle between panes to resize.");
|
||||
}
|
||||
TabId::FileTree => {
|
||||
ui.add_space(6.0);
|
||||
for item in &[
|
||||
"src/",
|
||||
" lib.rs",
|
||||
" tree.rs",
|
||||
" layout.rs",
|
||||
" header.rs",
|
||||
" dnd.rs",
|
||||
"Cargo.toml",
|
||||
] {
|
||||
ui.label(egui::RichText::new(*item).monospace().size(12.0));
|
||||
}
|
||||
}
|
||||
TabId::Terminal => {
|
||||
ui.add_space(4.0);
|
||||
ui.label(
|
||||
egui::RichText::new(format!("$ frame {tick}"))
|
||||
.monospace()
|
||||
.size(12.0),
|
||||
);
|
||||
ui.label(
|
||||
egui::RichText::new("grimdock running ✓")
|
||||
.monospace()
|
||||
.color(egui::Color32::from_rgb(100, 200, 120))
|
||||
.size(12.0),
|
||||
);
|
||||
}
|
||||
TabId::Search => {
|
||||
ui.add_space(8.0);
|
||||
ui.label("Search");
|
||||
ui.text_edit_singleline(&mut String::new());
|
||||
}
|
||||
TabId::Problems => {
|
||||
ui.add_space(8.0);
|
||||
ui.label(
|
||||
egui::RichText::new("No problems detected.")
|
||||
.color(egui::Color32::from_rgb(100, 200, 120)),
|
||||
);
|
||||
}
|
||||
TabId::Output => {
|
||||
ui.add_space(4.0);
|
||||
ui.label(
|
||||
egui::RichText::new("[INFO] Build complete.")
|
||||
.monospace()
|
||||
.size(12.0),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user