mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 17:34:10 +03:00
Add API to mark node VCS status. (https://github.com/enso-org/ide/pull/1160)
Original commit: 3c8b4b37ad
This commit is contained in:
parent
6229013e87
commit
0b4bf473d1
@ -36,12 +36,14 @@ read the notes of the `Enso 2.0.0-alpha.1` release.
|
||||
- [Added the ability to reposition visualisations.][1096] There is now an icon in the visualization
|
||||
action bar that allows dragging the visualization. Once the visualization has been moved, there
|
||||
appears another icon that will reset the position to the original position.
|
||||
- [There is now an API to show VCS status for node][1160].
|
||||
- [A shortcut for reloading visualization files.][1190] The visible visualizations must be switched
|
||||
to another and switched back to see the effect.
|
||||
|
||||
[1096]: https://github.com/enso-org/ide/pull/1172
|
||||
[1098]: https://github.com/enso-org/ide/pull/1098
|
||||
[1181]: https://github.com/enso-org/ide/pull/1181
|
||||
[1160]: https://github.com/enso-org/ide/pull/1160
|
||||
[1190]: https://github.com/enso-org/ide/pull/1190
|
||||
<br/>
|
||||
|
||||
|
@ -199,6 +199,11 @@ define_themes! { [light:0, dark:1]
|
||||
hovered = Lcha(0.0,0.0,0.0,0.45) , Lcha(1.0,0.0,0.0,0.7);
|
||||
}
|
||||
}
|
||||
vcs {
|
||||
unchanged = Lcha::transparent(), Lcha::transparent();
|
||||
added = Lcha::green(0.8,1.0), Lcha::green(0.8,1.0);
|
||||
edited = Lcha::yellow(0.9,1.0), Lcha::yellow(0.9,1.0);
|
||||
}
|
||||
}
|
||||
visualization {
|
||||
background = Lcha(0.98,0.014,0.18,1.0) , Lcha(0.2,0.014,0.18,1.0);
|
||||
|
@ -10,6 +10,8 @@ pub mod input;
|
||||
pub mod output;
|
||||
#[deny(missing_docs)]
|
||||
pub mod error;
|
||||
#[deny(missing_docs)]
|
||||
pub mod vcs;
|
||||
|
||||
pub use expression::Expression;
|
||||
pub use error::Error;
|
||||
@ -248,6 +250,7 @@ ensogl::define_endpoints! {
|
||||
/// colored if the definition type was present.
|
||||
set_expression_usage_type (Crumbs,Option<Type>),
|
||||
set_output_expression_visibility (bool),
|
||||
set_vcs_status (Option<vcs::Status>),
|
||||
}
|
||||
Output {
|
||||
/// Press event. Emitted when user clicks on non-active part of the node, like its
|
||||
@ -350,6 +353,7 @@ pub struct NodeModel {
|
||||
pub output : output::Area,
|
||||
pub visualization : visualization::Container,
|
||||
pub action_bar : action_bar::ActionBar,
|
||||
pub vcs_indicator : vcs::StatusIndicator,
|
||||
}
|
||||
|
||||
impl NodeModel {
|
||||
@ -381,12 +385,14 @@ impl NodeModel {
|
||||
let main_area = shape::View::new(&main_logger);
|
||||
let drag_area = drag_area::View::new(&drag_logger);
|
||||
let error_text = app.new_view::<text::Area>();
|
||||
let vcs_indicator = vcs::StatusIndicator::new(app);
|
||||
|
||||
let display_object = display::object::Instance::new(&logger);
|
||||
display_object.add_child(&drag_area);
|
||||
display_object.add_child(&main_area);
|
||||
display_object.add_child(&error_indicator);
|
||||
display_object.add_child(&error_text);
|
||||
display_object.add_child(&vcs_indicator);
|
||||
|
||||
error_text.set_default_color.emit(color::Rgba::red());
|
||||
error_text.set_default_text_size(TextSize::from(TEXT_SIZE));
|
||||
@ -411,7 +417,7 @@ impl NodeModel {
|
||||
|
||||
let app = app.clone_ref();
|
||||
Self {app,display_object,logger,main_area,drag_area,output,input,visualization,action_bar,
|
||||
error_indicator,error_text}.init()
|
||||
error_indicator,error_text,vcs_indicator}.init()
|
||||
}
|
||||
|
||||
pub fn get_crumbs_by_id(&self, id:ast::Id) -> Option<Crumbs> {
|
||||
@ -452,10 +458,13 @@ impl NodeModel {
|
||||
self.main_area.size.set(padded_size);
|
||||
self.drag_area.size.set(padded_size);
|
||||
self.error_indicator.size.set(padded_size);
|
||||
self.vcs_indicator.set_size(padded_size);
|
||||
self.main_area.mod_position(|t| t.x = width/2.0);
|
||||
self.drag_area.mod_position(|t| t.x = width/2.0);
|
||||
|
||||
self.error_indicator.set_position_x(width/2.0);
|
||||
self.vcs_indicator.set_position_x(width/2.0);
|
||||
|
||||
self.error_text.set_position_y(height + TEXT_SIZE);
|
||||
self.error_text.set_position_x(CORNER_RADIUS);
|
||||
|
||||
@ -584,6 +593,10 @@ impl Node {
|
||||
eval bg_color_anim.value ((c)
|
||||
model.main_area.bg_color.set(color::Rgba::from(c).into())
|
||||
);
|
||||
|
||||
|
||||
// === VCS Handling ===
|
||||
model.vcs_indicator.frp.set_status <+ frp.set_vcs_status;
|
||||
}
|
||||
|
||||
frp.set_error.emit(None);
|
||||
|
200
gui/src/rust/ide/view/graph-editor/src/component/node/vcs.rs
Normal file
200
gui/src/rust/ide/view/graph-editor/src/component/node/vcs.rs
Normal file
@ -0,0 +1,200 @@
|
||||
//! Functionality related to visualising the version control system status of a node.
|
||||
|
||||
use crate::component::node as node;
|
||||
use crate::prelude::*;
|
||||
|
||||
use enso_frp as frp;
|
||||
use ensogl::application::Application;
|
||||
use ensogl::data::color;
|
||||
use ensogl::display::shape::*;
|
||||
use ensogl::display;
|
||||
|
||||
|
||||
|
||||
// ==============
|
||||
// === Status ===
|
||||
// ==============
|
||||
|
||||
/// The version control system status of a node.
|
||||
#[derive(Debug,Copy,Clone)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum Status {
|
||||
Unchanged,
|
||||
Added,
|
||||
Edited,
|
||||
}
|
||||
|
||||
impl Status {
|
||||
fn get_highlight_color_from_style(self, style:&StyleWatch) -> color::Lcha {
|
||||
match self {
|
||||
Status::Unchanged => style.get_color(ensogl_theme::graph_editor::node::vcs::unchanged),
|
||||
Status::Added => style.get_color(ensogl_theme::graph_editor::node::vcs::added),
|
||||
Status::Edited => style.get_color(ensogl_theme::graph_editor::node::vcs::edited),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Status {
|
||||
fn default() -> Self {
|
||||
Status::Unchanged
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// =======================
|
||||
// === Indicator Shape ===
|
||||
// =======================
|
||||
|
||||
/// Shape used in the status indicator. Appears as a colored border surrounding the node.
|
||||
mod status_indicator_shape {
|
||||
use super::*;
|
||||
|
||||
const INDICATOR_WIDTH_OUTER : f32 = 15.0;
|
||||
const INDICATOR_WIDTH_INNER : f32 = 10.0;
|
||||
|
||||
ensogl::define_shape_system! {
|
||||
(style:Style,color_rgba:Vector4<f32>) {
|
||||
let width = Var::<Pixels>::from("input_size.x");
|
||||
let height = Var::<Pixels>::from("input_size.y");
|
||||
let width = width - node::PADDING.px() * 2.0;
|
||||
let height = height - node::PADDING.px() * 2.0;
|
||||
let radius = node::RADIUS.px();
|
||||
|
||||
let base = Rect((&width,&height)).corners_radius(&radius);
|
||||
let outer = base.grow(INDICATOR_WIDTH_OUTER.px());
|
||||
let inner = base.grow(INDICATOR_WIDTH_INNER.px());
|
||||
|
||||
(outer-inner).fill(color_rgba).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==============================
|
||||
// === Status Indicator Model ===
|
||||
// ==============================
|
||||
|
||||
/// Internal data of `StatusIndicator`.
|
||||
#[derive(Clone,CloneRef,Debug)]
|
||||
struct StatusIndicatorModel {
|
||||
shape : status_indicator_shape::View,
|
||||
root : display::object::Instance,
|
||||
}
|
||||
|
||||
impl StatusIndicatorModel {
|
||||
fn new(logger: &Logger) -> Self {
|
||||
let shape = status_indicator_shape::View::new(logger);
|
||||
let root = display::object::Instance::new(&logger);
|
||||
root.add_child(&shape);
|
||||
StatusIndicatorModel{shape, root}
|
||||
}
|
||||
|
||||
fn hide(&self) {
|
||||
self.shape.unset_parent();
|
||||
}
|
||||
|
||||
fn show(&self) {
|
||||
self.root.add_child(&self.shape);
|
||||
}
|
||||
|
||||
fn set_visibility(&self, visibility:bool) {
|
||||
if visibility {
|
||||
self.show()
|
||||
} else {
|
||||
self.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl display::Object for StatusIndicatorModel {
|
||||
fn display_object(&self) -> &display::object::Instance {
|
||||
&self.root
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// =======================
|
||||
// === StatusIndicator ===
|
||||
// =======================
|
||||
|
||||
ensogl::define_endpoints! {
|
||||
Input {
|
||||
set_status (Option<Status>),
|
||||
set_size (Vector2),
|
||||
set_visibility (bool),
|
||||
}
|
||||
Output {
|
||||
status (Option<Status>),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone,CloneRef,Debug)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct StatusIndicator {
|
||||
model : Rc<StatusIndicatorModel>,
|
||||
pub frp : Frp,
|
||||
}
|
||||
|
||||
impl StatusIndicator {
|
||||
/// Constructor.
|
||||
pub fn new(app:&Application) -> Self {
|
||||
let logger = Logger::new("status_indicator");
|
||||
let model = Rc::new(StatusIndicatorModel::new(&logger));
|
||||
let frp = Frp::new();
|
||||
Self {frp,model}.init_frp(app)
|
||||
}
|
||||
|
||||
fn init_frp(self, app:&Application) -> Self {
|
||||
let frp = &self.frp;
|
||||
let model = &self.model;
|
||||
let network = &frp.network;
|
||||
let indicator_color = color::Animation::new(network);
|
||||
|
||||
// FIXME : StyleWatch is unsuitable here, as it was designed as an internal tool for shape
|
||||
// system (#795)
|
||||
let styles = StyleWatch::new(&app.display.scene().style_sheet);
|
||||
|
||||
frp::extend! { network
|
||||
frp.source.status <+ frp.input.set_status;
|
||||
|
||||
status_color <- frp.set_status.unwrap().map(f!([styles](status)
|
||||
status.get_highlight_color_from_style(&styles)
|
||||
));
|
||||
indicator_color.target <+ status_color;
|
||||
|
||||
eval indicator_color.value ((c)
|
||||
model.shape.color_rgba.set(color::Rgba::from(c).into())
|
||||
);
|
||||
|
||||
eval frp.input.set_size ((size)
|
||||
model.shape.size.set(*size);
|
||||
);
|
||||
|
||||
has_status <- frp.status.map(|status| status.is_some());
|
||||
visible <- and(&frp.input.set_visibility,&has_status);
|
||||
eval visible ([model](visible) model.set_visibility(*visible));
|
||||
};
|
||||
|
||||
frp.set_status.emit(None);
|
||||
frp.set_visibility.emit(true);
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl display::Object for StatusIndicator {
|
||||
fn display_object(&self) -> &display::object::Instance {
|
||||
&self.model.display_object()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for StatusIndicator {
|
||||
type Target = Frp;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.frp
|
||||
}
|
||||
}
|
@ -408,6 +408,11 @@ ensogl::define_endpoints! {
|
||||
debug_set_test_visualization_data_for_selected_node(),
|
||||
|
||||
|
||||
// === VCS Status ===
|
||||
|
||||
set_node_vcs_status ((NodeId,Option<node::vcs::Status>)),
|
||||
|
||||
|
||||
set_detached_edge_targets (EdgeEndpoint),
|
||||
set_detached_edge_sources (EdgeEndpoint),
|
||||
set_edge_source ((EdgeId,EdgeEndpoint)),
|
||||
@ -2794,6 +2799,16 @@ fn new_graph_editor(app:&Application) -> GraphEditor {
|
||||
|
||||
|
||||
|
||||
// ================
|
||||
// === Node VCS ===
|
||||
// ================
|
||||
|
||||
eval inputs.set_node_vcs_status(((node_id,status))
|
||||
model.with_node(*node_id, |node| node.set_vcs_status.emit(status))
|
||||
);
|
||||
|
||||
|
||||
|
||||
// ==================
|
||||
// === Edge Binds ===
|
||||
// ==================
|
||||
|
@ -130,6 +130,29 @@ fn init(app:&Application) {
|
||||
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();
|
||||
@ -215,6 +238,7 @@ fn init(app:&Application) {
|
||||
// =============
|
||||
|
||||
use crate::graph_editor::component::node::Expression;
|
||||
use crate::graph_editor::component::node::vcs;
|
||||
|
||||
use ast::crumbs::*;
|
||||
use ast::crumbs::PatternMatchCrumb::*;
|
||||
@ -223,6 +247,19 @@ 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(&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();
|
||||
Expression {pattern,code,input_span_tree,output_span_tree}
|
||||
}
|
||||
|
||||
pub fn expression_mock() -> Expression {
|
||||
let pattern = Some("var1".to_string());
|
||||
let code = "[1,2,3]".to_string();
|
||||
|
Loading…
Reference in New Issue
Block a user