mirror of https://github.com/wayvr-org/wayvr.git
fix tooltips staying after parent is gone
This commit is contained in:
parent
acaabead52
commit
c74c51f7cd
|
|
@ -206,7 +206,10 @@ impl<S: 'static> GuiPanel<S> {
|
|||
setup_custom_label::<S>(&mut self.layout, &self.parser_state, elem, app);
|
||||
} else if let Ok(button) = self
|
||||
.parser_state
|
||||
.fetch_component_from_widget_id_as::<ComponentButton>(&self.layout.state, elem.widget_id)
|
||||
.fetch_component_from_widget_id_as::<ComponentButton>(
|
||||
&self.layout.state,
|
||||
elem.widget_id,
|
||||
)
|
||||
{
|
||||
setup_custom_button::<S>(
|
||||
&mut self.layout,
|
||||
|
|
|
|||
|
|
@ -372,8 +372,8 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
|
|||
let anim_mult = app.wgui_theme.animation_mult;
|
||||
|
||||
let on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, parser, attribs, _app| {
|
||||
let Ok(button) =
|
||||
parser.fetch_component_from_widget_id_as::<ComponentButton>(&layout.state, attribs.widget_id)
|
||||
let Ok(button) = parser
|
||||
.fetch_component_from_widget_id_as::<ComponentButton>(&layout.state, attribs.widget_id)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ fn find_children<S>(
|
|||
.layout
|
||||
.collect_children_ids_recursive(widget_id, &mut children);
|
||||
|
||||
for (child, _) in children {
|
||||
for child in children {
|
||||
if let Some(widget) = panel.layout.state.widgets.get_as::<WidgetSprite>(child) {
|
||||
sprites.push(ChildWidget {
|
||||
id: child,
|
||||
|
|
|
|||
|
|
@ -204,9 +204,10 @@ impl WvrWindowBackend {
|
|||
|
||||
let on_custom_attrib: OnCustomAttribFunc =
|
||||
Box::new(move |layout, parser, attribs, _app| {
|
||||
let Ok(button) =
|
||||
parser.fetch_component_from_widget_id_as::<ComponentButton>(&layout.state, attribs.widget_id)
|
||||
else {
|
||||
let Ok(button) = parser.fetch_component_from_widget_id_as::<ComponentButton>(
|
||||
&layout.state,
|
||||
attribs.widget_id,
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ pub fn create_whisper(
|
|||
let xml = "gui/whisper.xml";
|
||||
|
||||
let on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, parser, attribs, _app| {
|
||||
let Ok(button) =
|
||||
parser.fetch_component_from_widget_id_as::<ComponentButton>(&layout.state, attribs.widget_id)
|
||||
let Ok(button) = parser
|
||||
.fetch_component_from_widget_id_as::<ComponentButton>(&layout.state, attribs.widget_id)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ impl ComponentTrait for ComponentButton {
|
|||
.layout
|
||||
.collect_children_ids_recursive(self.data.id_rect, &mut children);
|
||||
|
||||
for (child, _) in children {
|
||||
for child in children {
|
||||
if let Some(mut widget) = data.layout.state.widgets.get_as::<WidgetSprite>(child) {
|
||||
if !state.id_sprite.is_null() && state.id_sprite != child {
|
||||
log::error!("Button with more than one sprite!");
|
||||
|
|
@ -184,6 +184,13 @@ impl ComponentTrait for ComponentButton {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy(&self, data: &mut components::DestroyData) {
|
||||
if let Some(comp) = self.state.borrow_mut().active_tooltip.take() {
|
||||
comp.destroy(data);
|
||||
data.destroy_widgets.push(comp.base().id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_color2(color: &WguiColor, gradient_intensity: f32) -> WguiColor {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
animation::{Animation, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::{
|
||||
Component, ComponentBase, ComponentTrait, RefreshData,
|
||||
Component, ComponentBase, ComponentTrait, DestroyData, RefreshData,
|
||||
radio_group::ComponentRadioGroup,
|
||||
tooltip::{self, ComponentTooltip, TooltipTrait},
|
||||
},
|
||||
|
|
@ -111,6 +111,13 @@ impl ComponentTrait for ComponentCheckbox {
|
|||
fn refresh(&self, _data: &mut RefreshData) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
fn destroy(&self, data: &mut DestroyData) {
|
||||
if let Some(comp) = self.state.borrow_mut().active_tooltip.take() {
|
||||
comp.destroy(data);
|
||||
data.destroy_widgets.push(comp.base().id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_box_checked(widgets: &layout::WidgetMap, data: &Data, checked: bool, hovered: bool) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ pub struct RefreshData<'a> {
|
|||
pub layout: &'a mut Layout,
|
||||
}
|
||||
|
||||
pub struct DestroyData<'a> {
|
||||
pub layout: &'a mut Layout,
|
||||
pub destroy_widgets: &'a mut Vec<WidgetID>,
|
||||
}
|
||||
|
||||
pub struct FocusChangeData<'a> {
|
||||
pub common: &'a mut CallbackDataCommon<'a>,
|
||||
pub focused: bool,
|
||||
|
|
@ -49,6 +54,7 @@ pub trait ComponentTrait: AnyTrait {
|
|||
fn base_mut(&mut self) -> &mut ComponentBase;
|
||||
fn refresh(&self, data: &mut RefreshData);
|
||||
fn on_focus_change(&self, _data: &mut FocusChangeData) {}
|
||||
fn destroy(&self, _data: &mut DestroyData) {}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
animation::{Animation, AnimationCallback, AnimationEasing},
|
||||
color::{WguiColor, WguiColorName},
|
||||
components::{
|
||||
Component, ComponentBase, ComponentTrait, RefreshData,
|
||||
Component, ComponentBase, ComponentTrait, DestroyData, RefreshData,
|
||||
tooltip::{self, ComponentTooltip, TooltipTrait},
|
||||
},
|
||||
event::{
|
||||
|
|
@ -160,6 +160,13 @@ impl ComponentTrait for ComponentSlider {
|
|||
fn base_mut(&mut self) -> &mut ComponentBase {
|
||||
&mut self.base
|
||||
}
|
||||
|
||||
fn destroy(&self, data: &mut DestroyData) {
|
||||
if let Some(comp) = self.state.borrow_mut().active_tooltip.take() {
|
||||
comp.destroy(data);
|
||||
data.destroy_widgets.push(comp.base().id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentSlider {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
assets::AssetPathRc,
|
||||
color::WguiColor,
|
||||
components::{
|
||||
Component, ComponentBase, ComponentTrait, RefreshData,
|
||||
Component, ComponentBase, ComponentTrait, DestroyData, RefreshData,
|
||||
button::{self, ComponentButton},
|
||||
},
|
||||
event::CallbackDataCommon,
|
||||
|
|
@ -71,6 +71,13 @@ impl ComponentTrait for ComponentTabs {
|
|||
fn refresh(&self, _data: &mut RefreshData) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
fn destroy(&self, data: &mut DestroyData) {
|
||||
for e in self.state.borrow_mut().mounted_entries.drain(..) {
|
||||
e.button.destroy(data);
|
||||
data.destroy_widgets.push(e.button.base().id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use std::{
|
|||
|
||||
use crate::{
|
||||
animation::Animations,
|
||||
components::{self, Component, ComponentWeak, FocusChangeData, RefreshData},
|
||||
components::{self, Component, ComponentWeak, DestroyData, FocusChangeData, RefreshData},
|
||||
drawing::{
|
||||
self, ANSI_BOLD_CODE, ANSI_RESET_CODE, Boundary, PushScissorStackResult, push_scissor_stack, push_transform_stack,
|
||||
},
|
||||
|
|
@ -283,21 +283,35 @@ impl Layout {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn collect_children_ids_recursive(&self, widget_id: WidgetID, out: &mut Vec<(WidgetID, taffy::NodeId)>) {
|
||||
pub fn collect_children_ids_recursive(&self, widget_id: WidgetID, out: &mut Vec<WidgetID>) {
|
||||
let Some(node_id) = self.state.nodes.get(widget_id) else {
|
||||
return;
|
||||
};
|
||||
|
||||
for child_id in self.state.tree.child_ids(*node_id) {
|
||||
let child_widget_id = self.state.tree.get_node_context(child_id).unwrap();
|
||||
out.push((*child_widget_id, child_id));
|
||||
out.push(*child_widget_id);
|
||||
self.collect_children_ids_recursive(*child_widget_id, out);
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_widget_single(&mut self, widget_id: WidgetID, node_id: Option<taffy::NodeId>) {
|
||||
fn remove_widget_single(&mut self, widget_id: WidgetID) {
|
||||
self.state.widgets.remove_single(widget_id);
|
||||
self.state.nodes.remove(widget_id);
|
||||
let node_id = self.state.nodes.remove(widget_id);
|
||||
|
||||
if let Some(component_weak) = self.state.components_by_widget_id.remove(widget_id)
|
||||
&& let Some(component) = component_weak.upgrade()
|
||||
{
|
||||
let mut destroy_widgets = vec![];
|
||||
component.destroy(&mut DestroyData {
|
||||
layout: self,
|
||||
destroy_widgets: &mut destroy_widgets,
|
||||
});
|
||||
for wid in destroy_widgets {
|
||||
self.remove_widget_single(wid);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(node_id) = node_id {
|
||||
self.registered_components_to_refresh.remove(&node_id);
|
||||
let _ = self.state.tree.remove(node_id);
|
||||
|
|
@ -313,16 +327,15 @@ impl Layout {
|
|||
self.mark_redraw();
|
||||
}
|
||||
|
||||
for (widget_id, node_id) in ids {
|
||||
self.remove_widget_single(widget_id, Some(node_id));
|
||||
for widget_id in ids {
|
||||
self.remove_widget_single(widget_id);
|
||||
}
|
||||
}
|
||||
|
||||
// remove widget and its children, recursively
|
||||
pub fn remove_widget(&mut self, widget_id: WidgetID) {
|
||||
self.remove_children(widget_id);
|
||||
let node_id = self.state.nodes.get(widget_id);
|
||||
self.remove_widget_single(widget_id, node_id.copied());
|
||||
self.remove_widget_single(widget_id);
|
||||
self.mark_redraw();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,11 @@ pub trait Fetchable {
|
|||
fn fetch_component_as<T: 'static>(&self, id: &str) -> anyhow::Result<Rc<T>>;
|
||||
|
||||
/// Fetch a component by widget ID and down‑cast it to a concrete component type `T` (see `components/mod.rs`)
|
||||
fn fetch_component_from_widget_id_as<T: 'static>(&self, state: &LayoutState, widget_id: WidgetID) -> anyhow::Result<Rc<T>>;
|
||||
fn fetch_component_from_widget_id_as<T: 'static>(
|
||||
&self,
|
||||
state: &LayoutState,
|
||||
widget_id: WidgetID,
|
||||
) -> anyhow::Result<Rc<T>>;
|
||||
|
||||
/// Return a widget by its string ID
|
||||
fn get_widget_id(&self, id: &str) -> anyhow::Result<WidgetID>;
|
||||
|
|
@ -168,7 +172,11 @@ impl Fetchable for ParserData {
|
|||
state.fetch_component_by_widget_id(widget_id)
|
||||
}
|
||||
|
||||
fn fetch_component_from_widget_id_as<T: 'static>(&self, state: &LayoutState, widget_id: WidgetID) -> anyhow::Result<Rc<T>> {
|
||||
fn fetch_component_from_widget_id_as<T: 'static>(
|
||||
&self,
|
||||
state: &LayoutState,
|
||||
widget_id: WidgetID,
|
||||
) -> anyhow::Result<Rc<T>> {
|
||||
state.fetch_component_from_widget_id_as(widget_id)
|
||||
}
|
||||
|
||||
|
|
@ -381,7 +389,11 @@ impl Fetchable for ParserState {
|
|||
self.data.fetch_component_by_widget_id(state, widget_id)
|
||||
}
|
||||
|
||||
fn fetch_component_from_widget_id_as<T: 'static>(&self, state: &LayoutState, widget_id: WidgetID) -> anyhow::Result<Rc<T>> {
|
||||
fn fetch_component_from_widget_id_as<T: 'static>(
|
||||
&self,
|
||||
state: &LayoutState,
|
||||
widget_id: WidgetID,
|
||||
) -> anyhow::Result<Rc<T>> {
|
||||
self.data.fetch_component_from_widget_id_as(state, widget_id)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue