Skip to content
This repository has been archived by the owner on Dec 28, 2021. It is now read-only.

Commit

Permalink
feat: Show visualization on output port hover.
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelMauderer committed Mar 23, 2021
1 parent a59a3b5 commit d012500
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 76 deletions.
1 change: 1 addition & 0 deletions src/rust/ensogl/lib/core/src/animation/frp/animation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! FRP bindings to the animation engine.

pub mod hysteretic;
pub mod delayed;

use crate::prelude::*;

Expand Down
82 changes: 82 additions & 0 deletions src/rust/ensogl/lib/core/src/animation/frp/animation/delayed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//! Animation that has a delayed onset.
use crate::prelude::*;

use crate::Easing;

use enso_frp as frp;



// ===========
// === Frp ===
// ===========

crate::define_endpoints! {
Input {
/// Start the onset of the animation. After the specified delay, the animation will run
/// with the specified duration.
start(),
/// Reset animation immediately to 0.0.
reset(),
/// Set the onset delay of the animation.
set_delay(f32),
/// Set the duration of the animation.
set_duration(f32),
}
Output {
/// Represents the numeric state of the animation in the range 0...1.
value(f32),
/// Triggered when the state reaches 1.0.
on_end(),
/// Triggered when the state reaches 0.0.
on_reset(),
}
}



// =========================
// === DelayedAnimation ===
// =========================

/// Animation that has a delayed onset.
#[derive(CloneRef,Debug,Shrinkwrap)]
pub struct DelayedAnimation {
#[allow(missing_docs)]
pub frp : FrpEndpoints,
}

impl DelayedAnimation {
#[allow(missing_docs)]
pub fn new(network:&frp::Network) -> Self {
let frp = Frp::extend(network);
let delay = Easing::new(network);
let transition = Easing::new(network);

frp::extend! { network
// Set delay duration.
delay.set_duration <+ frp.set_delay;
transition.set_duration <+ frp.set_duration;

// Start the delay.
delay.target <+ frp.start.constant(1.0);

// End delay if 1.0 reached.
delay_end <- delay.value.map(|t| (t - 1.0).abs() < std::f32::EPSILON).on_true();

// Start animation.
transition.target <+ delay_end.constant(1.0);

// Reset the animation and delay.
delay.stop_and_rewind <+ frp.reset.constant(0.0);
transition.stop_and_rewind <+ frp.reset.constant(0.0);

// Output bindings.
frp.source.value <+ transition.value;
frp.source.on_reset <+ transition.value.map(|t| (t - 0.0).abs() < std::f32::EPSILON).on_true();
frp.source.on_end <+ transition.value.map(|t| (t - 1.0).abs() < std::f32::EPSILON).on_true();
}

Self{frp}
}
}
2 changes: 1 addition & 1 deletion src/rust/ensogl/lib/theme/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ define_themes! { [light:0, dark:1]
size = 12.0, 12.0;
}
padding = 15.0, 15.0;
height = 36.0, 36.0;
height = 30.0, 30.0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ pub struct Input {
#[derive(Clone,CloneRef,Debug)]
#[allow(missing_docs)]
pub struct Error {
pub frp : visualization::instance::Frp,
model : Model,
frp : visualization::instance::Frp,
network : frp::Network,
}

Expand All @@ -95,12 +95,12 @@ impl Error {
let path = Self::path();
Definition::new(
Signature::new_for_any_type(path,Format::Json),
|scene| { Ok(Self::new(scene).into()) }
|scene| { Ok(Self::new(scene.clone_ref()).into()) }
)
}

/// Constructor.
pub fn new(scene:&Scene) -> Self {
pub fn new(scene:Scene) -> Self {
let network = frp::Network::new("js_visualization_raw_text");
let frp = visualization::instance::Frp::new(&network);
let model = Model::new(scene);
Expand All @@ -113,11 +113,12 @@ impl Error {
let frp = self.frp.clone_ref();
frp::extend! { network
eval frp.set_size ((size) model.set_size(*size));
eval frp.send_data ([frp](data) {
eval frp.send_data ([frp,model](data) {
if let Err(e) = model.receive_data(data) {
frp.data_receive_error.emit(Some(e));
}
});
eval frp.set_layer ((layer) model.set_layer(*layer));
}

frp.preprocessor_change.emit(preprocessor());
Expand Down Expand Up @@ -152,11 +153,12 @@ pub struct Model {
// when payload changes.
displayed : Rc<CloneCell<Kind>>,
messages : SharedHashMap<Kind,ImString>,
scene : Scene,
}

impl Model {
/// Constructor.
fn new(scene:&Scene) -> Self {
fn new(scene:Scene) -> Self {
let logger = Logger::new("RawText");
let div = web::create_div();
let dom = DomSymbol::new(&div);
Expand All @@ -177,7 +179,7 @@ impl Model {
dom.dom().set_style_or_warn("pointer-events","auto" ,&logger);

scene.dom.layers.back.manage(&dom);
Model{dom,logger,size,styles,displayed,messages}.init()
Model{dom,logger,size,styles,displayed,messages,scene}.init()
}

fn init(self) -> Self {
Expand Down Expand Up @@ -242,6 +244,10 @@ impl Model {
let text_color = format!("rgba({},{},{},{})",red,green,blue,text_color.alpha);
self.dom.dom().set_style_or_warn("color",text_color,&self.logger);
}

fn set_layer(&self, layer:Layer) {
layer.apply_for_html_component(&self.scene,&self.dom)
}
}

impl From<Error> for Instance {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ impl RawText {
let path = Path::builtin("JSON");
Definition::new(
Signature::new_for_any_type(path,Format::Json),
|scene| { Ok(Self::new(scene).into()) }
|scene| { Ok(Self::new(scene.clone_ref()).into()) }
)
}

/// Constructor.
pub fn new(scene:&Scene) -> Self {
pub fn new(scene:Scene) -> Self {
let network = frp::Network::new("js_visualization_raw_text");
let frp = visualization::instance::Frp::new(&network);
let model = RawTextModel::new(scene);
Expand All @@ -63,11 +63,12 @@ impl RawText {
let frp = self.frp.clone_ref();
frp::extend! { network
eval frp.set_size ((size) model.set_size(*size));
eval frp.send_data ([frp](data) {
eval frp.send_data ([frp,model](data) {
if let Err(e) = model.receive_data(data) {
frp.data_receive_error.emit(Some(e));
}
});
eval frp.set_layer ((layer) model.set_layer(*layer));
}
self
}
Expand All @@ -79,11 +80,12 @@ pub struct RawTextModel {
logger : Logger,
dom : DomSymbol,
size : Rc<Cell<Vector2>>,
scene : Scene,
}

impl RawTextModel {
/// Constructor.
fn new(scene:&Scene) -> Self {
fn new(scene:Scene) -> Self {
let logger = Logger::new("RawText");
let div = web::create_div();
let dom = DomSymbol::new(&div);
Expand Down Expand Up @@ -111,7 +113,7 @@ impl RawTextModel {
dom.dom().set_style_or_warn("pointer-events","auto" ,&logger);

scene.dom.layers.back.manage(&dom);
RawTextModel{dom,logger,size}.init()
RawTextModel{dom,logger,size,scene}.init()
}

fn init(self) -> Self {
Expand Down Expand Up @@ -141,6 +143,10 @@ impl RawTextModel {
fn reload_style(&self) {
self.dom.set_size(self.size.get());
}

fn set_layer(&self, layer:Layer) {
layer.apply_for_html_component(&self.scene,&self.dom)
}
}

impl From<RawText> for Instance {
Expand Down
88 changes: 73 additions & 15 deletions src/rust/ide/view/graph-editor/src/component/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::tooltip;
use enso_frp as frp;
use enso_frp;
use ensogl::Animation;
use ensogl::animation::delayed::DelayedAnimation;
use ensogl::application::Application;
use ensogl::data::color;
use ensogl::display::shape::*;
Expand Down Expand Up @@ -59,6 +60,9 @@ const ERROR_VISUALIZATION_SIZE : (f32,f32) = visualization::container::DEF

const VISUALIZATION_OFFSET_Y : f32 = -120.0;

const VIS_PREVIEW_ONSET_MS : f32 = 3000.0;
const ERROR_PREVIEW_ONSET_MS : f32 = 0000.0;



// =============
Expand Down Expand Up @@ -254,6 +258,8 @@ ensogl::define_endpoints! {
set_expression_usage_type (Crumbs,Option<Type>),
set_output_expression_visibility (bool),
set_vcs_status (Option<vcs::Status>),
/// Indicate whether preview visualisations should be delayed or immediate.
quick_preview_vis (bool),
}
Output {
/// Press event. Emitted when user clicks on non-active part of the node, like its
Expand Down Expand Up @@ -405,7 +411,7 @@ impl NodeModel {
display_object.add_child(&visualization);
display_object.add_child(&input);

let error_visualization = builtin_visualization::Error::new(&scene);
let error_visualization = builtin_visualization::Error::new(scene.clone_ref());
let (x,y) = ERROR_VISUALIZATION_SIZE;
error_visualization.set_size.emit(Vector2(x,y));

Expand Down Expand Up @@ -570,34 +576,78 @@ impl Node {
out.source.skip <+ action_bar.action_skip;
out.source.freeze <+ action_bar.action_freeze;
eval out.hover ((t) action_bar.set_visibility(t));
}


// === Errors on Node ===
// === Visualizations & Errors ===

is_error_set <- frp.error.map(|err| err.is_some());
let hover_onset_delay = DelayedAnimation::new(network);
hover_onset_delay.set_delay(VIS_PREVIEW_ONSET_MS);
hover_onset_delay.set_duration(0.0);

frp.source.error <+ frp.set_error.map(f!([model](error) {
model.set_error(error.as_ref());
error.clone()
}));
frp::extend! { network

frp.source.error <+ frp.set_error;
is_error_set <- frp.error.map(|err| err.is_some());
no_error_set <- not(&is_error_set);
error_color_anim.target <+ frp.error.map(f!([style](error)
Self::error_color(error,&style))
);

eval error_color_anim.value ((value) model.set_error_color(value));


// === Visualization ===

eval frp.set_visualization ((t) model.visualization.frp.set_visualization.emit(t));
visualization_enabled_frp <- bool(&frp.disable_visualization,&frp.enable_visualization);
eval visualization_enabled_frp ((enabled) model.action_bar.set_action_visibility_state(enabled));
no_error_set <- not(&is_error_set);

// Show preview visualisation after some delay, depending on whether we show an error
// or are in quick preview mode. Also, omit the delay if we don't have a tooltip to show.
has_tooltip <- model.output.frp.tooltip.map(|tt| tt.has_content());
preview_show_delay <- all3(&frp.quick_preview_vis,&is_error_set,&has_tooltip).map(
|(quick_preview,is_error,has_tooltip)| {
if !has_tooltip {
return 0.0;
}
match(is_error,quick_preview) {
(true,_) => ERROR_PREVIEW_ONSET_MS,
(false,false) => VIS_PREVIEW_ONSET_MS,
(false,true) => 0.0
}
});
hover_onset_delay.set_delay <+ preview_show_delay;
hide_tooltip <- preview_show_delay.map(|&delay| delay <= EPSILON);

hover_onset_delay.start <+ model.output.body_hover.on_true();
hover_onset_delay.reset <+ model.output.body_hover.on_false();
preview_visible <- bool(&hover_onset_delay.on_reset,&hover_onset_delay.on_end).on_change();

visualization_visible <- visualization_enabled && no_error_set;
frp.source.visualization_enabled <+ visualization_enabled;
visualization_visible <- visualization_visible || preview_visible;
visualization_visible <- visualization_visible.on_change();
frp.source.visualization_enabled <+ visualization_enabled || preview_visible;
eval visualization_visible ((is_visible) model.visualization.frp.set_visibility(is_visible));

// Ensure the preview is visible above all other elements, but the normal visualisation
// is below nodes.
layer_on_hover <- preview_visible.on_false().map(|_| visualization::Layer::Default);
layer_on_not_hover <- preview_visible.on_true().map(|_| visualization::Layer::Front);
layer <- any(layer_on_hover,layer_on_not_hover);
model.visualization.frp.set_layer <+ layer;
eval layer ((l) model.error_visualization.frp.set_layer.emit(l));


update_error <- all(frp.set_error,visualization_visible);
eval update_error([model]((error,visible)){
if *visible {
model.set_error(error.as_ref());
} else {
model.set_error(None);
}
});

eval error_color_anim.value ((value) model.set_error_color(value));

}

frp::extend! { network

// === Color Handling ===

Expand All @@ -612,7 +662,15 @@ impl Node {
model.main_area.bg_color.set(color::Rgba::from(c).into())
);

frp.source.tooltip <+ model.output.frp.tooltip;

// === Tooltip ===

// Hide tooltip if we show the preview vis.
frp.source.tooltip <+ preview_visible.on_true().constant(tooltip::Style::unset_label());
// Propagate output tooltip. Only if it is not hidden, or to disable it.
block_tooltip <- hide_tooltip && has_tooltip;
frp.source.tooltip <+ model.output.frp.tooltip.gate_not(&block_tooltip);


// === VCS Handling ===
model.vcs_indicator.frp.set_status <+ frp.set_vcs_status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ ensogl::define_endpoints! {
on_port_hover (Switch<Crumbs>),
on_port_type_change (Crumbs,Option<Type>),
port_size_multiplier (f32),
/// Indicates whether any part of the area is hovered.
body_hover (bool),
tooltip (tooltip::Style),
}
Expand Down
Loading

0 comments on commit d012500

Please sign in to comment.