Skip to content

Expose collapsing state in render hook #36

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

Merged
merged 8 commits into from
Nov 8, 2024
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
36 changes: 28 additions & 8 deletions examples/demo/src/apps/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use egui_json_tree::{
DefaultRender, RenderBaseValueContext, RenderContext, RenderExpandableDelimiterContext,
RenderPropertyContext,
},
DefaultExpand, JsonTree, JsonTreeStyle,
DefaultExpand, JsonTree, JsonTreeStyle, ToggleButtonsState,
};
use serde_json::Value;

Expand Down Expand Up @@ -154,7 +154,7 @@ impl Editor {
fn show_property_context_menu(
&mut self,
ui: &mut Ui,
context: RenderPropertyContext<'_, '_, Value>,
mut context: RenderPropertyContext<'_, '_, Value>,
) {
context
.render_default(ui)
Expand All @@ -164,13 +164,19 @@ impl Editor {
self.edit_events.push(EditEvent::AddToObject {
pointer: context.pointer.to_json_pointer_string(),
});
if let Some(state) = context.collapsing_state.as_mut() {
state.set_open(true);
}
ui.close_menu();
}

if context.value.is_array() && ui.button("Add to array").clicked() {
self.edit_events.push(EditEvent::AddToArray {
pointer: context.pointer.to_json_pointer_string(),
});
if let Some(state) = context.collapsing_state.as_mut() {
state.set_open(true);
}
ui.close_menu();
}

Expand Down Expand Up @@ -254,7 +260,10 @@ impl Editor {
context: RenderExpandableDelimiterContext<'_, '_, Value>,
) {
match context.delimiter {
ExpandableDelimiter::OpeningArray => {
ExpandableDelimiter::OpeningArray
| ExpandableDelimiter::CollapsedArray
| ExpandableDelimiter::CollapsedEmptyArray
| ExpandableDelimiter::ClosingArray => {
context
.render_default(ui)
.on_hover_cursor(CursorIcon::ContextMenu)
Expand All @@ -263,11 +272,15 @@ impl Editor {
self.edit_events.push(EditEvent::AddToArray {
pointer: context.pointer.to_json_pointer_string(),
});
context.collapsing_state.set_open(true);
ui.close_menu();
}
});
}
ExpandableDelimiter::OpeningObject => {
ExpandableDelimiter::OpeningObject
| ExpandableDelimiter::CollapsedObject
| ExpandableDelimiter::CollapsedEmptyObject
| ExpandableDelimiter::ClosingObject => {
context
.render_default(ui)
.on_hover_cursor(CursorIcon::ContextMenu)
Expand All @@ -276,13 +289,11 @@ impl Editor {
self.edit_events.push(EditEvent::AddToObject {
pointer: context.pointer.to_json_pointer_string(),
});
context.collapsing_state.set_open(true);
ui.close_menu();
}
});
}
_ => {
context.render_default(ui);
}
};
}

Expand Down Expand Up @@ -436,9 +447,18 @@ impl Show for JsonEditorExample {
ui.label("Right click on elements within the tree to edit values and object keys, and add/remove values.");
ui.add_space(10.0);

let toggle_buttons_state = match self.editor.state {
Some(_) => ToggleButtonsState::VisibleDisabled,
None => ToggleButtonsState::VisibleEnabled,
};

let style = JsonTreeStyle::new()
.abbreviate_root(true)
.toggle_buttons_state(toggle_buttons_state);

JsonTree::new(self.title(), &self.value)
.default_expand(DefaultExpand::All)
.style(JsonTreeStyle::new().abbreviate_root(true))
.style(style)
.on_render(|ui, context| self.editor.show(ui, &self.value, context))
.show(ui);

Expand Down
17 changes: 17 additions & 0 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ impl<'a, T: ToJsonTreeValue> JsonTreeNode<'a, T> {
pointer: JsonPointer(path_segments),
style: &config.style,
search_term: config.search_term.as_ref(),
collapsing_state: None,
},
);
renderer.render_spacing_delimiter(
Expand Down Expand Up @@ -219,6 +220,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
value: expandable.value,
pointer: JsonPointer(path_segments),
style,
collapsing_state: &mut state,
},
);
return;
Expand All @@ -231,6 +233,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
value: expandable.value,
pointer: JsonPointer(path_segments),
style,
collapsing_state: &mut state,
},
);
renderer.render_spacing_delimiter(
Expand All @@ -256,6 +259,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
pointer: JsonPointer(path_segments),
style,
search_term: search_term.as_ref(),
collapsing_state: Some(&mut state),
},
);
renderer.render_spacing_delimiter(
Expand Down Expand Up @@ -300,6 +304,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
value: elem,
pointer: JsonPointer(path_segments),
style,
collapsing_state: &mut state,
},
);
}
Expand Down Expand Up @@ -329,6 +334,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
value: expandable.value,
pointer: JsonPointer(path_segments),
style,
collapsing_state: &mut state,
},
);
} else {
Expand All @@ -341,6 +347,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
pointer: JsonPointer(path_segments),
style,
search_term: config.search_term.as_ref(),
collapsing_state: Some(&mut state),
},
);
renderer.render_spacing_delimiter(
Expand All @@ -360,6 +367,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
value: expandable.value,
pointer: JsonPointer(path_segments),
style,
collapsing_state: &mut state,
},
);
} else {
Expand All @@ -375,6 +383,7 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
value: expandable.value,
pointer: JsonPointer(path_segments),
style,
collapsing_state: &mut state,
},
);
}
Expand Down Expand Up @@ -442,9 +451,17 @@ fn show_expandable<'a, 'b, T: ToJsonTreeValue>(
value: expandable.value,
pointer: JsonPointer(path_segments),
style,
collapsing_state: &mut state,
},
);
});

if renderer.render_hook.is_some() {
// show_body_indented will store the CollapsingState,
// but since the subsequent render call above could also mutate the state in the render hook,
// we must store it again.
state.store(ui.ctx());
}
}
}

Expand Down
14 changes: 8 additions & 6 deletions src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::fmt::Display;

use egui::{
collapsing_header::CollapsingState,
text::LayoutJob,
util::cache::{ComputerMut, FrameCache},
Color32, FontId, Label, Response, Sense, TextFormat, Ui,
Expand All @@ -25,7 +26,6 @@ pub trait DefaultRender {
}

/// A handle to the information of a render call.
#[derive(Clone, Copy)]
pub enum RenderContext<'a, 'b, T: ToJsonTreeValue> {
/// A render call for an array index or an object key.
Property(RenderPropertyContext<'a, 'b, T>),
Expand Down Expand Up @@ -66,16 +66,18 @@ impl<'a, 'b, T: ToJsonTreeValue> RenderContext<'a, 'b, T> {
}

/// A handle to the information of a render call for an array index or object key.
#[derive(Clone, Copy)]
pub struct RenderPropertyContext<'a, 'b, T: ToJsonTreeValue> {
/// The array index or object key being rendered.
pub property: JsonPointerSegment<'a>,
/// The JSON array or object under this property.
/// The JSON value under this property.
pub value: &'a T,
/// The full JSON pointer to the array or object under this property.
pub pointer: JsonPointer<'a, 'b>,
/// The [`JsonTreeStyle`] that the [`JsonTree`](crate::JsonTree) was configured with.
pub style: &'b JsonTreeStyle,
/// If an array/object is under this property, contains the [`egui::collapsing_header::CollapsingState`] for it.
/// This can be used to toggle or check whether the array/object is expanded. Any mutations will be stored after the render hook.
pub collapsing_state: Option<&'b mut CollapsingState>,
pub(crate) search_term: Option<&'b SearchTerm>,
}

Expand All @@ -86,7 +88,6 @@ impl<'a, 'b, T: ToJsonTreeValue> DefaultRender for RenderPropertyContext<'a, 'b,
}

/// A handle to the information of a render call for a non-recursive JSON value.
#[derive(Clone, Copy)]
pub struct RenderBaseValueContext<'a, 'b, T: ToJsonTreeValue> {
/// The non-recursive JSON value being rendered.
pub value: &'a T,
Expand Down Expand Up @@ -114,7 +115,6 @@ impl<'a, 'b, T: ToJsonTreeValue> DefaultRender for RenderBaseValueContext<'a, 'b
}

/// A handle to the information of a render call for array brackets or object braces.
#[derive(Clone, Copy)]
pub struct RenderExpandableDelimiterContext<'a, 'b, T: ToJsonTreeValue> {
/// The specific token of the array bracket or object brace being rendered.
pub delimiter: ExpandableDelimiter,
Expand All @@ -124,6 +124,9 @@ pub struct RenderExpandableDelimiterContext<'a, 'b, T: ToJsonTreeValue> {
pub pointer: JsonPointer<'a, 'b>,
/// The [`JsonTreeStyle`] that the [`JsonTree`](crate::JsonTree) was configured with.
pub style: &'b JsonTreeStyle,
/// The [`egui::collapsing_header::CollapsingState`] for the array or object that this delimiter belongs to.
/// This can be used to toggle or check whether the array/object is expanded. Any mutations will be stored after the render hook.
pub collapsing_state: &'b mut CollapsingState,
}

impl<'a, 'b, T: ToJsonTreeValue> DefaultRender for RenderExpandableDelimiterContext<'a, 'b, T> {
Expand All @@ -132,7 +135,6 @@ impl<'a, 'b, T: ToJsonTreeValue> DefaultRender for RenderExpandableDelimiterCont
}
}

#[derive(Clone, Copy)]
pub(crate) struct RenderSpacingDelimiterContext<'b> {
pub(crate) delimiter: SpacingDelimiter,
pub(crate) style: &'b JsonTreeStyle,
Expand Down