Skip to content

Commit

Permalink
Merge branch 'develop' into wip/frizi/panic-handling
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Aug 17, 2023
2 parents d1dac36 + d15b3db commit 756dadb
Show file tree
Hide file tree
Showing 18 changed files with 233 additions and 739 deletions.
15 changes: 8 additions & 7 deletions app/gui/src/controller/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,13 +544,14 @@ impl Handle {

/// Returns information about all the nodes currently present in this graph.
pub fn nodes(&self) -> FallibleResult<Vec<Node>> {
let node_infos = self.all_node_infos()?;
let mut nodes = Vec::new();
for info in node_infos {
let metadata = self.module.node_metadata(info.id()).ok();
nodes.push(Node { info, metadata })
}
Ok(nodes)
Ok(self
.all_node_infos()?
.into_iter()
.map(|info| {
let metadata = self.module.node_metadata(info.id()).ok();
Node { info, metadata }
})
.collect())
}

/// Returns information about all the connections between graph's nodes.
Expand Down
15 changes: 6 additions & 9 deletions app/gui/src/model/execution_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,12 @@ pub struct ComputedValueInfo {

impl ComputedValueInfo {
fn apply_update(&mut self, update: ExpressionUpdate) {
// We do not erase method_call information to avoid ports "flickering" on every computation.
// the method_call should be updated soon anyway.
// The type of the expression could also be kept, but so far we use the "lack of type"
// information to inform user the results are recomputed.
// We do not erase this information to avoid ports "flickering" on every computation.
// The method_call should be updated soon anyway.
if !matches!(update.payload, ExpressionUpdatePayload::Pending { .. }) {
self.method_call = update.method_call.map(|mc| mc.method_pointer);
self.typename = update.typename.map(ImString::new);
}
self.typename = update.typename.map(ImString::new);
self.payload = update.payload
}
}
Expand Down Expand Up @@ -688,7 +686,7 @@ mod tests {
let update1 = value_update_with_dataflow_error(expr2);
let update2 = value_update_with_dataflow_panic(expr3, error_msg);
registry.apply_updates(vec![update1, update2]);
assert_eq!(registry.get(&expr1).unwrap().typename, Some(typename1.into()));
assert_eq!(registry.get(&expr1).unwrap().typename, Some(typename1.clone().into()));
assert!(matches!(registry.get(&expr1).unwrap().payload, ExpressionUpdatePayload::Value {
warnings: None,
}));
Expand All @@ -708,10 +706,9 @@ mod tests {
// Set pending value
let update1 = value_pending_update(expr1);
registry.apply_updates(vec![update1]);
// Method pointer should not be cleared to avoid port's flickering.
// Method pointer and type are not affected; pending state is shown by an opacity change.
assert_eq!(registry.get(&expr1).unwrap().method_call, Some(method_ptr));
// The type is erased to show invalidated path.
assert_eq!(registry.get(&expr1).unwrap().typename, None);
assert_eq!(registry.get(&expr1).unwrap().typename, Some(typename1.into()));
assert!(matches!(
registry.get(&expr1).unwrap().payload,
ExpressionUpdatePayload::Pending { message: None, progress: None }
Expand Down
11 changes: 11 additions & 0 deletions app/gui/src/presenter/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::presenter::graph::state::State;
use double_representation::context_switch::Context;
use double_representation::context_switch::ContextSwitch;
use double_representation::context_switch::ContextSwitchExpression;
use engine_protocol::language_server::ExpressionUpdatePayload;
use enso_frp as frp;
use futures::future::LocalBoxFuture;
use ide_view as view;
Expand Down Expand Up @@ -411,6 +412,15 @@ impl Model {
self.state.update_from_controller().set_node_error_from_payload(expression, payload)
}

fn refresh_node_pending(&self, expression: ast::Id) -> Option<(ViewNodeId, bool)> {
let registry = self.controller.computed_value_info_registry();
let is_pending = registry
.get(&expression)
.map(|info| matches!(info.payload, ExpressionUpdatePayload::Pending { .. }))
.unwrap_or_default();
self.state.update_from_controller().set_node_pending(expression, is_pending)
}

/// Extract the expression's current type from controllers.
fn expression_type(&self, id: ast::Id) -> Option<view::graph_editor::Type> {
let registry = self.controller.computed_value_info_registry();
Expand Down Expand Up @@ -746,6 +756,7 @@ impl Graph {
update_expression <= update_expressions;
view.set_expression_usage_type <+ update_expression.filter_map(f!((id) model.refresh_expression_type(*id)));
view.set_node_error_status <+ update_expression.filter_map(f!((id) model.refresh_node_error(*id)));
view.set_node_pending_status <+ update_expression.filter_map(f!((id) model.refresh_node_pending(*id)));

self.init_widgets(reset_node_types, update_expression.clone_ref());

Expand Down
48 changes: 28 additions & 20 deletions app/gui/src/presenter/graph/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use ide_view::graph_editor::EdgeEndpoint;

/// A single node data.
#[allow(missing_docs)]
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
pub struct Node {
pub view_id: Option<ViewNodeId>,
pub position: Vector2,
Expand All @@ -33,27 +33,12 @@ pub struct Node {
pub is_frozen: bool,
pub context_switch: Option<ContextSwitchExpression>,
pub error: Option<node_view::Error>,
pub is_pending: bool,
pub visualization: Option<visualization_view::Path>,

/// Indicate whether this node view is updated automatically by changes from the controller
/// or view, or will be explicitly updated..
expression_auto_update: bool,
}

impl Default for Node {
fn default() -> Self {
Self {
view_id: None,
position: Vector2::default(),
expression: node_view::Expression::default(),
is_skipped: false,
is_frozen: false,
context_switch: None,
error: None,
visualization: None,
expression_auto_update: true,
}
}
disable_expression_auto_update: bool,
}

/// The set of node states.
Expand Down Expand Up @@ -293,12 +278,19 @@ impl State {
// When node is in process of being created, it is not yet present in the state. In that
// case the initial expression update needs to be processed. Otherwise the node would be
// created without any expression.
self.nodes.borrow().get(node).map_or(true, |node| node.expression_auto_update)
let auto_update_disabled = self
.nodes
.borrow()
.get(node)
.map_or_default(|node| node.disable_expression_auto_update);
!auto_update_disabled
}

/// Set the flag that indicates if the node should be synced with its AST automatically.
pub fn allow_expression_auto_updates(&self, node: ast::Id, allow: bool) {
self.nodes.borrow_mut().get_mut(node).for_each(|node| node.expression_auto_update = allow);
if let Some(node) = self.nodes.borrow_mut().get_mut(node) {
node.disable_expression_auto_update = !allow;
}
}
}

Expand Down Expand Up @@ -452,6 +444,22 @@ impl<'a> ControllerChange<'a> {
}
}

/// Set whether this node is currently awaiting completion of execution.
pub fn set_node_pending(
&self,
node_id: ast::Id,
is_pending: bool,
) -> Option<(ViewNodeId, bool)> {
let mut nodes = self.nodes.borrow_mut();
let displayed = nodes.get_mut(node_id)?;
if displayed.is_pending != is_pending {
displayed.is_pending = is_pending;
Some((displayed.view_id?, is_pending))
} else {
None
}
}

fn convert_payload_to_error(
&self,
node_id: AstNodeId,
Expand Down
41 changes: 5 additions & 36 deletions app/gui/view/examples/interface/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
//! NOTE
//! This file is under a heavy development. It contains commented lines of code and some code may
//! be of poor quality. Expect drastic changes.

// === Standard Linter Configuration ===
#![deny(non_ascii_idents)]
#![warn(unsafe_code)]
Expand All @@ -17,7 +13,6 @@

use ensogl::prelude::*;

use enso_frp as frp;
use ensogl::application::Application;
use ensogl::display::object::ObjectOps;
use ensogl::display::shape::StyleWatch;
Expand All @@ -30,7 +25,6 @@ use ide_view::graph_editor;
use ide_view::graph_editor::component::node::vcs;
use ide_view::graph_editor::component::node::Expression;
use ide_view::graph_editor::GraphEditor;
use ide_view::graph_editor::NodeProfilingStatus;
use ide_view::graph_editor::Type;
use ide_view::project;
use ide_view::root;
Expand All @@ -53,26 +47,6 @@ pub fn main() {
}


fn _fence<T, Out>(network: &frp::Network, trigger: T) -> (frp::Stream, frp::Stream<bool>)
where
T: frp::HasOutput<Output = Out>,
T: Into<frp::Stream<Out>>,
Out: frp::Data, {
let trigger = trigger.into();
frp::extend! { network
def trigger_ = trigger.constant(());
def runner = source::<()>();
def switch = any_mut();
switch.attach(&trigger_);
def triggered = trigger.map(f_!(runner.emit(())));
switch.attach(&triggered);
def condition = switch.toggle_true();
}
let runner = runner.into();
(runner, condition)
}



// ==================
// === Mock Types ===
Expand Down Expand Up @@ -178,25 +152,30 @@ fn init(app: &Application) {
let dummy_node_added_id = graph_editor.model.add_node();
let dummy_node_edited_id = graph_editor.model.add_node();
let dummy_node_unchanged_id = graph_editor.model.add_node();
let dummy_node_pending_id = graph_editor.model.add_node();

graph_editor.frp.set_node_position.emit((dummy_node_added_id, Vector2(-450.0, 50.0)));
graph_editor.frp.set_node_position.emit((dummy_node_edited_id, Vector2(-450.0, 125.0)));
graph_editor.frp.set_node_position.emit((dummy_node_unchanged_id, Vector2(-450.0, 200.0)));
graph_editor.frp.set_node_position.emit((dummy_node_pending_id, Vector2(-450.0, 275.0)));

let dummy_node_added_expr = expression_mock_string("This node was added.");
let dummy_node_edited_expr = expression_mock_string("This node was edited.");
let dummy_node_unchanged_expr = expression_mock_string("This node was not changed.");
let dummy_node_pending_expr = expression_mock_string("This node is pending.");

graph_editor.frp.set_node_expression.emit((dummy_node_added_id, dummy_node_added_expr));
graph_editor.frp.set_node_expression.emit((dummy_node_edited_id, dummy_node_edited_expr));
graph_editor.frp.set_node_expression.emit((dummy_node_unchanged_id, dummy_node_unchanged_expr));
graph_editor.frp.set_node_expression.emit((dummy_node_pending_id, dummy_node_pending_expr));

graph_editor.frp.set_node_vcs_status.emit((dummy_node_added_id, Some(vcs::Status::Edited)));
graph_editor.frp.set_node_vcs_status.emit((dummy_node_edited_id, Some(vcs::Status::Added)));
graph_editor
.frp
.set_node_vcs_status
.emit((dummy_node_unchanged_id, Some(vcs::Status::Unchanged)));
graph_editor.frp.set_node_pending_status.emit((dummy_node_pending_id, true));


// === Types (Port Coloring) ===
Expand Down Expand Up @@ -232,16 +211,6 @@ fn init(app: &Application) {
});


// === Profiling ===

let node1_status = NodeProfilingStatus::Finished { duration: 500.0 };
graph_editor.set_node_profiling_status(node1_id, node1_status);
let node2_status = NodeProfilingStatus::Finished { duration: 1000.0 };
graph_editor.set_node_profiling_status(node2_id, node2_status);
let node3_status = NodeProfilingStatus::Finished { duration: 1500.0 };
graph_editor.set_node_profiling_status(node3_id, node3_status);


// === Execution Modes ===

graph_editor.set_available_execution_environments(make_dummy_execution_environments());
Expand Down
2 changes: 0 additions & 2 deletions app/gui/view/graph-editor/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
pub mod add_node_button;
pub mod edge;
pub mod node;
#[warn(missing_docs)]
pub mod profiling;
pub mod type_coloring;
pub mod visualization;

Expand Down
3 changes: 2 additions & 1 deletion app/gui/view/graph-editor/src/component/edge/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ fn junction_points(
// The target attachment will extend as far toward the edge of the node as it can without
// rising above the source.
let attachment_height = target_max_attachment_height.map(|dy| min(dy, target.y().abs()));
let attachment_y = target.y() + attachment_height.unwrap_or_default();
let attachment_y =
target.y() + attachment_height.unwrap_or_default() + target_size.y() / 2.0;
let target_attachment = Vector2(target.x(), attachment_y);
(vec![source, target_attachment], max_radius, attachment)
} else {
Expand Down
2 changes: 1 addition & 1 deletion app/gui/view/graph-editor/src/component/edge/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ mod attachment {
/// appears to pass through the top of the node. Without this adjustment, inexact
/// floating-point math and anti-aliasing would cause a 1-pixel gap artifact right where
/// the attachment should meet the corner at the edge of the node.
pub(super) const LENGTH_ADJUSTMENT: f32 = 0.1;
pub(super) const LENGTH_ADJUSTMENT: f32 = 1.0;
}


Expand Down
Loading

0 comments on commit 756dadb

Please sign in to comment.