diff --git a/doc/distrib/NodeHelpFiles/CoreNodeModelsWpf.Charts.BasicLineChartNodeModel.md b/doc/distrib/NodeHelpFiles/CoreNodeModelsWpf.Charts.BasicLineChartNodeModel.md
index 80e6fbc41d1..16a8150d475 100644
--- a/doc/distrib/NodeHelpFiles/CoreNodeModelsWpf.Charts.BasicLineChartNodeModel.md
+++ b/doc/distrib/NodeHelpFiles/CoreNodeModelsWpf.Charts.BasicLineChartNodeModel.md
@@ -1,6 +1,6 @@
## In Depth
-Basic Line creates a line chart with one or multiple labeled and color-coded lines plotted along a series of points. The number of string values in the list entered in the labels input determines the number of lines in the chart, along with their corresponding labels.
+Index-Value Line Plot creates a line chart with one or multiple labeled and color-coded lines plotted along a series of points. The number of string values in the list entered in the labels input determines the number of lines in the chart, along with their corresponding labels.
A list of double value lists entered into the values input determines the position of each point along the line(s). Assign a color for each line by entering a list of color values into the colors input.
___
diff --git a/src/DynamoCore/Graph/Nodes/NodeModel.cs b/src/DynamoCore/Graph/Nodes/NodeModel.cs
index 55a5f924989..2b1b8101ae6 100644
--- a/src/DynamoCore/Graph/Nodes/NodeModel.cs
+++ b/src/DynamoCore/Graph/Nodes/NodeModel.cs
@@ -1735,10 +1735,15 @@ public virtual void ClearErrorsAndWarnings()
///
/// Clears the info messages that are generated when running the graph,
- /// the State will be set to ElementState.Dead.
+ /// the State will be set to ElementState.Active.
///
public virtual void ClearInfoMessages()
{
+ if (State == ElementState.Info)
+ {
+ State = ElementState.Active;
+ }
+
infos.RemoveWhere(x => x.State == ElementState.Info);
OnNodeInfoMessagesClearing();
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/BarChartNodeModel.cs b/src/Libraries/CoreNodeModelsWpf/Charts/BarChartNodeModel.cs
index accae76bac2..2d0531cfc0c 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/BarChartNodeModel.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/BarChartNodeModel.cs
@@ -18,6 +18,10 @@
using Dynamo.UI;
using DynamoServices;
using Dynamo.Wpf.Properties;
+using Dynamo.Graph.Connectors;
+using System.Linq;
+using Newtonsoft.Json.Linq;
+using Dynamo.ViewModels;
namespace CoreNodeModelsWpf.Charts
{
@@ -26,9 +30,16 @@ namespace CoreNodeModelsWpf.Charts
[NodeCategory("Display.Charts.Create")]
[NodeDescription("ChartsBarChartDescription", typeof(CoreNodeModelWpfResources))]
[NodeSearchTags("ChartsBarChartSearchTags", typeof(CoreNodeModelWpfResources))]
-
+ [InPortNames("labels", "values", "colors")]
[InPortTypes("List", "List", "List")]
- [OutPortTypes("Dictionary")]
+ [InPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsBarChartLabelsDataPortToolTip",
+ "ChartsBarChartValuesDataPortToolTip",
+ "ChartsBarChartColorsDataPortToolTip")]
+ [OutPortNames("labels:values")]
+ [OutPortTypes("Dictionary")]
+ [OutPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsBarChartLabelsValuesDataPortToolTip")]
[AlsoKnownAs("CoreNodeModelsWpf.Charts.BarChart")]
public class BarChartNodeModel : NodeModel
{
@@ -50,6 +61,16 @@ public class BarChartNodeModel : NodeModel
/// Bar chart color values.
///
public List Colors { get; set; }
+
+ ///
+ /// Triggers when port is connected or disconnected
+ ///
+ public event EventHandler PortUpdated;
+
+ protected virtual void OnPortUpdated(EventArgs args)
+ {
+ PortUpdated?.Invoke(this, args);
+ }
#endregion
#region Constructors
@@ -58,25 +79,21 @@ public class BarChartNodeModel : NodeModel
///
public BarChartNodeModel()
{
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("labels", "A list of labels for the bar chart categories.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("values", "A list (of lists) to supply values for the bars in each category.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("colors", "A list of colors for each bar chart category.")));
-
- OutPorts.Add(new PortModel(PortType.Output, this, new PortData("labels:values", "Dictionary containing label:value key-pairs")));
-
RegisterAllPorts();
+ PortConnected += BarChartNodeModel_PortConnected;
PortDisconnected += BarChartNodeModel_PortDisconnected;
ArgumentLacing = LacingStrategy.Disabled;
}
- [JsonConstructor]
///
/// Instantiate a new NodeModel instance.
///
+ [JsonConstructor]
public BarChartNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
+ PortConnected += BarChartNodeModel_PortConnected;
PortDisconnected += BarChartNodeModel_PortDisconnected;
}
#endregion
@@ -84,16 +101,28 @@ public BarChartNodeModel(IEnumerable inPorts, IEnumerable
#region Events
private void BarChartNodeModel_PortDisconnected(PortModel port)
{
+ OnPortUpdated(null);
// Clear UI when a input port is disconnected
- if (port.PortType == PortType.Input && this.State == ElementState.Active)
+ if (port.PortType == PortType.Input)
{
- Labels.Clear();
- Values.Clear();
- Colors.Clear();
+ Labels?.Clear();
+ Values?.Clear();
+ Colors?.Clear();
RaisePropertyChanged("DataUpdated");
}
}
+ private void BarChartNodeModel_PortConnected(PortModel port, ConnectorModel arg2)
+ {
+ // Reset an info states if any
+ if (port.PortType == PortType.Input && InPorts[2].IsConnected && NodeInfos.Any(x => x.State.Equals(ElementState.Info)))
+ {
+ this.ClearInfoMessages();
+ }
+
+ OnPortUpdated(null);
+ RaisePropertyChanged("DataUpdated");
+ }
#endregion
#region databridge
@@ -126,10 +155,9 @@ private void DataBridgeCallback(object data)
var values = inputs[1] as ArrayList;
var colors = inputs[2] as ArrayList;
- // Only continue if key/values match in length
- if (labels.Count != values.Count && labels.Count != (values[0] as ArrayList).Count)
+ if (!InPorts[0].IsConnected && !InPorts[1].IsConnected && !InPorts[2].IsConnected)
{
- throw new Exception("Label and Values do not properly align in length.");
+ return;
}
// Update chart properties
@@ -137,6 +165,14 @@ private void DataBridgeCallback(object data)
Values = new List>();
Colors = new List();
+ var anyNullData = labels == null || values == null;
+
+ // Only continue if key/values match in length
+ if (anyNullData || labels.Count != values.Count && labels.Count != (values[0] as ArrayList).Count || labels.Count == 0)
+ {
+ throw new Exception("Label and Values do not properly align in length.");
+ }
+
// If the bar chart contains nested lists
if (values[0] is ArrayList)
{
@@ -159,6 +195,8 @@ private void DataBridgeCallback(object data)
Color color;
if (colors == null || colors.Count == 0 || colors.Count != labels.Count)
{
+ if (InPorts[2].IsConnected) return;
+
// In case colors are not provided, we supply some from the default library of colors
Info(Dynamo.Wpf.Properties.CoreNodeModelWpfResources.ProvideDefaultColorsWarningMessage);
@@ -166,7 +204,6 @@ private void DataBridgeCallback(object data)
}
else
{
-
var dynColor = (DSCore.Color)colors[i];
color = Color.FromArgb(dynColor.Alpha, dynColor.Red, dynColor.Green, dynColor.Blue);
}
@@ -191,6 +228,11 @@ private void DataBridgeCallback(object data)
Color color;
if (colors == null || colors.Count == 0 || colors.Count != labels.Count)
{
+ if (InPorts[3].IsConnected) return;
+
+ // In case colors are not provided, we supply some from the default library of colors
+ Info(Dynamo.Wpf.Properties.CoreNodeModelWpfResources.ProvideDefaultColorsWarningMessage);
+
color = Utilities.Colors.GetColor();
}
else
@@ -227,41 +269,61 @@ public override IEnumerable BuildOutputAst(List, List, List, Dictionary>(BarChartFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
+ );
+
return new[]
{
- AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()),
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
};
}
-
- AssociativeNode inputNode;
- if (isNestedList)
+ else if (!InPorts[0].IsConnected || !InPorts[1].IsConnected)
{
- inputNode = AstFactory.BuildFunctionCall(
- new Func, List>, List, Dictionary>>(BarChartFunctions.GetNodeInput),
- new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
- );
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()),
+ };
}
else
{
- inputNode = AstFactory.BuildFunctionCall(
- new Func, List, List, Dictionary>(BarChartFunctions.GetNodeInput),
- new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
- );
+ if (isNestedList)
+ {
+ inputNode = AstFactory.BuildFunctionCall(
+ new Func, List>, List, Dictionary>>(BarChartFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
+ );
+ }
+ else
+ {
+ inputNode = AstFactory.BuildFunctionCall(
+ new Func, List, List, Dictionary>(BarChartFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
+ );
+ }
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
}
- return new[]
- {
- AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
- AstFactory.BuildAssignment(
- AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
- VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
- )
- ),
- };
}
#endregion
@@ -272,6 +334,7 @@ public override IEnumerable BuildOutputAst(List
public override void Dispose()
{
+ PortConnected -= BarChartNodeModel_PortConnected;
PortDisconnected -= BarChartNodeModel_PortDisconnected;
VMDataBridge.DataBridge.Instance.UnregisterCallback(GUID.ToString());
}
@@ -285,6 +348,8 @@ public override void Dispose()
public class BarChartNodeView : INodeViewCustomization
{
private BarChartControl barChartControl;
+ private NodeView view;
+ private BarChartNodeModel model;
///
/// At run-time, this method is called during the node
@@ -294,6 +359,8 @@ public class BarChartNodeView : INodeViewCustomization
/// The NodeView representing the node in the graph.
public void CustomizeView(BarChartNodeModel model, NodeView nodeView)
{
+ this.model = model;
+ this.view = nodeView;
barChartControl = new BarChartControl(model);
nodeView.inputGrid.Children.Add(barChartControl);
@@ -303,6 +370,49 @@ public void CustomizeView(BarChartNodeModel model, NodeView nodeView)
var contextMenu = (nodeView.Content as Grid).ContextMenu;
contextMenu.Items.Add(exportImage);
+
+ UpdateDefaultInPortValues();
+
+ model.PortUpdated += ModelOnPortUpdated;
+ }
+
+ private void ModelOnPortUpdated(object sender, EventArgs e)
+ {
+ UpdateDefaultInPortValues();
+ }
+
+ private void UpdateDefaultInPortValues()
+ {
+ if (!this.view.ViewModel.InPorts.Any()) return;
+ var inPorts = this.view.ViewModel.InPorts;
+
+ // Only apply default values if all ports are disconnected
+ if (!model.IsInErrorState &&
+ model.State != ElementState.Active &&
+ !inPorts[0].IsConnected &&
+ !inPorts[1].IsConnected)
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = true;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = false;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = false;
+ }
+
+ var allPortsConnected = inPorts[0].IsConnected && inPorts[1].IsConnected && model.State != ElementState.Warning;
+ var noPortsConnected = !inPorts[0].IsConnected && !inPorts[1].IsConnected;
+
+ // The color input uses default values if it's not connected
+ if (!inPorts[2].IsConnected && (allPortsConnected || noPortsConnected))
+ {
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = false;
+ }
}
private void ExportImage_Click(object sender, RoutedEventArgs e)
@@ -314,6 +424,9 @@ private void ExportImage_Click(object sender, RoutedEventArgs e)
/// Here you can do any cleanup you require if you've assigned callbacks for particular
/// UI events on your node.
///
- public void Dispose() { }
+ public void Dispose()
+ {
+ model.PortUpdated -= ModelOnPortUpdated;
+ }
}
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/BasicLineChartNodeModel.cs b/src/Libraries/CoreNodeModelsWpf/Charts/BasicLineChartNodeModel.cs
index 113fb94963a..c78a6765a1d 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/BasicLineChartNodeModel.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/BasicLineChartNodeModel.cs
@@ -17,6 +17,8 @@
using ProtoCore.AST.AssociativeAST;
using DynamoServices;
using Dynamo.Wpf.Properties;
+using Dynamo.Graph.Connectors;
+using Dynamo.ViewModels;
namespace CoreNodeModelsWpf.Charts
{
@@ -25,9 +27,16 @@ namespace CoreNodeModelsWpf.Charts
[NodeCategory("Display.Charts.Create")]
[NodeDescription("ChartsBasicLineChartDescription", typeof(CoreNodeModelWpfResources))]
[NodeSearchTags("ChartsBasicLineChartSearchTags", typeof(CoreNodeModelWpfResources))]
-
+ [InPortNames("labels", "values", "colors")]
[InPortTypes("List", "List>", "List")]
- [OutPortTypes("Dictionary")]
+ [InPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsBasicLineChartLabelsDataPortToolTip",
+ "ChartsBasicLineChartValuesDataPortToolTip",
+ "ChartsBasicLineChartColorsDataPortToolTip")]
+ [OutPortNames("labels:values")]
+ [OutPortTypes("Dictionary>")]
+ [OutPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsBasicLineChartLabelsValuesDataPortToolTip")]
[AlsoKnownAs("CoreNodeModelsWpf.Charts.Index-ValueLinePlot")]
public class BasicLineChartNodeModel : NodeModel
{
@@ -48,6 +57,16 @@ public class BasicLineChartNodeModel : NodeModel
/// A list of color values, one for each plotted line.
///
public List Colors { get; set; }
+
+ ///
+ /// Triggers when port is connected or disconnected
+ ///
+ public event EventHandler PortUpdated;
+
+ protected virtual void OnPortUpdated(EventArgs args)
+ {
+ PortUpdated?.Invoke(this, args);
+ }
#endregion
#region Constructors
@@ -56,14 +75,9 @@ public class BasicLineChartNodeModel : NodeModel
///
public BasicLineChartNodeModel()
{
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("labels", "A list of string labels for each line to be plotted.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("values", "List of lists each containing double values to be plotted against X-Axis values.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("colors", "A list of colors for each line.")));
-
- OutPorts.Add(new PortModel(PortType.Output, this, new PortData("labels:values", "Dictionary containing label:value key-pairs")));
-
RegisterAllPorts();
+ PortConnected += BasicLineChartNodeModel_PortConnected;
PortDisconnected += BasicLineChartNodeModel_PortDisconnected;
ArgumentLacing = LacingStrategy.Disabled;
@@ -75,6 +89,7 @@ public BasicLineChartNodeModel()
///
public BasicLineChartNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
+ PortConnected += BasicLineChartNodeModel_PortConnected;
PortDisconnected += BasicLineChartNodeModel_PortDisconnected;
}
#endregion
@@ -82,16 +97,29 @@ public BasicLineChartNodeModel(IEnumerable inPorts, IEnumerable x.State.Equals(ElementState.Info)))
+ {
+ this.ClearInfoMessages();
+ }
+
+ OnPortUpdated(null);
+ RaisePropertyChanged("DataUpdated");
+ }
#endregion
#region Databridge
@@ -124,10 +152,9 @@ private void DataBridgeCallback(object data)
var values = inputs[1] as ArrayList;
var colors = inputs[2] as ArrayList;
- // Only continue if key/values match in length
- if (labels.Count != values.Count || labels.Count < 1)
+ if (!InPorts[0].IsConnected && !InPorts[1].IsConnected && !InPorts[2].IsConnected)
{
- throw new Exception("Label and Values do not properly align in length.");
+ return;
}
// Clear current chart values
@@ -135,9 +162,19 @@ private void DataBridgeCallback(object data)
Values = new List>();
Colors = new List();
+ var anyNullData = labels == null || values == null;
+
+ // Only continue if key/values match in length
+ if (anyNullData || labels.Count != values.Count || labels.Count < 1 || labels.Count == 0)
+ {
+ throw new Exception("Label and Values do not properly align in length.");
+ }
+
// If color count doesn't match title count use random colors
if (colors == null || colors.Count == 0 || colors.Count != labels.Count)
{
+ if (InPorts[2].IsConnected) return;
+
// In case colors are not provided, we supply some from the default library of colors
Info(Dynamo.Wpf.Properties.CoreNodeModelWpfResources.ProvideDefaultColorsWarningMessage);
@@ -202,30 +239,50 @@ public override IEnumerable BuildOutputAst(List, List>, List, Dictionary>>(BasicLineChartFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
+ );
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
+ else if (!InPorts[0].IsConnected || !InPorts[1].IsConnected)
{
return new[]
{
AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()),
};
}
-
- AssociativeNode inputNode = AstFactory.BuildFunctionCall(
- new Func, List>, List, Dictionary>>(BasicLineChartFunctions.GetNodeInput),
- new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
- );
-
- return new[]
+ else
{
- AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
- AstFactory.BuildAssignment(
- AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
- VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
- )
- ),
- };
+ inputNode = AstFactory.BuildFunctionCall(
+ new Func, List>, List, Dictionary>>(BasicLineChartFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
+ );
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
}
#endregion
@@ -236,6 +293,7 @@ public override IEnumerable BuildOutputAst(List
public override void Dispose()
{
+ PortConnected -= BasicLineChartNodeModel_PortConnected;
PortDisconnected -= BasicLineChartNodeModel_PortDisconnected;
VMDataBridge.DataBridge.Instance.UnregisterCallback(GUID.ToString());
}
@@ -250,6 +308,9 @@ public class BasicLineChartNodeView : INodeViewCustomization
/// At run-time, this method is called during the node
@@ -259,6 +320,8 @@ public class BasicLineChartNodeView : INodeViewCustomizationThe NodeView representing the node in the graph.
public void CustomizeView(BasicLineChartNodeModel model, NodeView nodeView)
{
+ this.model = model;
+ this.view = nodeView;
basicLineChartControl = new BasicLineChartControl(model);
nodeView.inputGrid.Children.Add(basicLineChartControl);
@@ -268,6 +331,49 @@ public void CustomizeView(BasicLineChartNodeModel model, NodeView nodeView)
var contextMenu = (nodeView.Content as Grid).ContextMenu;
contextMenu.Items.Add(exportImage);
+
+ UpdateDefaultInPortValues();
+
+ model.PortUpdated += ModelOnPortUpdated;
+ }
+
+ private void ModelOnPortUpdated(object sender, EventArgs e)
+ {
+ UpdateDefaultInPortValues();
+ }
+
+ private void UpdateDefaultInPortValues()
+ {
+ if (!this.view.ViewModel.InPorts.Any()) return;
+ var inPorts = this.view.ViewModel.InPorts;
+
+ // Only apply default values if all ports are disconnected
+ if (!model.IsInErrorState &&
+ model.State != ElementState.Active &&
+ !inPorts[0].IsConnected &&
+ !inPorts[1].IsConnected)
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = true;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = false;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = false;
+ }
+
+ var allPortsConnected = inPorts[0].IsConnected && inPorts[1].IsConnected && model.State != ElementState.Warning;
+ var noPortsConnected = !inPorts[0].IsConnected && !inPorts[1].IsConnected;
+
+ // The color input uses default values if it's not connected
+ if (!inPorts[2].IsConnected && (allPortsConnected || noPortsConnected))
+ {
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = false;
+ }
}
private void ExportImage_Click(object sender, RoutedEventArgs e)
@@ -279,6 +385,9 @@ private void ExportImage_Click(object sender, RoutedEventArgs e)
/// Here you can do any cleanup you require if you've assigned callbacks for particular
/// UI events on your node.
///
- public void Dispose() { }
+ public void Dispose()
+ {
+ model.PortUpdated -= ModelOnPortUpdated;
+ }
}
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BarChartControl.xaml.cs b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BarChartControl.xaml.cs
index 0f794c11837..1f6a34936b0 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BarChartControl.xaml.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BarChartControl.xaml.cs
@@ -2,7 +2,9 @@
using LiveCharts.Wpf;
using SharpDX.Direct2D1;
using System;
+using System.Collections.Generic;
using System.ComponentModel;
+using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
@@ -21,6 +23,9 @@ public partial class BarChartControl : UserControl, INotifyPropertyChanged
private static double PADDING = 4.0;
private static double MAX_COLUMN_WIDTH = 20.0;
+ private double MIN_WIDTH = 300;
+ private double MIN_HEIGHT = 300;
+
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
@@ -41,52 +46,15 @@ public BarChartControl(BarChartNodeModel model)
private void BuildUI(BarChartNodeModel model)
{
-
if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected)
{
- BarChart.Series = new SeriesCollection
- {
- new ColumnSeries
- {
- Title = "2019",
- Values = new ChartValues { 5, 6, 7, 8 },
- ColumnPadding = PADDING,
- MaxColumnWidth = MAX_COLUMN_WIDTH,
- },
- new ColumnSeries
- {
- Title = "2020",
- Values = new ChartValues { 10, 12, 14, 16 },
- ColumnPadding = PADDING,
- MaxColumnWidth = MAX_COLUMN_WIDTH,
- },
- new ColumnSeries
- {
- Title = "2021",
- Values = new ChartValues { 15, 18, 21, 24 },
- ColumnPadding = PADDING,
- MaxColumnWidth = MAX_COLUMN_WIDTH,
- }
- };
+ DefaultSeries();
}
else if (model.InPorts[0].IsConnected && model.InPorts[1].IsConnected && model.InPorts[2].IsConnected)
{
if (model.Labels.Count == model.Values.Count && model.Labels.Count > 0)
{
- var seriesRange = new ColumnSeries[model.Labels.Count];
-
- for (var i = 0; i < model.Labels.Count; i++)
- {
- seriesRange[i] = new ColumnSeries
- {
- Title = model.Labels[i],
- Values = new ChartValues(model.Values[i]),
- Fill = model.Colors[i],
- Stroke = model.Colors[i],
- ColumnPadding = PADDING,
- MaxColumnWidth = MAX_COLUMN_WIDTH,
- };
- }
+ var seriesRange = UpdateSeries(model);
BarChart.Series.AddRange(seriesRange);
}
@@ -102,27 +70,81 @@ private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e
// Invoke on UI thread
this.Dispatcher.Invoke(() =>
{
- var seriesRange = new ColumnSeries[model.Labels.Count];
+ BarChart.Series.Clear();
- for (var i = 0; i < model.Labels.Count; i++)
+ // Load sample data if any ports are not connected
+ if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected)
{
- seriesRange[i] = new ColumnSeries
- {
- Title = model.Labels[i],
- Values = new ChartValues(model.Values[i]),
- Fill = model.Colors[i],
- Stroke = model.Colors[i],
- ColumnPadding = PADDING,
- MaxColumnWidth = MAX_COLUMN_WIDTH,
- };
+ DefaultSeries();
}
+ else
+ {
+ var seriesRange = UpdateSeries(model);
- BarChart.Series.Clear();
- BarChart.Series.AddRange(seriesRange);
+ BarChart.Series.AddRange(seriesRange.ToArray());
+ }
});
}
}
+ private void DefaultSeries()
+ {
+ BarChart.Series = new SeriesCollection
+ {
+ new ColumnSeries
+ {
+ Title = "2019",
+ Values = new ChartValues { 5, 6, 7, 8 },
+ ColumnPadding = PADDING,
+ MaxColumnWidth = MAX_COLUMN_WIDTH,
+ },
+ new ColumnSeries
+ {
+ Title = "2020",
+ Values = new ChartValues { 10, 12, 14, 16 },
+ ColumnPadding = PADDING,
+ MaxColumnWidth = MAX_COLUMN_WIDTH,
+ },
+ new ColumnSeries
+ {
+ Title = "2021",
+ Values = new ChartValues { 15, 18, 21, 24 },
+ ColumnPadding = PADDING,
+ MaxColumnWidth = MAX_COLUMN_WIDTH,
+ }
+ };
+ }
+
+ private List UpdateSeries(BarChartNodeModel model)
+ {
+ var seriesRange = new List();
+
+ if (model == null)
+ {
+ model = this.model;
+ }
+
+ if (model.Labels != null && model.Labels.Any()
+ && model.Values != null && model.Values.Any()
+ && model.Colors != null && model.Colors.Any())
+ {
+ for (var i = 0; i < model.Labels.Count; i++)
+ {
+ seriesRange.Add(new ColumnSeries
+ {
+ Title = model.Labels[i],
+ Values = new ChartValues(model.Values[i]),
+ Fill = model.Colors[i],
+ Stroke = model.Colors[i],
+ ColumnPadding = PADDING,
+ MaxColumnWidth = MAX_COLUMN_WIDTH,
+ });
+ }
+ }
+
+ return seriesRange;
+ }
+
private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArgs e)
{
var yAdjust = ActualHeight + e.VerticalChange;
@@ -132,12 +154,12 @@ private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArg
{
var inputGrid = this.Parent as Grid;
- if (xAdjust >= inputGrid.MinWidth)
+ if (xAdjust >= inputGrid.MinWidth && xAdjust >= MIN_WIDTH)
{
Width = xAdjust;
}
- if (yAdjust >= inputGrid.MinHeight)
+ if (yAdjust >= inputGrid.MinHeight && xAdjust >= MIN_HEIGHT)
{
Height = yAdjust;
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BasicLineChartControl.xaml.cs b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BasicLineChartControl.xaml.cs
index ccea492333b..f04ed5c943b 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BasicLineChartControl.xaml.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/BasicLineChartControl.xaml.cs
@@ -6,6 +6,8 @@
using LiveCharts.Wpf;
using System.ComponentModel;
using System.Windows;
+using System.Collections.Generic;
+using System.Linq;
namespace CoreNodeModelsWpf.Charts
{
@@ -17,6 +19,9 @@ public partial class BasicLineChartControl : UserControl, INotifyPropertyChanged
private Random rnd = new Random();
private readonly BasicLineChartNodeModel model;
+ private double MIN_WIDTH = 300;
+ private double MIN_HEIGHT = 300;
+
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
@@ -42,12 +47,7 @@ private void BuildUI(BasicLineChartNodeModel model)
// Load sample data if any ports are not connected
if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected)
{
- var seriesRange = new LineSeries[]
- {
- new LineSeries { Title = "Series 1", Values = new ChartValues { 4, 6, 5, 2, 4 } },
- new LineSeries { Title = "Series 2", Values = new ChartValues { 6, 7, 3, 4, 6 } },
- new LineSeries { Title = "Series 3", Values = new ChartValues { 4, 2, 7, 2, 7 } }
- };
+ var seriesRange = DefaultSeries();
BasicLineChart.Series.AddRange(seriesRange);
}
@@ -55,19 +55,7 @@ private void BuildUI(BasicLineChartNodeModel model)
{
if (model.Labels.Count == model.Values.Count && model.Labels.Count > 0)
{
- LineSeries[] seriesRange = new LineSeries[model.Labels.Count];
-
- for (var i = 0; i < model.Labels.Count; i++)
- {
- seriesRange[i] = new LineSeries
- {
- Title = model.Labels[i],
- Values = new ChartValues(model.Values[i]),
- Stroke = model.Colors[i],
- StrokeThickness = 2.0,
- //Fill = Brushes.Transparent
- };
- }
+ var seriesRange = UpdateSeries(model);
BasicLineChart.Series.AddRange(seriesRange);
}
@@ -76,34 +64,73 @@ private void BuildUI(BasicLineChartNodeModel model)
private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
- if(e.PropertyName == "DataUpdated")
+ if (e.PropertyName == "DataUpdated")
{
var model = sender as BasicLineChartNodeModel;
// Invoke on UI thread
this.Dispatcher.Invoke(() =>
{
- LineSeries[] seriesRange = new LineSeries[model.Labels.Count];
+ BasicLineChart.Series.Clear();
- for (var i = 0; i < model.Labels.Count; i++)
+ if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected)
{
- seriesRange[i] = new LineSeries
- {
- Title = model.Labels[i],
- Values = new ChartValues(model.Values[i]),
- Stroke = model.Colors[i],
- StrokeThickness = 2.0,
- //Fill = Brushes.Transparent,
- //PointGeometrySize = 0
- };
+ var seriesRange = DefaultSeries();
+
+ BasicLineChart.Series.AddRange(seriesRange);
}
+ else
+ {
+ var seriesRange = UpdateSeries(model);
- BasicLineChart.Series.Clear();
- BasicLineChart.Series.AddRange(seriesRange);
+ BasicLineChart.Series.AddRange(seriesRange);
+ }
});
}
}
+
+ private LineSeries[] DefaultSeries()
+ {
+ var series = new LineSeries[]
+ {
+ new LineSeries { Title = "Series 1", Values = new ChartValues { 4, 6, 5, 2, 4 } },
+ new LineSeries { Title = "Series 2", Values = new ChartValues { 6, 7, 3, 4, 6 } },
+ new LineSeries { Title = "Series 3", Values = new ChartValues { 4, 2, 7, 2, 7 } }
+ };
+
+ return series;
+ }
+
+ private List UpdateSeries(BasicLineChartNodeModel model)
+ {
+ var seriesRange = new List();
+
+ if (model == null)
+ {
+ model = this.model;
+ }
+
+ if (model.Labels != null && model.Labels.Any()
+ && model.Values != null && model.Values.Any()
+ && model.Colors != null && model.Colors.Any())
+ {
+ for (var i = 0; i < model.Labels.Count; i++)
+ {
+ seriesRange.Add(new LineSeries
+ {
+ Title = model.Labels[i],
+ Values = new ChartValues(model.Values[i]),
+ Stroke = model.Colors[i],
+ StrokeThickness = 2.0,
+ });
+ }
+
+ }
+
+ return seriesRange;
+ }
+
private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArgs e)
{
var yAdjust = ActualHeight + e.VerticalChange;
@@ -113,12 +140,12 @@ private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArg
{
var inputGrid = this.Parent as Grid;
- if (xAdjust >= inputGrid.MinWidth)
+ if (xAdjust >= inputGrid.MinWidth && xAdjust >= MIN_WIDTH)
{
Width = xAdjust;
}
- if (yAdjust >= inputGrid.MinHeight)
+ if (yAdjust >= inputGrid.MinHeight && xAdjust >= MIN_HEIGHT)
{
Height = yAdjust;
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/HeatSeriesControl.xaml.cs b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/HeatSeriesControl.xaml.cs
index c4a269832fb..ab6562a8f35 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/HeatSeriesControl.xaml.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/HeatSeriesControl.xaml.cs
@@ -7,6 +7,7 @@
using LiveCharts.Wpf;
using System.ComponentModel;
using System.Windows;
+using System.Linq;
namespace CoreNodeModelsWpf.Charts.Controls
{
@@ -18,6 +19,9 @@ public partial class HeatSeriesControl : UserControl, INotifyPropertyChanged
private Random rnd = new Random();
private readonly HeatSeriesNodeModel model;
+ private double MIN_WIDTH = 300;
+ private double MIN_HEIGHT = 300;
+
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
@@ -43,9 +47,55 @@ private void BuildUI(HeatSeriesNodeModel model)
// Load sample data if any ports are not connected
if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected && !model.InPorts[3].IsConnected)
{
- // X - Products
- var XLabels = new[]
+ var chartValues = DefaultValues();
+
+ HeatSeriesUI.Series.Add(new HeatSeries()
+ {
+ Values = chartValues,
+ DrawsHeatRange = false,
+ });
+ }
+ // Else load input data
+ else if (model.InPorts[0].IsConnected && model.InPorts[1].IsConnected && model.InPorts[2].IsConnected && model.InPorts[3].IsConnected)
+ {
+ if (model.XLabels.Count == model.Values.Count && model.XLabels.Count > 0)
{
+ UpdateValues(model);
+ }
+ }
+ }
+ private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "DataUpdated")
+ {
+ var model = sender as HeatSeriesNodeModel;
+
+ // Invoke on UI thread
+ this.Dispatcher.Invoke(() =>
+ {
+ if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected && !model.InPorts[3].IsConnected)
+ {
+ var chartValues = DefaultValues();
+
+ HeatSeriesUI.Series.Add(new HeatSeries()
+ {
+ Values = chartValues,
+ DrawsHeatRange = false,
+ });
+ }
+ else
+ {
+ UpdateValues(model);
+ }
+ });
+ }
+ }
+
+ private ChartValues DefaultValues()
+ {
+ // X - Products
+ var XLabels = new[]
+ {
"Item-1",
"Item-2",
"Item-3",
@@ -53,9 +103,9 @@ private void BuildUI(HeatSeriesNodeModel model)
"Item-5"
};
- // Y - Day of the week
- var YLabels = new[]
- {
+ // Y - Day of the week
+ var YLabels = new[]
+ {
"Monday",
"Tuesday",
"Wednesday",
@@ -65,94 +115,61 @@ private void BuildUI(HeatSeriesNodeModel model)
"Sunday"
};
- // Value for each product on every day of the week
- var chartValues = new ChartValues();
+ // Value for each product on every day of the week
+ var chartValues = new ChartValues();
- for(var i = 0; i < XLabels.Length; i++)
+ for (var i = 0; i < XLabels.Length; i++)
+ {
+ for (var j = 0; j < YLabels.Length; j++)
{
- for ( var j = 0; j < YLabels.Length; j++)
- {
- chartValues.Add(new HeatPoint(i, j, rnd.Next(0, 10)));
- }
+ chartValues.Add(new HeatPoint(i, j, rnd.Next(0, 10)));
}
-
- XAxis.Labels = XLabels;
- YAxis.Labels = YLabels;
- HeatSeriesUI.Series.Add(new HeatSeries()
- {
- Values = chartValues,
- DrawsHeatRange = false,
- });
}
- // Else load input data
- else if (model.InPorts[0].IsConnected && model.InPorts[1].IsConnected && model.InPorts[2].IsConnected && model.InPorts[3].IsConnected)
- {
- if (model.XLabels.Count == model.Values.Count && model.XLabels.Count > 0)
- {
- var chartValues = new ChartValues();
-
- for (var i = 0; i < model.XLabels.Count; i++)
- {
- for (var j = 0; j < model.YLabels.Count; j++)
- {
- chartValues.Add(new HeatPoint(i, j, model.Values[i][j]));
- }
- }
- var colors = BuildColors(model);
- var hoverIconColor = new SolidColorBrush(Color.FromArgb(255, 94, 92, 90));
+ XAxis.Labels = XLabels;
+ YAxis.Labels = YLabels;
- XAxis.Labels = model.XLabels;
- YAxis.Labels = model.YLabels;
- HeatSeriesUI.Series.Add(new HeatSeries()
- {
- Values = chartValues,
- DrawsHeatRange = false,
- GradientStopCollection = colors,
- //Fill = hoverIconColor,
- PointGeometry = DefaultGeometries.Square
- //DataLabels = true
- });
- }
- }
+ return chartValues;
}
- private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ private void UpdateValues(HeatSeriesNodeModel model)
{
- if (e.PropertyName == "DataUpdated")
+ var chartValues = new ChartValues();
+ HeatSeriesUI.Series.Clear();
+
+ if (model == null)
{
- var model = sender as HeatSeriesNodeModel;
+ model = this.model;
+ }
- // Invoke on UI thread
- this.Dispatcher.Invoke(() =>
- {
- var chartValues = new ChartValues();
+ var colors = new GradientStopCollection();
- for (var i = 0; i < model.XLabels.Count; i++)
+ if (model.XLabels != null && model.XLabels.Any()
+ && model.YLabels != null && model.YLabels.Any()
+ && model.Values != null && model.Values.Any()
+ && model.Colors != null && model.Colors.Any())
+ {
+ for (var i = 0; i < model.XLabels.Count; i++)
+ {
+ for (var j = 0; j < model.YLabels.Count; j++)
{
- for (var j = 0; j < model.YLabels.Count; j++)
- {
- chartValues.Add(new HeatPoint(i, j, model.Values[i][j]));
- }
+ chartValues.Add(new HeatPoint(i, j, model.Values[i][j]));
}
+ }
- var colors = BuildColors(model);
- var hoverIconColor = new SolidColorBrush(Color.FromArgb(255, 94, 92, 90));
+ colors = BuildColors(model);
- HeatSeriesUI.Series.Clear();
- XAxis.Labels = model.XLabels;
- YAxis.Labels = model.YLabels;
- HeatSeriesUI.Series.Add(new HeatSeries()
- {
- Values = chartValues,
- DrawsHeatRange = false,
- GradientStopCollection = colors,
- //Fill = hoverIconColor,
- PointGeometry = DefaultGeometries.Square
- //DataLabels = true
- });
- });
+ XAxis.Labels = model.XLabels;
+ YAxis.Labels = model.YLabels;
}
+
+ HeatSeriesUI.Series.Add(new HeatSeries()
+ {
+ Values = chartValues,
+ DrawsHeatRange = false,
+ GradientStopCollection = colors,
+ PointGeometry = DefaultGeometries.Square
+ });
}
private GradientStopCollection BuildColors(HeatSeriesNodeModel model)
@@ -202,12 +219,12 @@ private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArg
{
var inputGrid = this.Parent as Grid;
- if (xAdjust >= inputGrid.MinWidth)
+ if (xAdjust >= inputGrid.MinWidth && xAdjust >= MIN_WIDTH)
{
Width = xAdjust;
}
- if (yAdjust >= inputGrid.MinHeight)
+ if (yAdjust >= inputGrid.MinHeight && yAdjust >= MIN_HEIGHT)
{
Height = yAdjust;
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/PieChartControl.xaml.cs b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/PieChartControl.xaml.cs
index 498490c6bba..3adcc8470e4 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/PieChartControl.xaml.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/PieChartControl.xaml.cs
@@ -5,6 +5,9 @@
using LiveCharts.Wpf;
using System.ComponentModel;
using System.Windows;
+using System.Web.ModelBinding;
+using System.Collections.Generic;
+using System.Linq;
namespace CoreNodeModelsWpf.Charts.Controls
{
@@ -17,6 +20,9 @@ public partial class PieChartControl : UserControl, INotifyPropertyChanged
private Random rnd = new Random();
private readonly PieChartNodeModel model;
+ private double MIN_WIDTH = 300;
+ private double MIN_HEIGHT = 300;
+
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
@@ -41,12 +47,7 @@ private void BuildUI(PieChartNodeModel model)
{
if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected)
{
- var seriesRange = new PieSeries[]
- {
- new PieSeries { Title = "Item1", Values = new ChartValues { 100.0 }, DataLabels = true/*, LabelPoint = PointLabel*/ },
- new PieSeries { Title = "Item2", Values = new ChartValues { 100.0 }, DataLabels = true/*, LabelPoint = PointLabel*/ },
- new PieSeries { Title = "Item3", Values = new ChartValues { 100.0 }, DataLabels = true/*, LabelPoint = PointLabel*/ }
- };
+ var seriesRange = DefaultSeries();
PieChart.Series.AddRange(seriesRange);
}
@@ -55,19 +56,7 @@ private void BuildUI(PieChartNodeModel model)
{
if (model.Labels.Count == model.Values.Count && model.Labels.Count > 0)
{
- var seriesRange = new PieSeries[model.Labels.Count];
-
- for (var i = 0; i < model.Labels.Count; i++)
- {
- seriesRange[i] = new PieSeries
- {
- Title = model.Labels[i],
- Values = new ChartValues { model.Values[i] },
- Fill = model.Colors[i],
- DataLabels = true,
- //LabelPoint = PointLabel
- };
- }
+ var seriesRange = UpdateSeries(model);
PieChart.Series.AddRange(seriesRange);
}
@@ -83,27 +72,65 @@ private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e
// Invoke on UI thread
this.Dispatcher.Invoke(() =>
{
- var seriesRange = new PieSeries[nodeModel.Labels.Count];
+ PieChart.Series.Clear();
- for (var i = 0; i < nodeModel.Labels.Count; i++)
+ if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected)
{
- seriesRange[i] = new PieSeries
- {
- Title = nodeModel.Labels[i],
- Fill = nodeModel.Colors[i],
- //StrokeThickness = 0,
- Values = new ChartValues { nodeModel.Values[i] },
- DataLabels = true,
- //LabelPoint = PointLabel
- };
+ var seriesRange = DefaultSeries();
+
+ PieChart.Series.AddRange(seriesRange);
}
+ else
+ {
+ var seriesRange = UpdateSeries(model);
- PieChart.Series.Clear();
- PieChart.Series.AddRange(seriesRange);
+ PieChart.Series.AddRange(seriesRange);
+ }
});
}
}
+ private PieSeries[] DefaultSeries()
+ {
+ var series = new PieSeries[]
+ {
+ new PieSeries { Title = "Item1", Values = new ChartValues { 100.0 }, DataLabels = true/*, LabelPoint = PointLabel*/ },
+ new PieSeries { Title = "Item2", Values = new ChartValues { 100.0 }, DataLabels = true/*, LabelPoint = PointLabel*/ },
+ new PieSeries { Title = "Item3", Values = new ChartValues { 100.0 }, DataLabels = true/*, LabelPoint = PointLabel*/ },
+ };
+
+ return series;
+ }
+
+ private List UpdateSeries(PieChartNodeModel model)
+ {
+ var seriesRange = new List();
+
+ if (model == null)
+ {
+ model = this.model;
+ }
+
+ if (model.Labels != null && model.Labels.Any()
+ && model.Values != null && model.Values.Any()
+ && model.Colors != null && model.Colors.Any())
+ {
+ for (var i = 0; i < model.Labels.Count; i++)
+ {
+ seriesRange.Add(new PieSeries
+ {
+ Title = model.Labels[i],
+ Values = new ChartValues { model.Values[i] },
+ Fill = model.Colors[i],
+ DataLabels = true,
+ //LabelPoint = PointLabel
+ });
+ }
+ }
+
+ return seriesRange;
+ }
+
private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArgs e)
{
@@ -114,13 +141,13 @@ private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArg
{
var inputGrid = this.Parent as Grid;
- if (xAdjust >= inputGrid.MinWidth)
+ if (xAdjust >= inputGrid.MinWidth && xAdjust >= MIN_WIDTH)
{
Width = xAdjust;
Height = xAdjust;
}
- if (yAdjust >= inputGrid.MinHeight)
+ if (yAdjust >= inputGrid.MinHeight && xAdjust >= MIN_HEIGHT)
{
Width = yAdjust;
Height = yAdjust;
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/ScatterPlotControl.xaml.cs b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/ScatterPlotControl.xaml.cs
index a95a68b620a..ce4484e184f 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/ScatterPlotControl.xaml.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/ScatterPlotControl.xaml.cs
@@ -8,6 +8,7 @@
using LiveCharts.Wpf;
using System.ComponentModel;
using System.Windows;
+using System.Linq;
namespace CoreNodeModelsWpf.Charts.Controls
{
@@ -19,6 +20,9 @@ public partial class ScatterPlotControl : UserControl, INotifyPropertyChanged
private Random rnd = new Random();
private readonly ScatterPlotNodeModel model;
+ private double MIN_WIDTH = 300;
+ private double MIN_HEIGHT = 300;
+
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
@@ -44,56 +48,15 @@ private void BuildUI(ScatterPlotNodeModel model)
// Load sample data if any ports are not connected
if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected && !model.InPorts[3].IsConnected)
{
- var ValuesA = new ChartValues();
- var ValuesB = new ChartValues();
- var ValuesC = new ChartValues();
-
- for (var i = 0; i < 20; i++)
- {
- ValuesA.Add(new ObservablePoint(rnd.NextDouble() * 10, rnd.NextDouble() * 10));
- ValuesB.Add(new ObservablePoint(rnd.NextDouble() * 10, rnd.NextDouble() * 10));
- ValuesC.Add(new ObservablePoint(rnd.NextDouble() * 10, rnd.NextDouble() * 10));
- }
-
- var plot1 = new ScatterSeries { Title = "Plot 1", Values = ValuesA };
- var plot2 = new ScatterSeries { Title = "Plot 2", Values = ValuesB };
- var plot3 = new ScatterSeries { Title = "Plot 3", Values = ValuesC };
-
- var plots = new ScatterSeries[] { plot1, plot2, plot3 };
-
+ var plots = DefaultSeries();
ScatterPlot.Series.AddRange(plots);
}
// Else load input data
- else if (model.InPorts[0].IsConnected && model.InPorts[1].IsConnected && model.InPorts[2].IsConnected && model.InPorts[3].IsConnected)
+ else if (model.InPorts[0].IsConnected && model.InPorts[1].IsConnected && model.InPorts[2].IsConnected)
{
if (model.Labels.Count == model.XValues.Count && model.XValues.Count == model.YValues.Count && model.Labels.Count > 0)
{
- var plots = new List();
-
- // For each set of points
- for (var i = 0; i < model.Labels.Count; i++)
- {
-
- ChartValues points = new ChartValues();
-
- // For each x-value list
- for (int j = 0; j < model.XValues[i].Count; j++)
- {
- points.Add(new ObservablePoint
- {
- X = model.XValues[i][j],
- Y = model.YValues[i][j]
- });
- }
-
- plots.Add(new ScatterSeries
- {
- Title = model.Labels[i],
- Values = points,
- Fill = model.Colors[i]
- });
- }
-
+ var plots = UpdateSeries();
ScatterPlot.Series.AddRange(plots);
}
}
@@ -110,35 +73,82 @@ private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e
{
ScatterPlot.Series.Clear();
- var plots = new List();
-
- // For each set of points
- for (var i = 0; i < model.Labels.Count; i++)
+ // Load sample data if any ports are not connected
+ if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected && !model.InPorts[3].IsConnected)
{
+ var plots = DefaultSeries();
+ ScatterPlot.Series.AddRange(plots);
+ }
+ else
+ {
+ var plots = UpdateSeries(model);
+ ScatterPlot.Series.AddRange(plots);
+ }
+ });
+ }
+ }
- ChartValues points = new ChartValues();
+ private ScatterSeries [] DefaultSeries()
+ {
+ var ValuesA = new ChartValues();
+ var ValuesB = new ChartValues();
+ var ValuesC = new ChartValues();
- // For each x-value list
- for (int j = 0; j < model.XValues[i].Count; j++)
- {
- points.Add(new ObservablePoint
- {
- X = model.XValues[i][j],
- Y = model.YValues[i][j]
- });
- }
-
- plots.Add(new ScatterSeries
+ for (var i = 0; i < 20; i++)
+ {
+ ValuesA.Add(new ObservablePoint(rnd.NextDouble() * 10, rnd.NextDouble() * 10));
+ ValuesB.Add(new ObservablePoint(rnd.NextDouble() * 10, rnd.NextDouble() * 10));
+ ValuesC.Add(new ObservablePoint(rnd.NextDouble() * 10, rnd.NextDouble() * 10));
+ }
+
+ var plot1 = new ScatterSeries { Title = "Plot 1", Values = ValuesA };
+ var plot2 = new ScatterSeries { Title = "Plot 2", Values = ValuesB };
+ var plot3 = new ScatterSeries { Title = "Plot 3", Values = ValuesC };
+
+ var plots = new ScatterSeries[] { plot1, plot2, plot3 };
+
+ return plots;
+ }
+
+ private List UpdateSeries(ScatterPlotNodeModel model = null)
+ {
+ var plots = new List();
+
+ if(model == null)
+ {
+ model = this.model;
+ }
+
+ if (model.Labels != null && model.Labels.Any()
+ && model.XValues != null && model.XValues.Any()
+ && model.YValues != null && model.YValues.Any()
+ && model.Colors != null && model.Colors.Any())
+ {
+ // For each set of points
+ for (var i = 0; i < model.Labels.Count; i++)
+ {
+ ChartValues points = new ChartValues();
+
+ // For each x-value list
+ for (int j = 0; j < model.XValues[i].Count; j++)
+ {
+ points.Add(new ObservablePoint
{
- Title = model.Labels[i],
- Values = points,
- Fill = model.Colors[i]
+ X = model.XValues[i][j],
+ Y = model.YValues[i][j]
});
}
- ScatterPlot.Series.AddRange(plots);
- });
+ plots.Add(new ScatterSeries
+ {
+ Title = model.Labels[i],
+ Values = points,
+ Fill = model.Colors[i]
+ });
+ }
}
+
+ return plots;
}
private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArgs e)
@@ -150,12 +160,12 @@ private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArg
{
var inputGrid = this.Parent as Grid;
- if (xAdjust >= 100/*inputGrid.MinWidth*/)
+ if (xAdjust >= MIN_WIDTH/*inputGrid.MinWidth*/ )
{
Width = xAdjust;
}
- if (yAdjust >= 100/*inputGrid.MinHeight*/)
+ if (yAdjust >= MIN_HEIGHT/*inputGrid.MinHeight*/)
{
Height = yAdjust;
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/XYLineChartControl.xaml.cs b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/XYLineChartControl.xaml.cs
index 3c6aa3e4c0e..ac5220eb17d 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/Controls/XYLineChartControl.xaml.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/Controls/XYLineChartControl.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
@@ -7,6 +8,7 @@
using LiveCharts.Wpf;
using System.ComponentModel;
using System.Windows;
+using System.Linq;
namespace CoreNodeModelsWpf.Charts.Controls
{
@@ -18,6 +20,9 @@ public partial class XYLineChartControl : UserControl, INotifyPropertyChanged
private Random rnd = new Random();
private readonly XYLineChartNodeModel model;
+ private double MIN_WIDTH = 300;
+ private double MIN_HEIGHT = 300;
+
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
@@ -43,73 +48,16 @@ private void BuildUI(XYLineChartNodeModel model)
// Load sample data if any ports are not connected
if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected && !model.InPorts[3].IsConnected)
{
- var defaultXValues = new double[][]
- {
- new double[]{ 0, 1, 2, 3 },
- new double[]{ 0, 1, 2, 3 },
- new double[]{ 0, 1, 2, 3 }
- };
-
- var defaultYValues = new double[][]
- {
- new double[]{ 0, 1, 2, 3 },
- new double[]{ 1, 2, 3, 4 },
- new double[]{ 2, 3, 4, 5 }
- };
-
- LineSeries[] seriesRange = new LineSeries[defaultXValues.Length];
-
- for (var i = 0; i < defaultXValues.Length; i++)
- {
- ChartValues points = new ChartValues();
-
- for (int j = 0; j < defaultXValues[i].Length; j++)
- {
- points.Add(new ObservablePoint
- {
- X = defaultXValues[i][j],
- Y = defaultYValues[i][j]
- });
- }
-
- seriesRange[i] = new LineSeries
- {
- Values = points,
- Fill = Brushes.Transparent
- };
- }
+ var seriesRange = DefaultSeries();
XYLineChart.Series.AddRange(seriesRange);
}
// Else load input data
- else if (model.InPorts[0].IsConnected && model.InPorts[1].IsConnected && model.InPorts[2].IsConnected && model.InPorts[3].IsConnected)
+ else if (model.InPorts[0].IsConnected && model.InPorts[1].IsConnected && model.InPorts[2].IsConnected)
{
if (model.Labels.Count == model.XValues.Count && model.XValues.Count == model.YValues.Count && model.Labels.Count > 0)
{
- LineSeries[] seriesRange = new LineSeries[model.Labels.Count];
-
- for (var i = 0; i < model.Labels.Count; i++)
- {
- ChartValues points = new ChartValues();
-
- for (int j = 0; j < model.XValues[i].Count; j++)
- {
- points.Add(new ObservablePoint
- {
- X = model.XValues[i][j],
- Y = model.YValues[i][j]
- });
- }
-
- seriesRange[i] = new LineSeries
- {
- Title = model.Labels[i],
- Values = points,
- Stroke = model.Colors[i],
- StrokeThickness = 2.0,
- Fill = Brushes.Transparent,
- };
- }
+ var seriesRange = UpdateSeries();
XYLineChart.Series.AddRange(seriesRange);
}
@@ -125,36 +73,102 @@ private void NodeModel_PropertyChanged(object sender, PropertyChangedEventArgs e
// Invoke on UI thread
this.Dispatcher.Invoke(() =>
{
- LineSeries[] seriesRange = new LineSeries[model.Labels.Count];
+ XYLineChart.Series.Clear();
- for (var i = 0; i < model.Labels.Count; i++)
+ if (!model.InPorts[0].IsConnected && !model.InPorts[1].IsConnected && !model.InPorts[2].IsConnected && !model.InPorts[3].IsConnected)
{
- ChartValues points = new ChartValues();
+ var seriesRange = DefaultSeries();
+ XYLineChart.Series.AddRange(seriesRange);
+ }
+ else
+ {
+ var seriesRange = UpdateSeries(model);
+ XYLineChart.Series.AddRange(seriesRange);
- for (int j = 0; j < model.XValues[i].Count; j++)
- {
- points.Add(new ObservablePoint
- {
- X = model.XValues[i][j],
- Y = model.YValues[i][j]
- });
- }
-
- seriesRange[i] = new LineSeries
+ }
+ });
+ }
+ }
+
+ private LineSeries[] DefaultSeries()
+ {
+ var defaultXValues = new double[][]
+ {
+ new double[]{ 0, 1, 2, 3 },
+ new double[]{ 0, 1, 2, 3 },
+ new double[]{ 0, 1, 2, 3 }
+ };
+
+ var defaultYValues = new double[][]
+ {
+ new double[]{ 0, 1, 2, 3 },
+ new double[]{ 1, 2, 3, 4 },
+ new double[]{ 2, 3, 4, 5 }
+ };
+ List labels = new List { "Plot 1", "Plot 2", "Plot 3" };
+ LineSeries[] seriesRange = new LineSeries[defaultXValues.Length];
+
+ for (var i = 0; i < defaultXValues.Length; i++)
+ {
+ ChartValues points = new ChartValues();
+
+ for (int j = 0; j < defaultXValues[i].Length; j++)
+ {
+ points.Add(new ObservablePoint
+ {
+ X = defaultXValues[i][j],
+ Y = defaultYValues[i][j]
+ });
+ }
+
+ seriesRange[i] = new LineSeries
+ {
+ Title = labels[i],
+ Values = points,
+ Fill = Brushes.Transparent
+ };
+ }
+
+ return seriesRange;
+ }
+
+ private List UpdateSeries(XYLineChartNodeModel model = null)
+ {
+ var seriesRange = new List();
+ if(model == null)
+ {
+ model = this.model;
+ }
+ if(model.Labels != null && model.Labels.Any()
+ && model.XValues != null && model.XValues.Any()
+ && model.YValues != null && model.YValues.Any()
+ && model.Colors != null && model.Colors.Any())
+ {
+ for (var i = 0; i < model.Labels.Count; i++)
+ {
+ ChartValues points = new ChartValues();
+
+ for (int j = 0; j < model.XValues[i].Count; j++)
+ {
+ points.Add(new ObservablePoint
{
- Title = model.Labels[i],
- Values = points,
- Stroke = model.Colors[i],
- StrokeThickness = 2.0,
- Fill = Brushes.Transparent
- //PointGeometrySize = 0
- };
+ X = model.XValues[i][j],
+ Y = model.YValues[i][j]
+ });
}
- XYLineChart.Series.Clear();
- XYLineChart.Series.AddRange(seriesRange);
- });
+ seriesRange.Add(new LineSeries
+ {
+ Title = model.Labels[i],
+ Values = points,
+ Stroke = model.Colors[i],
+ StrokeThickness = 2.0,
+ Fill = Brushes.Transparent
+ });
+ }
}
+
+ return seriesRange;
}
private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArgs e)
@@ -166,12 +180,12 @@ private void ThumbResizeThumbOnDragDeltaHandler(object sender, DragDeltaEventArg
{
var inputGrid = this.Parent as Grid;
- if (xAdjust >= inputGrid.MinWidth)
+ if (xAdjust >= inputGrid.MinWidth && xAdjust >= MIN_WIDTH)
{
Width = xAdjust;
}
- if (yAdjust >= inputGrid.MinHeight)
+ if (yAdjust >= inputGrid.MinHeight && xAdjust >= MIN_HEIGHT)
{
Height = yAdjust;
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/HeatSeriesNodeModel.cs b/src/Libraries/CoreNodeModelsWpf/Charts/HeatSeriesNodeModel.cs
index ece3b24c7c7..0b31dba4417 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/HeatSeriesNodeModel.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/HeatSeriesNodeModel.cs
@@ -18,6 +18,9 @@
using ProtoCore.AST.AssociativeAST;
using DynamoServices;
using Dynamo.Wpf.Properties;
+using Dynamo.Graph.Connectors;
+using Newtonsoft.Json.Linq;
+using Dynamo.ViewModels;
namespace CoreNodeModelsWpf.Charts
{
@@ -26,9 +29,17 @@ namespace CoreNodeModelsWpf.Charts
[NodeCategory("Display.Charts.Create")]
[NodeDescription("ChartsHeatSeriesDescription", typeof(CoreNodeModelWpfResources))]
[NodeSearchTags("ChartsHeatSeriesSearchTags", typeof(CoreNodeModelWpfResources))]
-
+ [InPortNames("x-labels", "y-labels", "values", "colors")]
[InPortTypes("List", "List", "List>", "List")]
- [OutPortTypes("object[]")]
+ [InPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsHeatSeriesXLabelsDataPortToolTip",
+ "ChartsHeatSeriesYLabelsDataPortToolTip",
+ "ChartsHeatSeriesValuesDataPortToolTip",
+ "ChartsHeatSeriesColorsDataPortToolTip")]
+ [OutPortNames("labels:values")]
+ [OutPortTypes("Dictionary>")]
+ [OutPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsHeatSeriesLabelsValuesDataPortToolTip")]
[AlsoKnownAs("CoreNodeModelsWpf.Charts.HeatSeriesPlot")]
public class HeatSeriesNodeModel : NodeModel
{
@@ -54,6 +65,16 @@ public class HeatSeriesNodeModel : NodeModel
/// A list of color values, one for each plotted line.
///
public List Colors { get; set; }
+
+ ///
+ /// Triggers when port is connected or disconnected
+ ///
+ public event EventHandler PortUpdated;
+
+ protected virtual void OnPortUpdated(EventArgs args)
+ {
+ PortUpdated?.Invoke(this, args);
+ }
#endregion
#region Constructors
@@ -62,16 +83,11 @@ public class HeatSeriesNodeModel : NodeModel
///
public HeatSeriesNodeModel()
{
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("x-labels", "A list of string labels for the x-axis.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("y-labels", "A list of string labels for the y-axis.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("values", "A list of lists each containing double values representing items in a column.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("colors", "A list of colors used to generate a color range.")));
-
- OutPorts.Add(new PortModel(PortType.Output, this, new PortData("labels:values", "Dictionary containing label:value key-pairs")));
-
RegisterAllPorts();
- PortDisconnected += XYLineChartNodeModel_PortDisconnected;
+
+ PortConnected += HeatSeriesNodeModel_PortConnected;
+ PortDisconnected += HeatSeriesNodeModel_PortDisconnected;
ArgumentLacing = LacingStrategy.Disabled;
}
@@ -82,24 +98,39 @@ public HeatSeriesNodeModel()
///
public HeatSeriesNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
- PortDisconnected += XYLineChartNodeModel_PortDisconnected;
+ PortConnected += HeatSeriesNodeModel_PortConnected;
+ PortDisconnected += HeatSeriesNodeModel_PortDisconnected;
}
#endregion
#region Events
- private void XYLineChartNodeModel_PortDisconnected(PortModel port)
+ private void HeatSeriesNodeModel_PortDisconnected(PortModel port)
{
+ OnPortUpdated(null);
// Clear UI when a input port is disconnected
- if (port.PortType == PortType.Input && this.State == ElementState.Active)
+ if (port.PortType == PortType.Input)
{
- XLabels.Clear();
- YLabels.Clear();
- Values.Clear();
- Colors.Clear();
+ XLabels?.Clear();
+ YLabels?.Clear();
+ Values?.Clear();
+ Colors?.Clear();
RaisePropertyChanged("DataUpdated");
}
}
+
+
+ private void HeatSeriesNodeModel_PortConnected(PortModel port, ConnectorModel arg2)
+ {
+ // Reset an info states if any
+ if (port.PortType == PortType.Input && InPorts[3].IsConnected && NodeInfos.Any(x => x.State.Equals(ElementState.Info)))
+ {
+ this.ClearInfoMessages();
+ }
+
+ OnPortUpdated(null);
+ RaisePropertyChanged("DataUpdated");
+ }
#endregion
#region Databridge
@@ -124,6 +155,9 @@ protected override void OnBuilt()
/// The data passed through the data bridge.
private void DataBridgeCallback(object data)
{
+ // Reset an info states if any
+ if (NodeInfos.Count > 0) this.ClearInfoMessages();
+
// Grab input data which always returned as an ArrayList
var inputs = data as ArrayList;
@@ -133,11 +167,9 @@ private void DataBridgeCallback(object data)
var values = inputs[2] as ArrayList;
var colors = inputs[3] as ArrayList;
- // TODO - is it worth/possible to display jagged data
- // If data is jagged throw warning
- if (xLabels.Count != values.Count || xLabels.Count == 0)
+ if (!InPorts[0].IsConnected && !InPorts[1].IsConnected && !InPorts[2].IsConnected)
{
- throw new Exception("Label and Values do not properly align in length.");
+ return;
}
// Clear current chart values
@@ -146,6 +178,13 @@ private void DataBridgeCallback(object data)
Values = new List>();
Colors = new List();
+ var anyNullData = xLabels == null || yLabels == null || values == null;
+
+ if (anyNullData || xLabels.Count != values.Count || yLabels.Count != (values[0] as ArrayList).Count || xLabels.Count == 0 || yLabels.Count == 0)
+ {
+ throw new Exception("Label and Values do not properly align in length.");
+ }
+
// Iterate the x and y values separately as they may be different lengths
for (var i = 0; i < xLabels.Count; i++)
{
@@ -174,6 +213,8 @@ private void DataBridgeCallback(object data)
// If colors is empty add 1 random color
if (colors == null || colors.Count == 0)
{
+ if (InPorts[3].IsConnected) return;
+
// In case colors are not provided, we supply some from the default library of colors
Info(Dynamo.Wpf.Properties.CoreNodeModelWpfResources.ProvideDefaultColorsWarningMessage);
@@ -183,7 +224,6 @@ private void DataBridgeCallback(object data)
Utilities.Colors.ResetColors();
}
-
// If provided with 1 color blend white to color
// Else create color range from provided color
else
@@ -196,8 +236,6 @@ private void DataBridgeCallback(object data)
}
}
- // TODO - Should this use Dynamo Scheduler to prevent timing issues with redundant calls?
- // Notify UI the data has been modified
RaisePropertyChanged("DataUpdated");
}
#endregion
@@ -216,8 +254,29 @@ public override IEnumerable BuildOutputAst(List, List, List>, List, Dictionary>>(HeatSeriesFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2], inputAstNodes[3] }
+ );
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
+ else if (!InPorts[0].IsConnected ||
!InPorts[1].IsConnected ||
!InPorts[2].IsConnected)
{
@@ -226,21 +285,23 @@ public override IEnumerable BuildOutputAst(List, List, List>, List, Dictionary>>(HeatSeriesFunctions.GetNodeInput),
- new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2], inputAstNodes[3] }
- );
-
- return new[]
+ else
{
- AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
- AstFactory.BuildAssignment(
- AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
- VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
- )
- ),
- };
+ inputNode = AstFactory.BuildFunctionCall(
+ new Func, List, List>, List, Dictionary>>(HeatSeriesFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2], inputAstNodes[3] }
+ );
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
}
#endregion
@@ -251,7 +312,8 @@ public override IEnumerable BuildOutputAst(List
public override void Dispose()
{
- PortDisconnected -= XYLineChartNodeModel_PortDisconnected;
+ PortConnected -= HeatSeriesNodeModel_PortConnected;
+ PortDisconnected -= HeatSeriesNodeModel_PortDisconnected;
VMDataBridge.DataBridge.Instance.UnregisterCallback(GUID.ToString());
}
@@ -264,6 +326,9 @@ public override void Dispose()
public class HeatSeriesNodeView : INodeViewCustomization
{
private HeatSeriesControl heatSeriesControl;
+ private NodeView view;
+ private HeatSeriesNodeModel model;
+
///
/// At run-time, this method is called during the node
@@ -273,6 +338,8 @@ public class HeatSeriesNodeView : INodeViewCustomization
/// The NodeView representing the node in the graph.
public void CustomizeView(HeatSeriesNodeModel model, NodeView nodeView)
{
+ this.model = model;
+ this.view = nodeView;
heatSeriesControl = new HeatSeriesControl(model);
nodeView.inputGrid.Children.Add(heatSeriesControl);
@@ -282,6 +349,50 @@ public void CustomizeView(HeatSeriesNodeModel model, NodeView nodeView)
var contextMenu = (nodeView.Content as Grid).ContextMenu;
contextMenu.Items.Add(exportImage);
+
+ UpdateDefaultInPortValues();
+
+ model.PortUpdated += ModelOnPortUpdated;
+ }
+ private void ModelOnPortUpdated(object sender, EventArgs e)
+ {
+ UpdateDefaultInPortValues();
+ }
+ private void UpdateDefaultInPortValues()
+ {
+ if (!this.view.ViewModel.InPorts.Any()) return;
+ var inPorts = this.view.ViewModel.InPorts;
+
+ // Only apply default values if all ports are disconnected
+ if (!model.IsInErrorState &&
+ model.State != ElementState.Active &&
+ !inPorts[0].IsConnected &&
+ !inPorts[1].IsConnected &&
+ !inPorts[2].IsConnected)
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = true;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = true;
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = false;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = false;
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = false;
+ }
+
+ var allPortsConnected = inPorts[0].IsConnected && inPorts[1].IsConnected && inPorts[2].IsConnected && model.State != ElementState.Warning;
+ var noPortsConnected = !inPorts[0].IsConnected && !inPorts[1].IsConnected && !inPorts[2].IsConnected;
+
+ // The color input uses default values if it's not connected
+ if (!inPorts[3].IsConnected && (allPortsConnected || noPortsConnected))
+ {
+ ((InPortViewModel)inPorts[3]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[3]).PortDefaultValueMarkerVisible = false;
+ }
}
private void ExportImage_Click(object sender, RoutedEventArgs e)
@@ -293,6 +404,9 @@ private void ExportImage_Click(object sender, RoutedEventArgs e)
/// Here you can do any cleanup you require if you've assigned callbacks for particular
/// UI events on your node.
///
- public void Dispose() { }
+ public void Dispose()
+ {
+ model.PortUpdated -= ModelOnPortUpdated;
+ }
}
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/PieChartNodeModel.cs b/src/Libraries/CoreNodeModelsWpf/Charts/PieChartNodeModel.cs
index d8ece538c61..8f28f85c339 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/PieChartNodeModel.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/PieChartNodeModel.cs
@@ -19,6 +19,8 @@
using DynamoServices;
using Dynamo.Wpf.Properties;
using Xceed.Wpf.Toolkit;
+using Dynamo.Graph.Connectors;
+using Dynamo.ViewModels;
namespace CoreNodeModelsWpf.Charts
{
@@ -27,9 +29,16 @@ namespace CoreNodeModelsWpf.Charts
[NodeCategory("Display.Charts.Create")]
[NodeDescription("ChartsPieChartDescription", typeof(CoreNodeModelWpfResources))]
[NodeSearchTags("ChartsPieChartSearchTags", typeof(CoreNodeModelWpfResources))]
-
+ [InPortNames("labels", "values", "colors")]
[InPortTypes("List", "List", "List")]
- [OutPortTypes("Dictionary")]
+ [InPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsPieChartLabelsDataPortToolTip",
+ "ChartsPieChartValuesDataPortToolTip",
+ "ChartsPieChartColorsDataPortToolTip")]
+ [OutPortNames("labels:values")]
+ [OutPortTypes("Dictionary")]
+ [OutPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsPieChartLabelsValuesDataPortToolTip")]
[AlsoKnownAs("CoreNodeModelsWpf.Charts.PieChart")]
public class PieChartNodeModel : NodeModel
{
@@ -49,6 +58,16 @@ public class PieChartNodeModel : NodeModel
/// Pie chart color values.
///
public List Colors { get; set; }
+
+ ///
+ /// Triggers when port is connected or disconnected
+ ///
+ public event EventHandler PortUpdated;
+
+ protected virtual void OnPortUpdated(EventArgs args)
+ {
+ PortUpdated?.Invoke(this, args);
+ }
#endregion
#region Constructors
@@ -57,25 +76,22 @@ public class PieChartNodeModel : NodeModel
///
public PieChartNodeModel()
{
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("labels", "A list of string labels for each segment in the pie chart.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("values", "A list of double values to supply a value for each segment of the pie chart.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("colors", "A list of colors for each segment of the pie chart.")));
-
- OutPorts.Add(new PortModel(PortType.Output, this, new PortData("labels:values", "Dictionary containing label:value key-pairs")));
-
RegisterAllPorts();
+ PortConnected += PieChartNodeModel_PortConnected;
PortDisconnected += PieChartNodeModel_PortDisconnected;
ArgumentLacing = LacingStrategy.Disabled;
}
+
[JsonConstructor]
///
/// Instantiate a new NodeModel instance.
///
public PieChartNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
+ PortConnected += PieChartNodeModel_PortConnected;
PortDisconnected += PieChartNodeModel_PortDisconnected;
}
#endregion
@@ -83,16 +99,29 @@ public PieChartNodeModel(IEnumerable inPorts, IEnumerable
#region Events
private void PieChartNodeModel_PortDisconnected(PortModel port)
{
+ OnPortUpdated(null);
// Clear UI when a input port is disconnected
- if (port.PortType == PortType.Input && this.State == ElementState.Active)
+ if (port.PortType == PortType.Input)
{
- Labels.Clear();
- Values.Clear();
- Colors.Clear();
+ Labels?.Clear();
+ Values?.Clear();
+ Colors?.Clear();
RaisePropertyChanged("DataUpdated");
}
}
+
+ private void PieChartNodeModel_PortConnected(PortModel port, ConnectorModel arg2)
+ {
+ // Reset an info states if any
+ if (port.PortType == PortType.Input && InPorts[2].IsConnected && NodeInfos.Any(x => x.State.Equals(ElementState.Info)))
+ {
+ this.ClearInfoMessages();
+ }
+
+ OnPortUpdated(null);
+ RaisePropertyChanged("DataUpdated");
+ }
#endregion
#region databridge
@@ -125,10 +154,9 @@ private void DataBridgeCallback(object data)
var values = inputs[1] as ArrayList;
var colors = inputs[2] as ArrayList;
- // Only continue if key/values match in length
- if (keys.Count != values.Count || keys.Count < 1)
+ if (!InPorts[0].IsConnected && !InPorts[1].IsConnected && !InPorts[2].IsConnected)
{
- throw new Exception("Label and Values do not properly align in length.");
+ return;
}
// Update chart properties
@@ -136,8 +164,18 @@ private void DataBridgeCallback(object data)
Values = new List();
Colors = new List();
+ var anyNullData = keys == null || values == null;
+
+ // Only continue if key/values match in length
+ if (anyNullData || keys.Count != values.Count || keys.Count == 0)
+ {
+ throw new Exception("Label and Values do not properly align in length.");
+ }
+
if (colors == null || colors.Count == 0 || colors.Count != keys.Count)
{
+ if (InPorts[2].IsConnected) return;
+
// In case colors are not provided, we supply some from the default library of colors
Info(Dynamo.Wpf.Properties.CoreNodeModelWpfResources.ProvideDefaultColorsWarningMessage);
@@ -186,30 +224,52 @@ public override IEnumerable BuildOutputAst(List, List, List, Dictionary>(PieChartFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
+ );
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
+ else if (!InPorts[0].IsConnected || !InPorts[1].IsConnected)
{
return new[]
{
AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()),
};
+
}
+ else
+ {
+ inputNode = AstFactory.BuildFunctionCall(
+ new Func, List, List, Dictionary>(PieChartFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
+ );
- AssociativeNode inputNode = AstFactory.BuildFunctionCall(
- new Func, List, List, Dictionary>(PieChartFunctions.GetNodeInput),
- new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2] }
- );
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
- return new[]
- {
- AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
- AstFactory.BuildAssignment(
- AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
- VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
- )
- ),
- };
}
#endregion
@@ -220,6 +280,7 @@ public override IEnumerable BuildOutputAst(List
public override void Dispose()
{
+ PortConnected -= PieChartNodeModel_PortConnected;
PortDisconnected -= PieChartNodeModel_PortDisconnected;
VMDataBridge.DataBridge.Instance.UnregisterCallback(GUID.ToString());
}
@@ -233,6 +294,8 @@ public override void Dispose()
public class PieChartNodeView : INodeViewCustomization
{
private PieChartControl pieChartControl;
+ private NodeView view;
+ private PieChartNodeModel model;
///
/// At run-time, this method is called during the node
@@ -242,6 +305,8 @@ public class PieChartNodeView : INodeViewCustomization
/// The NodeView representing the node in the graph.
public void CustomizeView(PieChartNodeModel model, NodeView nodeView)
{
+ this.model = model;
+ this.view = nodeView;
pieChartControl = new PieChartControl(model);
nodeView.inputGrid.Children.Add(pieChartControl);
@@ -251,6 +316,49 @@ public void CustomizeView(PieChartNodeModel model, NodeView nodeView)
var contextMenu = (nodeView.Content as Grid).ContextMenu;
contextMenu.Items.Add(exportImage);
+
+ UpdateDefaultInPortValues();
+
+ model.PortUpdated += ModelOnPortUpdated;
+ }
+
+ private void ModelOnPortUpdated(object sender, EventArgs e)
+ {
+ UpdateDefaultInPortValues();
+ }
+
+ private void UpdateDefaultInPortValues()
+ {
+ if (!this.view.ViewModel.InPorts.Any()) return;
+ var inPorts = this.view.ViewModel.InPorts;
+
+ // Only apply default values if all ports are disconnected
+ if (!model.IsInErrorState &&
+ model.State != ElementState.Active &&
+ !inPorts[0].IsConnected &&
+ !inPorts[1].IsConnected)
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = true;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = false;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = false;
+ }
+
+ var allPortsConnected = inPorts[0].IsConnected && inPorts[1].IsConnected && model.State != ElementState.Warning;
+ var noPortsConnected = !inPorts[0].IsConnected && !inPorts[1].IsConnected;
+
+ // The color input uses default values if it's not connected
+ if (!inPorts[2].IsConnected && (allPortsConnected || noPortsConnected))
+ {
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = false;
+ }
}
private void ExportImage_Click(object sender, RoutedEventArgs e)
@@ -262,6 +370,9 @@ private void ExportImage_Click(object sender, RoutedEventArgs e)
/// Here you can do any cleanup you require if you've assigned callbacks for particular
/// UI events on your node.
///
- public void Dispose() { }
+ public void Dispose()
+ {
+ model.PortUpdated -= ModelOnPortUpdated;
+ }
}
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/ScatterPlotNodeModel.cs b/src/Libraries/CoreNodeModelsWpf/Charts/ScatterPlotNodeModel.cs
index 43ec13132be..612df33032e 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/ScatterPlotNodeModel.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/ScatterPlotNodeModel.cs
@@ -19,6 +19,8 @@
using DynamoServices;
using Dynamo.Wpf.Properties;
using ProtoCore.DesignScriptParser;
+using Dynamo.Graph.Connectors;
+using Dynamo.ViewModels;
namespace CoreNodeModelsWpf.Charts
{
@@ -27,9 +29,17 @@ namespace CoreNodeModelsWpf.Charts
[NodeCategory("Display.Charts.Create")]
[NodeDescription("ChartsScatterPlotDescription", typeof(CoreNodeModelWpfResources))]
[NodeSearchTags("ChartsScatterPlotSearchTags", typeof(CoreNodeModelWpfResources))]
-
+ [InPortNames("labels", "x-values", "y-values", "colors")]
[InPortTypes("List", "List>", "List>", "List")]
- [OutPortTypes("Dictionary")]
+ [InPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsScatterPlotLabelsDataPortToolTip",
+ "ChartsScatterPlotXLabelsDataPortToolTip",
+ "ChartsScatterPlotYLabelsDataPortToolTip",
+ "ChartsScatterPlotColorsDataPortToolTip")]
+ [OutPortNames("labels:values")]
+ [OutPortTypes("Dictionary>>")]
+ [OutPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsScatterPlotLabelsValuesDataPortToolTip")]
[AlsoKnownAs("CoreNodeModelsWpf.Charts.ScatterPlot")]
public class ScatterPlotNodeModel : NodeModel
{
@@ -55,6 +65,16 @@ public class ScatterPlotNodeModel : NodeModel
/// A list of color values, one for each plotted line.
///
public List Colors { get; set; }
+
+ ///
+ /// Triggers when port is connected or disconnected
+ ///
+ public event EventHandler PortUpdated;
+
+ protected virtual void OnPortUpdated(EventArgs args)
+ {
+ PortUpdated?.Invoke(this, args);
+ }
#endregion
#region Constructors
@@ -63,15 +83,9 @@ public class ScatterPlotNodeModel : NodeModel
///
public ScatterPlotNodeModel()
{
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("labels", "A list of string labels for each group of points to be plotted.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("x-values", "A list of lists each containing double values representing x-coordinates.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("y-values", "A list of lists each containing double values representing y-coordinates.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("colors", "A list of colors for each group of points.")));
-
- OutPorts.Add(new PortModel(PortType.Output, this, new PortData("labels:values", "Dictionary containing label:value key-pairs")));
-
RegisterAllPorts();
+ PortConnected += ScatterPlotNodeModel_PortConnected;
PortDisconnected += ScatterPlotNodeModel_PortDisconnected;
ArgumentLacing = LacingStrategy.Disabled;
@@ -83,6 +97,7 @@ public ScatterPlotNodeModel()
///
public ScatterPlotNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
+ PortConnected += ScatterPlotNodeModel_PortConnected;
PortDisconnected += ScatterPlotNodeModel_PortDisconnected;
}
#endregion
@@ -90,17 +105,30 @@ public ScatterPlotNodeModel(IEnumerable inPorts, IEnumerable x.State.Equals(ElementState.Info)))
+ {
+ this.ClearInfoMessages();
+ }
+
+ OnPortUpdated(null);
+ RaisePropertyChanged("DataUpdated");
+ }
#endregion
#region Databridge
@@ -134,10 +162,9 @@ private void DataBridgeCallback(object data)
var yValues = inputs[2] as ArrayList;
var colors = inputs[3] as ArrayList;
- // Only continue if key/values match in length
- if (labels.Count != xValues.Count || xValues.Count != yValues.Count || labels.Count < 1)
+ if (!InPorts[0].IsConnected && !InPorts[1].IsConnected && !InPorts[2].IsConnected)
{
- throw new Exception("Label and Values do not properly align in length.");
+ return;
}
// Clear current chart values
@@ -146,9 +173,19 @@ private void DataBridgeCallback(object data)
YValues = new List>();
Colors = new List();
+ var anyNullData = labels == null || xValues == null || yValues == null;
+
+ // Only continue if key/values match in length
+ if (anyNullData || labels.Count != xValues.Count || xValues.Count != yValues.Count || labels.Count == 0 || xValues.Count == 0)
+ {
+ throw new Exception("Label and Values do not properly align in length.");
+ }
+
// If color count doesn't match title count use random colors
if (colors == null || colors.Count == 0 || colors.Count != labels.Count)
{
+ if (InPorts[3].IsConnected) return;
+
// In case colors are not provided, we supply some from the default library of colors
Info(Dynamo.Wpf.Properties.CoreNodeModelWpfResources.ProvideDefaultColorsWarningMessage);
@@ -199,11 +236,18 @@ private void DataBridgeCallback(object data)
XValues.Add(outputXValues);
YValues.Add(outputYValues);
- var dynColor = (DSCore.Color)colors[i];
- var convertedColor = Color.FromArgb(dynColor.Alpha, dynColor.Red, dynColor.Green, dynColor.Blue);
- SolidColorBrush brush = new SolidColorBrush(convertedColor);
- brush.Freeze();
- Colors.Add(brush);
+ try
+ {
+ var dynColor = (DSCore.Color)colors[i];
+ var convertedColor = Color.FromArgb(dynColor.Alpha, dynColor.Red, dynColor.Green, dynColor.Blue);
+ SolidColorBrush brush = new SolidColorBrush(convertedColor);
+ brush.Freeze();
+ Colors.Add(brush);
+ }
+ catch (Exception)
+ {
+ throw new Exception("Colors are not properly defined list of colors.");
+ }
}
}
@@ -226,31 +270,54 @@ public override IEnumerable BuildOutputAst(List, List>, List>, List, Dictionary>>>(ScatterPlotFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2], inputAstNodes[3] }
+ );
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
+ else if (!InPorts[0].IsConnected ||
+ !InPorts[1].IsConnected ||
+ !InPorts[2].IsConnected)
{
return new[]
{
AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()),
};
}
-
- AssociativeNode inputNode = AstFactory.BuildFunctionCall(
- new Func, List>, List>, List, Dictionary>>>(ScatterPlotFunctions.GetNodeInput),
- new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2], inputAstNodes[3] }
- );
-
- return new[]
+ else
{
- AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
- AstFactory.BuildAssignment(
- AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
- VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
- )
- ),
- };
+ inputNode = AstFactory.BuildFunctionCall(
+ new Func, List>, List>, List, Dictionary>>>(ScatterPlotFunctions.GetNodeInput),
+ new List { inputAstNodes[0], inputAstNodes[1], inputAstNodes[2], inputAstNodes[3] }
+ );
+
+ return new[]
+ {
+ AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), inputNode),
+ AstFactory.BuildAssignment(
+ AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"),
+ VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes)
+ )
+ ),
+ };
+ }
}
#endregion
@@ -261,6 +328,7 @@ public override IEnumerable BuildOutputAst(List
public override void Dispose()
{
+ PortConnected -= ScatterPlotNodeModel_PortConnected;
PortDisconnected -= ScatterPlotNodeModel_PortDisconnected;
VMDataBridge.DataBridge.Instance.UnregisterCallback(GUID.ToString());
}
@@ -274,6 +342,8 @@ public override void Dispose()
public class ScatterPlotNodeView : INodeViewCustomization
{
private ScatterPlotControl scatterPlotControl;
+ private NodeView view;
+ private ScatterPlotNodeModel model;
///
/// At run-time, this method is called during the node
@@ -283,6 +353,8 @@ public class ScatterPlotNodeView : INodeViewCustomization
/// The NodeView representing the node in the graph.
public void CustomizeView(ScatterPlotNodeModel model, NodeView nodeView)
{
+ this.model = model;
+ this.view = nodeView;
scatterPlotControl = new ScatterPlotControl(model);
nodeView.inputGrid.Children.Add(scatterPlotControl);
@@ -292,6 +364,52 @@ public void CustomizeView(ScatterPlotNodeModel model, NodeView nodeView)
var contextMenu = (nodeView.Content as Grid).ContextMenu;
contextMenu.Items.Add(exportImage);
+
+ UpdateDefaultInPortValues();
+
+ model.PortUpdated += ModelOnPortUpdated;
+ }
+
+ private void ModelOnPortUpdated(object sender, EventArgs e)
+ {
+ UpdateDefaultInPortValues();
+ }
+
+ private void UpdateDefaultInPortValues()
+ {
+ if (!this.view.ViewModel.InPorts.Any()) return;
+ var inPorts = this.view.ViewModel.InPorts;
+
+ // Only apply default values if all ports are disconnected
+ if (!model.IsInErrorState &&
+ model.State != ElementState.Active &&
+ !inPorts[0].IsConnected &&
+ !inPorts[1].IsConnected &&
+ !inPorts[2].IsConnected)
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = true;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = true;
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[0]).PortDefaultValueMarkerVisible = false;
+ ((InPortViewModel)inPorts[1]).PortDefaultValueMarkerVisible = false;
+ ((InPortViewModel)inPorts[2]).PortDefaultValueMarkerVisible = false;
+ }
+
+ var allPortsConnected = inPorts[0].IsConnected && inPorts[1].IsConnected && inPorts[2].IsConnected && model.State != ElementState.Warning;
+ var noPortsConnected = !inPorts[0].IsConnected && !inPorts[1].IsConnected && !inPorts[2].IsConnected;
+
+ // The color input uses default values if it's not connected
+ if (!inPorts[3].IsConnected && (allPortsConnected || noPortsConnected))
+ {
+ ((InPortViewModel)inPorts[3]).PortDefaultValueMarkerVisible = true;
+ }
+ else
+ {
+ ((InPortViewModel)inPorts[3]).PortDefaultValueMarkerVisible = false;
+ }
}
private void ExportImage_Click(object sender, RoutedEventArgs e)
@@ -303,6 +421,9 @@ private void ExportImage_Click(object sender, RoutedEventArgs e)
/// Here you can do any cleanup you require if you've assigned callbacks for particular
/// UI events on your node.
///
- public void Dispose() { }
+ public void Dispose()
+ {
+ model.PortUpdated -= ModelOnPortUpdated;
+ }
}
}
diff --git a/src/Libraries/CoreNodeModelsWpf/Charts/XYLineChartNodeModel.cs b/src/Libraries/CoreNodeModelsWpf/Charts/XYLineChartNodeModel.cs
index bbb5acd8bd3..ef699141c64 100644
--- a/src/Libraries/CoreNodeModelsWpf/Charts/XYLineChartNodeModel.cs
+++ b/src/Libraries/CoreNodeModelsWpf/Charts/XYLineChartNodeModel.cs
@@ -12,7 +12,9 @@
using CoreNodeModelsWpf.Charts.Controls;
using CoreNodeModelsWpf.Charts.Utilities;
using Dynamo.Controls;
+using Dynamo.Graph.Connectors;
using Dynamo.Graph.Nodes;
+using Dynamo.ViewModels;
using Dynamo.Wpf;
using Newtonsoft.Json;
using ProtoCore.AST.AssociativeAST;
@@ -26,9 +28,17 @@ namespace CoreNodeModelsWpf.Charts
[NodeCategory("Display.Charts.Create")]
[NodeDescription("ChartsXYLineChartDescription", typeof(CoreNodeModelWpfResources))]
[NodeSearchTags("ChartsXYLineChartSearchTags", typeof(CoreNodeModelWpfResources))]
-
+ [InPortNames("labels", "x-values", "y-values", "colors")]
[InPortTypes("List", "List>", "List>", "List")]
- [OutPortTypes("Dictionary")]
+ [InPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsXYLineChartLabelsDataPortToolTip",
+ "ChartsXYLineChartXLabelsDataPortToolTip",
+ "ChartsXYLineChartYLabelsDataPortToolTip",
+ "ChartsXYLineChartColorsDataPortToolTip")]
+ [OutPortNames("labels:values")]
+ [OutPortTypes("Dictionary>>")]
+ [OutPortDescriptions(typeof(CoreNodeModelWpfResources),
+ "ChartsXYLineChartLabelsValuesDataPortToolTip")]
[AlsoKnownAs("CoreNodeModelsWpf.Charts.XYLinePlot")]
public class XYLineChartNodeModel : NodeModel
{
@@ -54,6 +64,16 @@ public class XYLineChartNodeModel : NodeModel
/// A list of color values, one for each plotted line.
///
public List Colors { get; set; }
+
+ ///
+ /// Triggers when port is connected or disconnected
+ ///
+ public event EventHandler PortUpdated;
+
+ protected virtual void OnPortUpdated(EventArgs args)
+ {
+ PortUpdated?.Invoke(this, args);
+ }
#endregion
#region Constructors
@@ -62,26 +82,21 @@ public class XYLineChartNodeModel : NodeModel
///
public XYLineChartNodeModel()
{
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("labels", "A list of string labels for each line to be plotted")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("x-values", "A list of lists each containing double values representing x-coordinates for each point in a line.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("y-values", "A list of lists each containing double values representing y-coordinates for each point in a line.")));
- InPorts.Add(new PortModel(PortType.Input, this, new PortData("colors", "A list of colors for each line in the line plot.")));
-
- OutPorts.Add(new PortModel(PortType.Output, this, new PortData("labels:values", "Dictionary containing label:value key-pairs")));
-
RegisterAllPorts();
+ PortConnected += XYLineChartNodeModel_PortConnected;
PortDisconnected += XYLineChartNodeModel_PortDisconnected;
ArgumentLacing = LacingStrategy.Disabled;
}
- [JsonConstructor]
///
/// Instantiate a new NodeModel instance.
///
+ [JsonConstructor]
public XYLineChartNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts)
{
+ PortConnected += XYLineChartNodeModel_PortConnected;
PortDisconnected += XYLineChartNodeModel_PortDisconnected;
}
#endregion
@@ -89,17 +104,29 @@ public XYLineChartNodeModel(IEnumerable inPorts, IEnumerable x.State.Equals(ElementState.Info)))
+ {
+ this.ClearInfoMessages();
+ }
+
+ OnPortUpdated(null);
+ RaisePropertyChanged("DataUpdated");
+ }
#endregion
#region Databridge
@@ -132,11 +159,10 @@ private void DataBridgeCallback(object data)
var xValues = inputs[1] as ArrayList;
var yValues = inputs[2] as ArrayList;
var colors = inputs[3] as ArrayList;
-
- // Only continue if key/values match in length
- if (labels.Count != xValues.Count || xValues.Count != yValues.Count || labels.Count < 1)
+
+ if (!InPorts[0].IsConnected && !InPorts[1].IsConnected && !InPorts[2].IsConnected)
{
- throw new Exception("Label and Values do not properly align in length.");
+ return;
}
// Clear current chart values
@@ -145,9 +171,19 @@ private void DataBridgeCallback(object data)
YValues = new List>();
Colors = new List();
+ var anyNullData = labels == null || xValues == null || yValues == null;
+
+ // Only continue if key/values match in length
+ if (anyNullData || labels.Count != xValues.Count || xValues.Count != yValues.Count || labels.Count == 0 || xValues.Count == 0)
+ {
+ throw new Exception("Label and Values do not properly align in length.");
+ }
+
// If color count doesn't match title count use random colors
if (colors == null || colors.Count == 0 || colors.Count != labels.Count)
{
+ if(InPorts[3].IsConnected) return;
+
// In case colors are not provided, we supply some from the default library of colors
Info(Dynamo.Wpf.Properties.CoreNodeModelWpfResources.ProvideDefaultColorsWarningMessage);
@@ -198,11 +234,18 @@ private void DataBridgeCallback(object data)
XValues.Add(outputXValues);
YValues.Add(outputYValues);
- var dynColor = (DSCore.Color)colors[i];
- var convertedColor = Color.FromArgb(dynColor.Alpha, dynColor.Red, dynColor.Green, dynColor.Blue);
- SolidColorBrush brush = new SolidColorBrush(convertedColor);
- brush.Freeze();
- Colors.Add(brush);
+ try
+ {
+ var dynColor = (DSCore.Color)colors[i];
+ var convertedColor = Color.FromArgb(dynColor.Alpha, dynColor.Red, dynColor.Green, dynColor.Blue);
+ SolidColorBrush brush = new SolidColorBrush(convertedColor);
+ brush.Freeze();
+ Colors.Add(brush);
+ }
+ catch(Exception)
+ {
+ throw new Exception("Colors are not properly defined list of colors.");
+ }
}
}
@@ -225,31 +268,55 @@ public override IEnumerable