Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into wip/procrat/home-button-6399
Browse files Browse the repository at this point in the history
* develop:
  Finishing Vector Editor (#6470)
  Proper handling of multiple list views. (#6461)
  Fix disappearing cached shapes (#6458)
  Add Execution Context control to Text.write (#6459)
  Change defaults for `Connection.tables` and ensure that `Connection.query` recognizes all available tables (#6443)
Procrat committed May 2, 2023
2 parents 30789bd + d6fa36d commit 4234c47
Showing 90 changed files with 2,086 additions and 641 deletions.
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -135,7 +135,9 @@
- [Added capability to create node widgets with complex UI][6347]. Node widgets
such as dropdown can now be placed in the node and affect the code text flow.
- [The IDE UI element for selecting the execution mode of the project is now
sending messages to the backend.][6341].
sending messages to the backend][6341].
- [List Editor Widget][6470]. Now you can edit lists by clicking buttons on
nodes or by dragging the elements.
- [Added a button to return from an opened project back to the project
- dashboard.][6474]

@@ -202,7 +204,8 @@
[5895]: https://github.com/enso-org/enso/pull/6130
[6035]: https://github.com/enso-org/enso/pull/6035
[6097]: https://github.com/enso-org/enso/pull/6097
[6097]: https://github.com/enso-org/enso/pull/6341
[6341]: https://github.com/enso-org/enso/pull/6341
[6470]: https://github.com/enso-org/enso/pull/6470

#### Enso Standard Library

@@ -402,6 +405,8 @@
`Time_Of_Day`, `Time_Zone`, and `URI` to `Text`.][6404]
- [Implemented `create_database_table` allowing upload of in-memory
tables.][6429]
- [Added execution context control to writing files and dry run capabilities to
`Text.write`.][6459]

[debug-shortcuts]:
https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug
@@ -606,6 +611,7 @@
[6404]: https://github.com/enso-org/enso/pull/6404
[6347]: https://github.com/enso-org/enso/pull/6347
[6429]: https://github.com/enso-org/enso/pull/6429
[6459]: https://github.com/enso-org/enso/pull/6459

#### Enso Compiler

2 changes: 1 addition & 1 deletion app/gui/controller/engine-protocol/src/language_server.rs
Original file line number Diff line number Diff line change
@@ -157,7 +157,7 @@ trait API {

/// Restart the program execution.
#[MethodInput=RecomputeInput, rpc_name="executionContext/recompute"]
fn recompute(&self, context_id: ContextId, invalidated_expressions: InvalidatedExpressions, mode: Option<ExecutionEnvironment>) -> ();
fn recompute(&self, context_id: ContextId, invalidated_expressions: InvalidatedExpressions, execution_environment: Option<ExecutionEnvironment>) -> ();

/// Obtain the full suggestions database.
#[MethodInput=GetSuggestionsDatabaseInput, rpc_name="search/getSuggestionsDatabase"]
8 changes: 8 additions & 0 deletions app/gui/language/ast/impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -623,6 +623,14 @@ impl<T> SpanSeed<T> {
pub fn child(node: T) -> Self {
Self::Child(SpanSeedChild { node })
}

pub fn token(token: String) -> Self {
Self::Token(SpanSeedToken { token })
}

pub fn is_child(&self) -> bool {
matches!(self, SpanSeed::Child { .. })
}
}


80 changes: 68 additions & 12 deletions app/gui/language/span-tree/src/action.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ use crate::SpanTree;
use ast::opr::match_named_argument;
use ast::opr::ArgWithOffset;
use ast::Ast;
use ast::SpanSeed;



@@ -142,6 +143,33 @@ impl<'a, T> Implementation for node::Ref<'a, T> {
),
};
Ok(infix.into_ast())
} else if let ast::Shape::Tree(tree) = ast.shape() {
let mut tree = tree.clone();
let span_info = &mut tree.span_info;
let has_children =
span_info.iter().any(|span| matches!(span, ast::SpanSeed::Child(_)));
match *kind {
BeforeArgument(index) => {
span_info.insert(index, ast::SpanSeed::child(new));
span_info.insert(index + 1, ast::SpanSeed::token(",".to_owned()));
span_info.insert(index + 2, ast::SpanSeed::space(1).unwrap());
}
Append => {
let last_token_index = span_info
.iter()
.rposition(|span| matches!(span, ast::SpanSeed::Token(_)));
let index = last_token_index.unwrap_or(0);
if has_children {
span_info.insert(index, ast::SpanSeed::token(",".to_owned()));
span_info.insert(index + 1, ast::SpanSeed::space(1).unwrap());
span_info.insert(index + 2, ast::SpanSeed::child(new));
} else {
span_info.insert(index, ast::SpanSeed::child(new));
}
}
_ => unreachable!("Wrong insertion point in tree."),
}
Ok(ast.with_shape(tree))
} else {
let mut prefix = ast::prefix::Chain::from_ast_non_strict(&ast);
let item = ast::prefix::Argument::new(new, DEFAULT_OFFSET, None);
@@ -236,7 +264,6 @@ impl<'a, T> Implementation for node::Ref<'a, T> {
}
}


fn erase_impl<C: Context>(&self) -> Option<EraseOperation<C>> {
if self.node.kind.removable() {
Some(Box::new(move |root, context| {
@@ -245,6 +272,11 @@ impl<'a, T> Implementation for node::Ref<'a, T> {
let mut ast = root.get_traversing(parent_crumbs)?;
let is_named_argument = match_named_argument(ast).is_some();

// When an element is removed, we have to find an adequate span tree node that
// could become a new temporary target of dragged edge. It should be a node that
// has an reverse set operation to the erase we are performing now.
let mut reinsert_crumbs = None;

if is_named_argument {
// When erasing named argument, we need to remove the whole argument, not only
// the value part. The named argument AST is always a single infix expression,
@@ -266,6 +298,28 @@ impl<'a, T> Implementation for node::Ref<'a, T> {
infix.args.pop();
}
Ok(infix.into_ast())
} else if let (Crumb::Tree(crumb), ast::Shape::Tree(tree)) =
(last_crumb, ast.shape())
{
let index = crumb.index;
let mut tree = tree.clone();
let span_info: &mut Vec<_> = &mut tree.span_info;
let after = &span_info[index + 1..];
let before = &span_info[..index];
let is_child = |span: &SpanSeed<Ast>| span.is_child();
let child_after_offset = after.iter().position(is_child);
let child_before_offset = before.iter().rposition(is_child);
let (insertion_point_offset, removed_range) =
match (child_after_offset, child_before_offset) {
(Some(after), _) => (-1, index..=index + after),
(None, Some(before)) => (-2, before + 1..=index),
(None, None) => (-1, index..=index),
};

reinsert_crumbs =
Some(self.crumbs.relative_sibling(insertion_point_offset));
span_info.drain(removed_range);
Ok(ast.with_shape(tree))
} else {
let mut prefix = ast::prefix::Chain::from_ast_non_strict(&ast);
prefix.args.pop();
@@ -327,17 +381,19 @@ impl<'a, T> Implementation for node::Ref<'a, T> {
// placeholder. The position of placeholder is not guaranteed to be in the same
// place as the removed argument, as it might have been out of order. To find
// the correct placeholder position, we need to search regenerated span-tree.
let reinsert_crumbs = self.kind.definition_index().and_then(|_| {
let call_id = self.kind.call_id();
let name = self.kind.argument_name();

let found = new_span_tree.root_ref().find_node(|node| {
node.kind.is_insertion_point()
&& node.kind.call_id() == call_id
&& node.kind.argument_name() == name
});

found.map(|found| found.crumbs)
let reinsert_crumbs = reinsert_crumbs.or_else(|| {
self.kind.definition_index().and_then(|_| {
let call_id = self.kind.call_id();
let name = self.kind.argument_name();

let found = new_span_tree.root_ref().find_node(|node| {
node.kind.is_insertion_point()
&& node.kind.call_id() == call_id
&& node.kind.argument_name() == name
});

found.map(|found| found.crumbs)
})
});

// For non-resolved arguments, use the preceding insertion point. After the
28 changes: 27 additions & 1 deletion app/gui/language/span-tree/src/generate.rs
Original file line number Diff line number Diff line change
@@ -819,13 +819,28 @@ fn tree_generate_node<T: Payload>(
} else {
let mut parent_offset = ByteDiff::from(0);
let mut sibling_offset = ByteDiff::from(0);
let first_token_or_child =
tree.span_info.iter().find(|span| !matches!(span, SpanSeed::Space(_)));
let is_array = matches!(first_token_or_child, Some(SpanSeed::Token(ast::SpanSeedToken { token })) if token == "[");
let last_token_index =
tree.span_info.iter().rposition(|span| matches!(span, SpanSeed::Token(_)));
for (index, raw_span_info) in tree.span_info.iter().enumerate() {
match raw_span_info {
SpanSeed::Space(ast::SpanSeedSpace { space }) => {
parent_offset += ByteDiff::from(space);
sibling_offset += ByteDiff::from(space);
}
SpanSeed::Token(ast::SpanSeedToken { token }) => {
if is_array && Some(index) == last_token_index {
let kind = InsertionPointType::Append;
children.push(node::Child {
node: Node::<T>::new().with_kind(kind),
parent_offset,
sibling_offset,
ast_crumbs: vec![],
});
sibling_offset = 0.byte_diff();
}
let kind = node::Kind::Token;
let size = ByteDiff::from(token.len());
let ast_crumbs = vec![TreeCrumb { index }.into()];
@@ -835,7 +850,18 @@ fn tree_generate_node<T: Payload>(
sibling_offset = 0.byte_diff();
}
SpanSeed::Child(ast::SpanSeedChild { node }) => {
let kind = node::Kind::argument();
if is_array {
let kind = InsertionPointType::BeforeArgument(index);
children.push(node::Child {
node: Node::<T>::new().with_kind(kind),
parent_offset,
sibling_offset,
ast_crumbs: vec![],
});
sibling_offset = 0.byte_diff();
}

let kind = node::Kind::argument().with_removable(is_array);
let node = node.generate_node(kind, context)?;
let child_size = node.size;
let ast_crumbs = vec![TreeCrumb { index }.into()];
11 changes: 10 additions & 1 deletion app/gui/language/span-tree/src/node.rs
Original file line number Diff line number Diff line change
@@ -255,6 +255,15 @@ impl Crumbs {
vec.push(child);
self
}

/// Create crumbs to the sibling node, which is `offset` nodes away from the current node.
pub fn relative_sibling(&self, offset: isize) -> Self {
let mut vec = self.vec.deref().clone();
if let Some(last) = vec.last_mut() {
*last = last.saturating_add_signed(offset)
}
Self { vec: Rc::new(vec) }
}
}

impl<T: IntoIterator<Item = Crumb>> From<T> for Crumbs {
@@ -391,7 +400,7 @@ impl<'a, T> Ref<'a, T> {
}

/// Iterator over all direct children producing `Ref`s.
pub fn children_iter(self) -> impl DoubleEndedIterator<Item = Ref<'a, T>> {
pub fn children_iter(self) -> impl DoubleEndedIterator<Item = Ref<'a, T>> + Clone {
let children_count = self.node.children.len();
(0..children_count).map(move |i| self.clone().child(i).unwrap())
}
9 changes: 3 additions & 6 deletions app/gui/src/presenter/graph.rs
Original file line number Diff line number Diff line change
@@ -300,18 +300,15 @@ impl Model {
let update = self.state.update_from_view();
let ast_to_remove = update.remove_connection(id)?;
Some(self.controller.disconnect(&ast_to_remove).map(|target_crumbs| {
target_crumbs.and_then(|crumbs| {
if let Some(crumbs) = target_crumbs {
trace!(
"Updating edge target after disconnecting it. New crumbs: {crumbs:?}"
);
// If we are still using this edge (e.g. when dragging it), we need to
// update its target endpoint. Otherwise it will not reflect expression
// update performed on the target node.
let edge = self.view.model.edges.get_cloned_ref(&id)?;
let outdated_target = edge.target()?;
edge.set_target(EdgeEndpoint::new(outdated_target.node_id, crumbs));
Some(())
});
self.view.replace_detached_edge_target((id, crumbs));
};
}))
},
"delete connection",
2 changes: 1 addition & 1 deletion app/gui/view/graph-editor/src/component/breadcrumbs.rs
Original file line number Diff line number Diff line change
@@ -166,7 +166,7 @@ impl BreadcrumbsModel {
pub fn new(app: Application, frp: &Frp) -> Self {
let scene = &app.display.default_scene;
let project_name = app.new_view();
let display_object = display::object::Instance::new();
let display_object = display::object::Instance::new_named("Breadcrumbs");
let root = display::object::Instance::new();
let breadcrumbs_container = display::object::Instance::new();
let scene = scene.clone_ref();
4 changes: 2 additions & 2 deletions app/gui/view/graph-editor/src/component/edge.rs
Original file line number Diff line number Diff line change
@@ -779,7 +779,7 @@ macro_rules! define_components {
/// Constructor.
#[allow(clippy::vec_init_then_push)]
pub fn new() -> Self {
let display_object = display::object::Instance::new();
let display_object = display::object::Instance::new_named(stringify!($name));
$(let $field = <$field_type>::new();)*
$(display_object.add_child(&$field);)*
let mut shape_view_events:Vec<PointerTarget_DEPRECATED> = Vec::default();
@@ -1304,7 +1304,7 @@ impl EdgeModelData {
/// Constructor.
#[profile(Debug)]
pub fn new(scene: &Scene, network: &frp::Network) -> Self {
let display_object = display::object::Instance::new();
let display_object = display::object::Instance::new_named("Edge");
let front = Front::new();
let back = Back::new();
let joint = joint::View::new();
2 changes: 1 addition & 1 deletion app/gui/view/graph-editor/src/component/node.rs
Original file line number Diff line number Diff line change
@@ -513,7 +513,7 @@ impl NodeModel {
let background = background::View::new();
let drag_area = drag_area::View::new();
let vcs_indicator = vcs::StatusIndicator::new(app);
let display_object = display::object::Instance::new();
let display_object = display::object::Instance::new_named("Node");

display_object.add_child(&profiling_label);
display_object.add_child(&drag_area);
4 changes: 3 additions & 1 deletion app/gui/view/graph-editor/src/component/node/input/area.rs
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ use enso_frp;
use ensogl::application::Application;
use ensogl::data::color;
use ensogl::display;
use ensogl::display::world::with_context;
use ensogl::gui::cursor;
use ensogl::Animation;
use ensogl_component::text;
@@ -152,13 +153,14 @@ impl Model {
#[profile(Debug)]
pub fn new(app: &Application) -> Self {
let app = app.clone_ref();
let display_object = display::object::Instance::new();
let display_object = display::object::Instance::new_named("input");

let edit_mode_label = app.new_view::<text::Text>();
let expression = default();
let styles = StyleWatch::new(&app.display.default_scene.style_sheet);
let styles_frp = StyleWatchFrp::new(&app.display.default_scene.style_sheet);
let widget_tree = widget::Tree::new(&app);
with_context(|ctx| ctx.layers.widget.add(&widget_tree));
Self { app, display_object, edit_mode_label, expression, styles, styles_frp, widget_tree }
.init()
}
Loading

0 comments on commit 4234c47

Please sign in to comment.