1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 06:10:06 -04:00

Collapsing header with custom header (#1538)

* Returns openness in CollapsingResponse
* Make CollapsingState a building block for custom collapsing headers
* Add a demo of the custom collapsing header
* Revert to much simpler tree demo
* Add CollapsingState::is_open and CollapsingState::set_open
This commit is contained in:
Emil Ernerfeldt
2022-04-28 11:09:44 +02:00
committed by GitHub
parent 8e266760e2
commit 39917bec26
7 changed files with 323 additions and 144 deletions

View File

@@ -14,6 +14,7 @@ pub struct MiscDemoWindow {
widgets: Widgets,
colors: ColorWidgets,
custom_collapsing_header: CustomCollapsingHeader,
tree: Tree,
box_painting: BoxPainting,
@@ -32,6 +33,7 @@ impl Default for MiscDemoWindow {
widgets: Default::default(),
colors: Default::default(),
custom_collapsing_header: Default::default(),
tree: Tree::demo(),
box_painting: Default::default(),
@@ -82,6 +84,10 @@ impl View for MiscDemoWindow {
self.colors.ui(ui);
});
CollapsingHeader::new("Custom Collapsing Header")
.default_open(false)
.show(ui, |ui| self.custom_collapsing_header.ui(ui));
CollapsingHeader::new("Tree")
.default_open(false)
.show(ui, |ui| self.tree.ui(ui));
@@ -351,6 +357,44 @@ impl BoxPainting {
// ----------------------------------------------------------------------------
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct CustomCollapsingHeader {
selected: bool,
radio_value: bool,
}
impl Default for CustomCollapsingHeader {
fn default() -> Self {
Self {
selected: true,
radio_value: false,
}
}
}
impl CustomCollapsingHeader {
pub fn ui(&mut self, ui: &mut egui::Ui) {
ui.label("Example of a collapsing header with custom header:");
let id = ui.make_persistent_id("my_collapsing_header");
egui::collapsing_header::CollapsingState::load_with_default_open(ui.ctx(), id, true)
.show_header(ui, |ui| {
ui.toggle_value(&mut self.selected, "Click to select/unselect");
ui.radio_value(&mut self.radio_value, false, "");
ui.radio_value(&mut self.radio_value, true, "");
})
.body(|ui| {
ui.label("The body is always custom");
});
CollapsingHeader::new("Normal collapsing header for comparison").show(ui, |ui| {
ui.label("Nothing exciting here");
});
}
}
// ----------------------------------------------------------------------------
#[derive(Clone, Copy, PartialEq)]
enum Action {
Keep,
@@ -359,53 +403,30 @@ enum Action {
#[derive(Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct Tree(String, SubTree);
struct Tree(Vec<Tree>);
impl Tree {
pub fn demo() -> Self {
Self(
String::from("root"),
SubTree(vec![
SubTree(vec![SubTree::default(); 4]),
SubTree(vec![SubTree(vec![SubTree::default(); 2]); 3]),
]),
)
Self(vec![
Tree(vec![Tree::default(); 4]),
Tree(vec![Tree(vec![Tree::default(); 2]); 3]),
])
}
pub fn ui(&mut self, ui: &mut Ui) -> Action {
self.1.ui(ui, 0, "root", &mut self.0)
self.ui_impl(ui, 0, "root")
}
}
#[derive(Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
struct SubTree(Vec<SubTree>);
impl SubTree {
pub fn ui(
&mut self,
ui: &mut Ui,
depth: usize,
name: &str,
selected_name: &mut String,
) -> Action {
let response = CollapsingHeader::new(name)
impl Tree {
fn ui_impl(&mut self, ui: &mut Ui, depth: usize, name: &str) -> Action {
CollapsingHeader::new(name)
.default_open(depth < 1)
.selectable(true)
.selected(selected_name.as_str() == name)
.show(ui, |ui| self.children_ui(ui, name, depth, selected_name));
if response.header_response.clicked() {
*selected_name = name.to_string();
}
response.body_returned.unwrap_or(Action::Keep)
.show(ui, |ui| self.children_ui(ui, depth))
.body_returned
.unwrap_or(Action::Keep)
}
fn children_ui(
&mut self,
ui: &mut Ui,
parent_name: &str,
depth: usize,
selected_name: &mut String,
) -> Action {
fn children_ui(&mut self, ui: &mut Ui, depth: usize) -> Action {
if depth > 0
&& ui
.button(RichText::new("delete").color(Color32::RED))
@@ -419,13 +440,7 @@ impl SubTree {
.into_iter()
.enumerate()
.filter_map(|(i, mut tree)| {
if tree.ui(
ui,
depth + 1,
&format!("{}/{}", parent_name, i),
selected_name,
) == Action::Keep
{
if tree.ui_impl(ui, depth + 1, &format!("child #{}", i)) == Action::Keep {
Some(tree)
} else {
None
@@ -434,7 +449,7 @@ impl SubTree {
.collect();
if ui.button("+").clicked() {
self.0.push(SubTree::default());
self.0.push(Tree::default());
}
Action::Keep