mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 16:32:18 +03:00
Fix location_of_text_end method (#3170)
This commit is contained in:
parent
73abebf7aa
commit
850a16cb40
@ -1,412 +0,0 @@
|
||||
#![allow(missing_docs)]
|
||||
#![warn(missing_copy_implementations)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![warn(trivial_casts)]
|
||||
#![warn(trivial_numeric_casts)]
|
||||
#![warn(unsafe_code)]
|
||||
#![warn(unused_import_braces)]
|
||||
#![warn(unused_qualifications)]
|
||||
|
||||
//! 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.
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::graph_editor;
|
||||
use crate::graph_editor::GraphEditor;
|
||||
use crate::graph_editor::NodeProfilingStatus;
|
||||
use crate::graph_editor::Type;
|
||||
use crate::project;
|
||||
use crate::root;
|
||||
use crate::status_bar;
|
||||
|
||||
use enso_frp as frp;
|
||||
use ensogl::application::Application;
|
||||
use ensogl::display::navigation::navigator::Navigator;
|
||||
use ensogl::display::object::ObjectOps;
|
||||
use ensogl::display::shape::StyleWatch;
|
||||
use ensogl::system::web;
|
||||
use ensogl_hardcoded_theme as theme;
|
||||
use ensogl_text as text;
|
||||
use parser::Parser;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
|
||||
|
||||
const STUB_MODULE: &str = "from Base import all\n\nmain = IO.println \"Hello\"\n";
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[allow(dead_code)]
|
||||
pub fn entry_point_interface() {
|
||||
web::forward_panic_hook_to_console();
|
||||
web::set_stack_trace_limit();
|
||||
run_once_initialized(|| {
|
||||
let app = Application::new(&web::get_html_element_by_id("root").unwrap());
|
||||
init(&app);
|
||||
mem::forget(app);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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 ===
|
||||
// ==================
|
||||
|
||||
/// Allows the creation of arbitrary unique `Type`s.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct DummyTypeGenerator {
|
||||
type_counter: u32,
|
||||
}
|
||||
|
||||
impl DummyTypeGenerator {
|
||||
fn get_dummy_type(&mut self) -> Type {
|
||||
self.type_counter += 1;
|
||||
Type::from(format!("dummy_type_{}", self.type_counter))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ========================
|
||||
// === Init Application ===
|
||||
// ========================
|
||||
|
||||
fn init(app: &Application) {
|
||||
let _bg = app.display.scene().style_sheet.var(theme::application::background);
|
||||
|
||||
let world = &app.display;
|
||||
let scene = world.scene();
|
||||
let camera = scene.camera();
|
||||
let navigator = Navigator::new(scene, &camera);
|
||||
|
||||
app.views.register::<root::View>();
|
||||
app.views.register::<project::View>();
|
||||
app.views.register::<text::Area>();
|
||||
app.views.register::<GraphEditor>();
|
||||
let root_view = app.new_view::<root::View>();
|
||||
root_view.switch_view_to_project();
|
||||
let graph_editor = root_view.project().graph().clone_ref();
|
||||
let code_editor = root_view.project().code_editor().clone_ref();
|
||||
world.add_child(&root_view);
|
||||
|
||||
code_editor.text_area().set_content(STUB_MODULE.to_owned());
|
||||
|
||||
root_view.status_bar().add_event(status_bar::event::Label::new("This is a status message."));
|
||||
graph_editor.debug_push_breadcrumb();
|
||||
|
||||
|
||||
// === Nodes ===
|
||||
|
||||
let node1_id = graph_editor.add_node();
|
||||
let node2_id = graph_editor.add_node();
|
||||
let node3_id = graph_editor.add_node();
|
||||
|
||||
graph_editor.frp.set_node_position.emit((node1_id, Vector2(-150.0, 50.0)));
|
||||
graph_editor.frp.set_node_position.emit((node2_id, Vector2(50.0, 50.0)));
|
||||
graph_editor.frp.set_node_position.emit((node3_id, Vector2(150.0, 250.0)));
|
||||
|
||||
|
||||
let expression_1 = expression_mock();
|
||||
graph_editor.frp.set_node_expression.emit((node1_id, expression_1.clone()));
|
||||
let comment_1 = String::from("Sample documentation comment.");
|
||||
graph_editor.frp.set_node_comment.emit((node1_id, comment_1));
|
||||
|
||||
let expression_2 = expression_mock3();
|
||||
graph_editor.frp.set_node_expression.emit((node2_id, expression_2.clone()));
|
||||
|
||||
let expression_3 = expression_mock2();
|
||||
graph_editor.frp.set_node_expression.emit((node3_id, expression_3));
|
||||
let kind = Immutable(graph_editor::component::node::error::Kind::Panic);
|
||||
let message = Rc::new(Some("Runtime Error".to_owned()));
|
||||
let propagated = Immutable(false);
|
||||
let error = graph_editor::component::node::Error { kind, message, propagated };
|
||||
graph_editor.frp.set_node_error_status.emit((node3_id, Some(error)));
|
||||
|
||||
let foo_node = graph_editor.add_node_below(node3_id);
|
||||
graph_editor.set_node_expression.emit((foo_node, Expression::new_plain("foo")));
|
||||
|
||||
let baz_node = graph_editor.add_node_below(node3_id);
|
||||
graph_editor.set_node_expression.emit((baz_node, Expression::new_plain("baz")));
|
||||
let (_, baz_position) = graph_editor.node_position_set.value();
|
||||
let styles = StyleWatch::new(&scene.style_sheet);
|
||||
let min_spacing = styles.get_number(theme::graph_editor::minimal_x_spacing_for_new_nodes);
|
||||
let gap_between_nodes = styles.get_number(theme::graph_editor::default_x_gap_between_nodes);
|
||||
let gap_for_bar_node = min_spacing + gap_between_nodes + f32::EPSILON;
|
||||
graph_editor.set_node_position((baz_node, baz_position + Vector2(gap_for_bar_node, 0.0)));
|
||||
|
||||
let bar_node = graph_editor.add_node_below(node3_id);
|
||||
graph_editor.set_node_expression.emit((bar_node, Expression::new_plain("bar")));
|
||||
|
||||
|
||||
// === Connections ===
|
||||
|
||||
let src = graph_editor::EdgeEndpoint::new(node1_id, span_tree::Crumbs::new(default()));
|
||||
let tgt =
|
||||
graph_editor::EdgeEndpoint::new(node2_id, span_tree::Crumbs::new(vec![0, 0, 0, 0, 1]));
|
||||
graph_editor.frp.connect_nodes.emit((src, tgt));
|
||||
|
||||
|
||||
// === VCS ===
|
||||
|
||||
let dummy_node_added_id = graph_editor.add_node();
|
||||
let dummy_node_edited_id = graph_editor.add_node();
|
||||
let dummy_node_unchanged_id = graph_editor.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)));
|
||||
|
||||
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.");
|
||||
|
||||
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_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)));
|
||||
|
||||
|
||||
// === Types (Port Coloring) ===
|
||||
|
||||
let mut dummy_type_generator = DummyTypeGenerator::default();
|
||||
|
||||
expression_1.input_span_tree.root_ref().leaf_iter().for_each(|node| {
|
||||
if let Some(expr_id) = node.ast_id {
|
||||
let dummy_type = Some(dummy_type_generator.get_dummy_type());
|
||||
graph_editor.frp.set_expression_usage_type.emit((node1_id, expr_id, dummy_type));
|
||||
}
|
||||
});
|
||||
|
||||
expression_1.output_span_tree.root_ref().leaf_iter().for_each(|node| {
|
||||
if let Some(expr_id) = node.ast_id {
|
||||
let dummy_type = Some(dummy_type_generator.get_dummy_type());
|
||||
graph_editor.frp.set_expression_usage_type.emit((node1_id, expr_id, dummy_type));
|
||||
}
|
||||
});
|
||||
|
||||
expression_2.input_span_tree.root_ref().leaf_iter().for_each(|node| {
|
||||
if let Some(expr_id) = node.ast_id {
|
||||
let dummy_type = Some(dummy_type_generator.get_dummy_type());
|
||||
graph_editor.frp.set_expression_usage_type.emit((node2_id, expr_id, dummy_type));
|
||||
}
|
||||
});
|
||||
|
||||
expression_2.output_span_tree.root_ref().leaf_iter().for_each(|node| {
|
||||
if let Some(expr_id) = node.ast_id {
|
||||
let dummy_type = Some(dummy_type_generator.get_dummy_type());
|
||||
graph_editor.frp.set_expression_usage_type.emit((node2_id, expr_id, dummy_type));
|
||||
}
|
||||
});
|
||||
|
||||
root_view.project().show_prompt();
|
||||
|
||||
// === 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);
|
||||
|
||||
|
||||
// let tgt_type = dummy_type_generator.get_dummy_type();
|
||||
let mut was_rendered = false;
|
||||
let mut loader_hidden = false;
|
||||
let mut to_theme_switch = 100;
|
||||
|
||||
world
|
||||
.on_frame(move |_| {
|
||||
let _keep_alive = &navigator;
|
||||
let _keep_alive = &root_view;
|
||||
|
||||
if to_theme_switch == 0 {
|
||||
// println!("THEME SWITCH !!!");
|
||||
// scene.style_sheet.set("application.background",color::Rgba(0.0,0.0,0.0,1.0));
|
||||
// ensogl_hardcoded_theme::builtin::dark::enable(&app);
|
||||
//
|
||||
// println!(">>> {:?}", "lcha(1,0,0,1)".parse::<color::Lcha>());
|
||||
}
|
||||
to_theme_switch -= 1;
|
||||
|
||||
// if i > 0 { i -= 1 } else {
|
||||
// println!("CHANGING TYPES OF EXPRESSIONS");
|
||||
// i = 10000;
|
||||
// graph_editor.frp.set_node_expression.emit((node2_id,expression_2.clone()));
|
||||
// // expression_1.input_span_tree.root_ref().leaf_iter().for_each(|node|{
|
||||
// // if let Some(expr_id) = node.ast_id {
|
||||
// // let dummy_type = Some(tgt_type.clone());
|
||||
// // // if j != 0 {
|
||||
// // // j -= 1;
|
||||
// // println!("----\n");
|
||||
// //
|
||||
// graph_editor.frp.set_expression_usage_type.emit((node1_id,expr_id,dummy_type));
|
||||
// // // } else {
|
||||
// // // println!(">> null change");
|
||||
// // // j = 3;
|
||||
// // //
|
||||
// graph_editor.frp.set_expression_usage_type.emit((node1_id,expr_id,None));
|
||||
// // //
|
||||
// graph_editor.frp.set_expression_usage_type.emit((node1_id,expr_id,dummy_type));
|
||||
// // // };
|
||||
// // }
|
||||
// // });
|
||||
// }
|
||||
|
||||
// Temporary code removing the web-loader instance.
|
||||
// To be changed in the future.
|
||||
if was_rendered && !loader_hidden {
|
||||
web::get_element_by_id("loader")
|
||||
.map(|t| t.parent_node().map(|p| p.remove_child(&t).unwrap()))
|
||||
.ok();
|
||||
loader_hidden = true;
|
||||
}
|
||||
was_rendered = true;
|
||||
})
|
||||
.forget();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// =============
|
||||
// === Mocks ===
|
||||
// =============
|
||||
|
||||
use crate::graph_editor::component::node::vcs;
|
||||
use crate::graph_editor::component::node::Expression;
|
||||
|
||||
use ast::crumbs::PatternMatchCrumb::*;
|
||||
use ast::crumbs::*;
|
||||
use engine_protocol::prelude::Uuid;
|
||||
use ensogl_text_msdf_sys::run_once_initialized;
|
||||
use span_tree::traits::*;
|
||||
|
||||
|
||||
pub fn expression_mock_string(label: &str) -> Expression {
|
||||
let pattern = Some(label.to_string());
|
||||
let code = format!("\"{}\"", label);
|
||||
let parser = Parser::new_or_panic();
|
||||
let parameters = vec![];
|
||||
let ast = parser.parse_line_ast(&code).unwrap();
|
||||
let invocation_info = span_tree::generate::context::CalledMethodInfo { parameters };
|
||||
let ctx = span_tree::generate::MockContext::new_single(ast.id.unwrap(), invocation_info);
|
||||
let output_span_tree = span_tree::SpanTree::default();
|
||||
let input_span_tree = span_tree::SpanTree::new(&ast, &ctx).unwrap();
|
||||
let whole_expression_id = default();
|
||||
Expression { pattern, code, whole_expression_id, input_span_tree, output_span_tree }
|
||||
}
|
||||
|
||||
pub fn expression_mock() -> Expression {
|
||||
let pattern = Some("var1".to_string());
|
||||
let code = "[1,2,3]".to_string();
|
||||
let parser = Parser::new_or_panic();
|
||||
let this_param =
|
||||
span_tree::ArgumentInfo { name: Some("this".to_owned()), tp: Some("Text".to_owned()) };
|
||||
let parameters = vec![this_param];
|
||||
let ast = parser.parse_line_ast(&code).unwrap();
|
||||
let invocation_info = span_tree::generate::context::CalledMethodInfo { parameters };
|
||||
let ctx = span_tree::generate::MockContext::new_single(ast.id.unwrap(), invocation_info);
|
||||
let output_span_tree = span_tree::SpanTree::default();
|
||||
let input_span_tree = span_tree::SpanTree::new(&ast, &ctx).unwrap();
|
||||
let whole_expression_id = default();
|
||||
Expression { pattern, code, whole_expression_id, input_span_tree, output_span_tree }
|
||||
}
|
||||
|
||||
pub fn expression_mock2() -> Expression {
|
||||
let pattern = Some("var1".to_string());
|
||||
let pattern_cr = vec![Seq { right: false }, Or, Or, Build];
|
||||
let val = ast::crumbs::SegmentMatchCrumb::Body { val: pattern_cr };
|
||||
let parens_cr = ast::crumbs::MatchCrumb::Segs { val, index: 0 };
|
||||
let code = "make_maps size (distribution normal)".into();
|
||||
let output_span_tree = span_tree::SpanTree::default();
|
||||
let input_span_tree = span_tree::builder::TreeBuilder::new(36)
|
||||
.add_child(0, 14, span_tree::node::Kind::Chained, PrefixCrumb::Func)
|
||||
.add_child(0, 9, span_tree::node::Kind::Operation, PrefixCrumb::Func)
|
||||
.set_ast_id(Uuid::new_v4())
|
||||
.done()
|
||||
.add_empty_child(10, span_tree::node::InsertionPointType::BeforeTarget)
|
||||
.add_child(10, 4, span_tree::node::Kind::this().removable(), PrefixCrumb::Arg)
|
||||
.set_ast_id(Uuid::new_v4())
|
||||
.done()
|
||||
.add_empty_child(14, span_tree::node::InsertionPointType::Append)
|
||||
.set_ast_id(Uuid::new_v4())
|
||||
.done()
|
||||
.add_child(15, 21, span_tree::node::Kind::argument().removable(), PrefixCrumb::Arg)
|
||||
.set_ast_id(Uuid::new_v4())
|
||||
.add_child(1, 19, span_tree::node::Kind::argument(), parens_cr)
|
||||
.set_ast_id(Uuid::new_v4())
|
||||
.add_child(0, 12, span_tree::node::Kind::Operation, PrefixCrumb::Func)
|
||||
.set_ast_id(Uuid::new_v4())
|
||||
.done()
|
||||
.add_empty_child(13, span_tree::node::InsertionPointType::BeforeTarget)
|
||||
.add_child(13, 6, span_tree::node::Kind::this(), PrefixCrumb::Arg)
|
||||
.set_ast_id(Uuid::new_v4())
|
||||
.done()
|
||||
.add_empty_child(19, span_tree::node::InsertionPointType::Append)
|
||||
.done()
|
||||
.done()
|
||||
.add_empty_child(36, span_tree::node::InsertionPointType::Append)
|
||||
.build();
|
||||
let whole_expression_id = default();
|
||||
Expression { pattern, code, whole_expression_id, input_span_tree, output_span_tree }
|
||||
}
|
||||
|
||||
pub fn expression_mock3() -> Expression {
|
||||
let pattern = Some("Vector x y z".to_string());
|
||||
// let code = "image.blur ((foo bar) baz)".to_string();
|
||||
let code = "Vector x y z".to_string();
|
||||
let parser = Parser::new_or_panic();
|
||||
let this_param =
|
||||
span_tree::ArgumentInfo { name: Some("this".to_owned()), tp: Some("Image".to_owned()) };
|
||||
let param0 = span_tree::ArgumentInfo {
|
||||
name: Some("radius".to_owned()),
|
||||
tp: Some("Number".to_owned()),
|
||||
};
|
||||
let param1 =
|
||||
span_tree::ArgumentInfo { name: Some("name".to_owned()), tp: Some("Text".to_owned()) };
|
||||
let param2 = span_tree::ArgumentInfo {
|
||||
name: Some("area".to_owned()),
|
||||
tp: Some("Vector Int".to_owned()),
|
||||
};
|
||||
let param3 = span_tree::ArgumentInfo {
|
||||
name: Some("matrix".to_owned()),
|
||||
tp: Some("Vector String".to_owned()),
|
||||
};
|
||||
let parameters = vec![this_param, param0, param1, param2, param3];
|
||||
let ast = parser.parse_line_ast(&code).unwrap();
|
||||
let invocation_info = span_tree::generate::context::CalledMethodInfo { parameters };
|
||||
let ctx = span_tree::generate::MockContext::new_single(ast.id.unwrap(), invocation_info);
|
||||
let output_span_tree = span_tree::SpanTree::new(&ast, &ctx).unwrap(); //span_tree::SpanTree::default();
|
||||
let input_span_tree = span_tree::SpanTree::new(&ast, &ctx).unwrap();
|
||||
let whole_expression_id = default();
|
||||
Expression { pattern, code, whole_expression_id, input_span_tree, output_span_tree }
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
//! This is a visualization example scene which creates a sinusoidal graph.
|
||||
|
||||
#![warn(missing_copy_implementations)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(trivial_casts)]
|
||||
#![warn(trivial_numeric_casts)]
|
||||
#![warn(unsafe_code)]
|
||||
#![warn(unused_import_braces)]
|
||||
#![warn(unused_qualifications)]
|
||||
|
||||
use crate::graph_editor::component::visualization;
|
||||
use crate::graph_editor::component::visualization::Data;
|
||||
use crate::graph_editor::component::visualization::Registry;
|
||||
|
||||
use ensogl::application::Application;
|
||||
use ensogl::display::navigation::navigator::Navigator;
|
||||
use ensogl::system::web;
|
||||
use ensogl_text_msdf_sys::run_once_initialized;
|
||||
use js_sys::Math::sin;
|
||||
use nalgebra::Vector2;
|
||||
use std::rc::Rc;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
fn generate_data(seconds: f64) -> Vec<Vector2<f32>> {
|
||||
let mut data = Vec::new();
|
||||
for x in 0..100 {
|
||||
let x = x as f64 / 50.0 - 1.0;
|
||||
let y = sin(x * std::f64::consts::PI + seconds);
|
||||
data.push(Vector2::new(x as f32, y as f32));
|
||||
}
|
||||
data
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn constructor_graph() -> visualization::java_script::Definition {
|
||||
let source = r#"
|
||||
class Graph extends Visualization {
|
||||
static inputType = "[[Float,Float,Float]]"
|
||||
|
||||
onDataReceived(data) {
|
||||
if (!this.canvas) {
|
||||
this.canvas = document.createElement("canvas");
|
||||
this.canvas.setAttribute("tabindex","0");
|
||||
this.context = this.canvas.getContext("2d");
|
||||
this.dom.appendChild(this.canvas);
|
||||
this.dom.addEventListener("keydown", function(e) {
|
||||
console.log("pressed",e);
|
||||
})
|
||||
}
|
||||
this.setPreprocessor(`x ->\n IO.println "Preprocessor set after receiving ${data}`)
|
||||
|
||||
let first = data.shift();
|
||||
if (first) {
|
||||
this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
|
||||
this.context.save();
|
||||
this.context.scale(this.canvas.width/2,this.canvas.height/2);
|
||||
this.context.translate(1,1);
|
||||
this.context.lineWidth = 1/Math.min(this.canvas.width,this.canvas.height);
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(first[0],first[1]);
|
||||
data.forEach(data => {
|
||||
this.context.lineTo(data[0],data[1]);
|
||||
});
|
||||
this.context.stroke();
|
||||
this.context.restore();
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(first[0],first[1]);
|
||||
this.context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
setSize(size) {
|
||||
if (this.canvas) {
|
||||
this.canvas.width = size[0];
|
||||
this.canvas.height = size[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Graph
|
||||
"#;
|
||||
visualization::java_script::Definition::new_builtin(source).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[allow(dead_code, missing_docs)]
|
||||
pub fn entry_point_visualization() {
|
||||
web::forward_panic_hook_to_console();
|
||||
web::set_stack_trace_limit();
|
||||
run_once_initialized(|| {
|
||||
let app = Application::new(&web::get_html_element_by_id("root").unwrap());
|
||||
init(&app);
|
||||
std::mem::forget(app);
|
||||
});
|
||||
}
|
||||
|
||||
fn init(app: &Application) {
|
||||
let world = &app.display;
|
||||
let scene = world.scene();
|
||||
let camera = scene.camera();
|
||||
let navigator = Navigator::new(scene, &camera);
|
||||
let registry = Registry::new();
|
||||
|
||||
registry.add(constructor_graph());
|
||||
|
||||
let vis_factories = registry.valid_sources(&"[[Float,Float,Float]]".into());
|
||||
let vis_class = vis_factories
|
||||
.iter()
|
||||
.find(|class| &*class.signature.name == "Graph")
|
||||
.expect("Couldn't find Graph class.");
|
||||
let visualization = vis_class.new_instance(scene).expect("Couldn't create visualiser.");
|
||||
visualization.activate.emit(());
|
||||
|
||||
let network = enso_frp::Network::new("VisualizationExample");
|
||||
enso_frp::extend! { network
|
||||
trace visualization.on_preprocessor_change;
|
||||
};
|
||||
std::mem::forget(network);
|
||||
|
||||
let mut was_rendered = false;
|
||||
let mut loader_hidden = false;
|
||||
world
|
||||
.on_frame(move |time_info| {
|
||||
let _keep_alive = &navigator;
|
||||
|
||||
let data = generate_data((time_info.local / 1000.0).into());
|
||||
let data = Rc::new(data);
|
||||
let content = serde_json::to_value(data).unwrap();
|
||||
let data = Data::from(content);
|
||||
|
||||
visualization.send_data.emit(data);
|
||||
|
||||
// Temporary code removing the web-loader instance.
|
||||
// To be changed in the future.
|
||||
if was_rendered && !loader_hidden {
|
||||
web::get_element_by_id("loader")
|
||||
.map(|t| t.parent_node().map(|p| p.remove_child(&t).unwrap()))
|
||||
.ok();
|
||||
loader_hidden = true;
|
||||
}
|
||||
was_rendered = true;
|
||||
})
|
||||
.forget();
|
||||
}
|
@ -457,7 +457,13 @@ impl Text {
|
||||
/// The location of text end.
|
||||
pub fn location_of_text_end(&self) -> Location {
|
||||
let lines_count = self.lines(self.byte_range()).count();
|
||||
if lines_count == 0 {
|
||||
let last_char_off = self.rope.prev_codepoint_offset(self.len());
|
||||
let last_char = last_char_off.map(|off| self.rope.slice_to_cow(off..));
|
||||
let ends_with_eol = last_char.map_or(false, |ch| ch.starts_with('\n'));
|
||||
if ends_with_eol {
|
||||
let line: Line = lines_count.into();
|
||||
Location(line, 0.column())
|
||||
} else if lines_count == 0 {
|
||||
default()
|
||||
} else {
|
||||
let line = ((lines_count - 1) as i32).line();
|
||||
@ -949,3 +955,44 @@ impl<S: AsRef<str>> Change<Bytes, S> {
|
||||
Ok(string)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// =============
|
||||
// === Tests ===
|
||||
// =============
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn location_of_text_end() {
|
||||
struct Case {
|
||||
text: &'static str,
|
||||
expected: (usize, usize), // Line and column
|
||||
}
|
||||
|
||||
impl Case {
|
||||
fn run(&self) {
|
||||
let text: Text = self.text.into();
|
||||
let (exp_line, exp_column) = self.expected;
|
||||
let expected = Location { line: exp_line.into(), column: exp_column.into() };
|
||||
let result = text.location_of_text_end();
|
||||
assert_eq!(result, expected, "Wrong text end location in case \"{}\"", text);
|
||||
}
|
||||
}
|
||||
|
||||
let cases = &[
|
||||
Case { text: "", expected: (0, 0) },
|
||||
Case { text: "single line", expected: (0, 11) },
|
||||
Case { text: "single line with eol\n", expected: (1, 0) },
|
||||
Case { text: "\nMany\nLines", expected: (2, 5) },
|
||||
Case { text: "Many\nLines\nwith eol\n", expected: (3, 0) },
|
||||
];
|
||||
|
||||
for case in cases {
|
||||
case.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user