Fix performance issue with too many labels existing in the performance visualisation. (#3336)

This PR resolves the issue that too many text labels are created in the performance visualization.

https://user-images.githubusercontent.com/1428930/158601643-d8941752-2922-4551-9759-62fa468289ec.mp4

# Important Notes
[ci no changelog needed]
This commit is contained in:
Michael Mauderer 2022-03-17 12:44:40 +01:00 committed by GitHub
parent cdcc852e03
commit 28be22fea5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -7,7 +7,6 @@ use ensogl::frp;
use ensogl_core::application::Application;
use ensogl_core::data::color;
use ensogl_core::display;
use ensogl_core::display::scene::Layer;
use ensogl_core::display::shape::StyleWatchFrp;
use ensogl_core::Animation;
use ensogl_gui_component::component;
@ -23,6 +22,8 @@ use ensogl_text as text;
const TEXT_OFFSET_X: f32 = 4.0;
const TEXT_OFFSET_Y: f32 = -2.0;
const EMPTY_LABEL: &str = "<No Label>";
// =========================
@ -82,9 +83,17 @@ impl component::Frp<Model> for Frp {
eval self.set_content((t) model.set_content(t));
eval self.set_size((size) model.set_size(*size));
eval_ model.background.events.mouse_over(model.enable_label());
label_opacity.target <+ model.background.events.mouse_over.constant(1.0);
label_opacity.target <+ model.background.events.mouse_out.constant(0.0);
eval label_opacity.value ((t) model.set_label_opacity(*t));
eval label_opacity.value ([model](t){
if *t <= 0.0 {
model.disable_label()
}
});
}
label_opacity.target.emit(0.0);
@ -102,8 +111,9 @@ impl component::Frp<Model> for Frp {
pub struct Model {
app: Application,
background: background::View,
label: text::Area,
label: Rc<RefCell<Option<text::Area>>>,
display_object: display::object::Instance,
text: Rc<RefCell<Option<String>>>,
}
impl component::Model for Model {
@ -114,46 +124,62 @@ impl component::Model for Model {
fn new(app: &Application, logger: &Logger) -> Self {
let scene = &app.display.default_scene;
let display_object = display::object::Instance::new(&logger);
let label = app.new_view::<text::Area>();
let background = background::View::new(&logger);
let label = default();
let text = default();
let background = background::View::new(&logger);
display_object.add_child(&background);
display_object.add_child(&label);
scene.layers.tooltip.add_exclusive(&background);
let app = app.clone_ref();
let model = Model { app, background, label, display_object };
model.set_layers(&scene.layers.tooltip, &scene.layers.tooltip_text);
model
Model { app, background, label, display_object, text }
}
}
impl Model {
/// Set scene layers for background and text respectively.
pub fn set_layers(&self, background_layer: &Layer, text_layer: &Layer) {
// FIXME[MM/WD]: Depth sorting of labels to in front of everything else in the scene.
// Temporary solution. The depth management needs to allow defining relative position
// of the text and background and let the whole component to be set to am
// an arbitrary layer.
background_layer.add_exclusive(&self.background);
self.label.add_to_scene_layer(text_layer);
}
fn set_size(&self, size: Vector2) {
self.background.size.set(size);
let text_size = self.label.height.value();
let text_origin = Vector2(TEXT_OFFSET_X - size.x / 2.0, TEXT_OFFSET_Y + text_size / 2.0);
self.label.set_position_xy(text_origin);
}
fn set_content(&self, t: &str) {
self.label.set_content(t)
self.text.set(t.to_owned());
if let Some(label) = self.label.borrow().deref() {
label.set_content(t.to_owned())
}
}
fn set_label_opacity(&self, opacity: f32) {
let color = self.label.default_color.value();
let color: color::Rgba = color.opaque.with_alpha(opacity);
self.label.set_color_all.emit(color);
self.label.set_default_color.emit(color);
if let Some(label) = self.label.borrow().deref() {
let color = label.default_color.value();
let color: color::Rgba = color.opaque.with_alpha(opacity);
label.set_color_all.emit(color);
label.set_default_color.emit(color);
}
}
fn enable_label(&self) {
let label = self.app.new_view::<text::Area>();
self.add_child(&label);
let text_layer = &self.app.display.default_scene.layers.tooltip_text;
label.add_to_scene_layer(text_layer);
let text_size = label.height.value();
let text_origin = Vector2(
TEXT_OFFSET_X - self.background.size.get().x / 2.0,
TEXT_OFFSET_Y + text_size / 2.0,
);
label.set_position_xy(text_origin);
label.set_content(self.text.borrow().clone().unwrap_or_else(|| EMPTY_LABEL.to_owned()));
self.label.set(label);
self.set_label_opacity(0.0);
}
fn disable_label(&self) {
if let Some(label) = self.label.take() {
label.unset_parent()
}
}
}