Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/DynamoCoreWpf/Controls/DynamoTextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ private void UpdateDataSource(bool recordForUndo)

if (expr.HasValidationError && nvm != null)
{
nvm.NodeModel.ClearErrorsAndWarnings();
nvm.NodeModel.Error(expr.ValidationError.ErrorContent as string);
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/Libraries/CoreNodeModels/Input/BaseTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,18 @@ protected override void DeserializeCore(XmlElement element, SaveContext context)
{
base.DeserializeCore(element, context); //Base implementation must be called

ClearErrorsAndWarnings();

foreach (
XmlNode subNode in
element.ChildNodes.Cast<XmlNode>()
.Where(subNode => subNode.Name.Equals(typeof(double).FullName)))
{
Value = subNode.Attributes[0].Value;
}

// Value's equality guard can skip notify, force UI to drop uncommitted invalid text
RaisePropertyChanged(nameof(Value));
}

#endregion
Expand Down
74 changes: 68 additions & 6 deletions src/Libraries/CoreNodeModels/Input/DateTime.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Dynamo.Configuration;
using Dynamo.Graph;
using Dynamo.Graph.Nodes;
using Newtonsoft.Json;
using ProtoCore.AST.AssociativeAST;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;

namespace CoreNodeModels.Input
{
Expand All @@ -23,6 +25,27 @@ private DateTime(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts
ShouldDisplayPreviewCore = false;
}

/// <summary>
/// Display text for the DateTime input. Bound TwoWay so WPF validation can run;
/// the setter intentionally discard the value — commits go through UpdateModelValueCommand.
/// </summary>
[JsonIgnore]
public string ValueText
{
get => Value.ToString(PreferenceSettings.DefaultDateFormat, CultureInfo.InvariantCulture);
set => _ = value;
}

public override System.DateTime Value
{
get { return base.Value; }
set
{
base.Value = value;
RaisePropertyChanged(nameof(ValueText));
}
}

/// <summary>
/// Constructor
/// </summary>
Expand Down Expand Up @@ -92,14 +115,53 @@ public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode
};
}

protected override bool UpdateValueCore(UpdateValueParams updateValueParams)
{
if (updateValueParams.PropertyName == nameof(Value)
|| updateValueParams.PropertyName == nameof(ValueText))
{
if (!TryParseDateTime(updateValueParams.PropertyValue, out var parsed))
{
Error(Properties.Resources.DateTimeNodeInputInvalidFormat);
return false;
}

ClearErrorsAndWarnings();
Value = System.DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
return true;
}
return base.UpdateValueCore(updateValueParams);
}

/// <summary>
/// Parses <paramref name="text"/> using <see cref="PreferenceSettings.DefaultDateFormat"/>
/// and the invariant culture.
/// </summary>
/// <param name="text">The date/time string to parse.</param>
/// <param name="parsed">When this method returns, the parsed value if successful; otherwise default.</param>
/// <returns>Return <c>true</c> if <paramref name="text"/> matches the expected format; otherwise <c>false</c>.</returns>
public static bool TryParseDateTime(string text, out System.DateTime parsed)
{
return System.DateTime.TryParseExact(
text,
PreferenceSettings.DefaultDateFormat,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out parsed);
}

protected override System.DateTime DeserializeValue(string val)
{
System.DateTime result;
result = System.DateTime.TryParseExact(val, PreferenceSettings.DefaultDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ?
result : PreferenceSettings.DynamoDefaultTime;
var result = TryParseDateTime(val, out var parsed) ? parsed : PreferenceSettings.DynamoDefaultTime;
return System.DateTime.SpecifyKind(result, DateTimeKind.Utc);
}

protected override void DeserializeCore(XmlElement nodeElement, SaveContext context)
{
base.DeserializeCore(nodeElement, context);
ClearErrorsAndWarnings();
}

protected override string SerializeValue()
{
return Value.ToString(PreferenceSettings.DefaultDateFormat, CultureInfo.InvariantCulture);
Expand Down
9 changes: 9 additions & 0 deletions src/Libraries/CoreNodeModels/Input/DoubleSlider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,22 @@ protected override bool UpdateValueCore(UpdateValueParams updateValueParams)
{
case "Min":
case "MinText":
ClearErrorsAndWarnings();
Min = ConvertStringToDouble(value);
return true; // UpdateValueCore handled.
case "Max":
case "MaxText":
ClearErrorsAndWarnings();
Max = ConvertStringToDouble(value);
return true; // UpdateValueCore handled.
case "Value":
case "ValueText":
ClearErrorsAndWarnings();
Value = ConvertStringToDouble(value);
return true; // UpdateValueCore handled.
case "Step":
case "StepText":
ClearErrorsAndWarnings();
Step = ConvertStringToDouble(value);
return true;
}
Expand All @@ -154,6 +158,8 @@ protected override void DeserializeCore(XmlElement element, SaveContext context)
{
base.DeserializeCore(element, context); //Base implementation must be called.

ClearErrorsAndWarnings();

foreach (XmlNode subNode in element.ChildNodes)
{
if (!subNode.Name.Equals("Range"))
Expand All @@ -180,6 +186,9 @@ protected override void DeserializeCore(XmlElement element, SaveContext context)
}
}

// Value's equality guard can skip notify, force UI to drop uncommitted invalid text
RaisePropertyChanged(nameof(Value));

break;
}
}
Expand Down
21 changes: 7 additions & 14 deletions src/Libraries/CoreNodeModels/Input/IntegerSlider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ public IntegerSlider64Bit()
}

// If the value field in the slider has a number greater than
// long.Maxvalue (or MinValue), the value will be changed to long.MaxValue (or MinValue)
// long.MaxValue (or MinValue), the value will be changed to long.MaxValue (or MinValue)
// The property setter is overridden here to update the UI, in case the value is changed.
public override long Value
{
Expand All @@ -315,38 +315,29 @@ protected override bool UpdateValueCore(UpdateValueParams updateValueParams)
{
case nameof(Min):
case "MinText":
ClearErrorsAndWarnings();
Min = ConvertStringToInt64(value);
return true; // UpdateValueCore handled.
case nameof(Max):
case "MaxText":
ClearErrorsAndWarnings();
Max = ConvertStringToInt64(value);
return true; // UpdateValueCore handled.
case nameof(Value):
case "ValueText":
UpdateNodeInfo(value);
ClearErrorsAndWarnings();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UpdateNodeInfo() used to display an info message when the value has been restricted. So this is a visible change to the user. Not sure if it was intentional.

Value = ConvertStringToInt64(value);
return true; // UpdateValueCore handled.
case nameof(Step):
case "StepText":
ClearErrorsAndWarnings();
Step = ConvertStringToInt64(value);
return true;
}

return base.UpdateValueCore(updateValueParams);
}

private void UpdateNodeInfo(string value)
{
if (IsValueInt64(value))
{
ClearInfoMessages();
}
else
{
Info(Resources.IntegerSliderInfoMessage, true);
}
}

public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
{
var rhs = AstFactory.BuildIntNode(Value);
Expand Down Expand Up @@ -390,6 +381,8 @@ protected override void DeserializeCore(XmlElement element, SaveContext context)
{
base.DeserializeCore(element, context); //Base implementation must be called.

ClearErrorsAndWarnings();

foreach (XmlNode subNode in element.ChildNodes)
{
if (!subNode.Name.Equals(nameof(Range)))
Expand Down
18 changes: 0 additions & 18 deletions src/Libraries/CoreNodeModels/Input/SliderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,23 +160,5 @@ protected static long ConvertStringToInt64(string value)
}
return result;
}

/// <summary>
/// check if the value is within int64 range
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
protected static bool IsValueInt64(string value)
{
try
{
var result = Convert.ToInt64(value);
return true;
}
catch (OverflowException)
{
return false;
}
}
}
}
18 changes: 18 additions & 0 deletions src/Libraries/CoreNodeModels/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/Libraries/CoreNodeModels/Properties/Resources.en-US.resx
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,12 @@
<data name="NumberNodeInputMustBeNumeric" xml:space="preserve">
<value>The input must be numeric.</value>
</data>
<data name="DateTimeNodeInputInvalidFormat" xml:space="preserve">
<value>The input must match the Date Time format and be a valid date/time.</value>
</data>
<data name="IntegerSliderInputMustBeInteger" xml:space="preserve">
<value>The input must be an integer.</value>
</data>
<data name="ColorPaletteDescription" xml:space="preserve">
<value>Select a Color from the palette</value>
</data>
Expand Down
6 changes: 6 additions & 0 deletions src/Libraries/CoreNodeModels/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,12 @@
<data name="NumberNodeInputMustBeNumeric" xml:space="preserve">
<value>The input must be numeric.</value>
</data>
<data name="DateTimeNodeInputInvalidFormat" xml:space="preserve">
<value>The input must match the Date Time format and be a valid date/time.</value>
</data>
<data name="IntegerSliderInputMustBeInteger" xml:space="preserve">
<value>The input must be an integer.</value>
</data>
<data name="ColorPaletteDescription" xml:space="preserve">
<value>Select a Color from the palette</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
<UserControl x:Class="CoreNodeModelsWpf.Controls.DateTimeInputControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:CoreNodeModelsWpf.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:nodes="clr-namespace:Dynamo.Nodes;assembly=DynamoCoreWpf"
xmlns:p="clr-namespace:Dynamo.Wpf.Properties"
xmlns:ui="clr-namespace:Dynamo.UI;assembly=DynamoCoreWpf"
Width="Auto"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<converters:StringToDateTimeConverter x:Key="StringToDateTimeConverter" />
<ResourceDictionary.MergedDictionaries>
<ui:SharedResourceDictionary Source="{x:Static ui:SharedDictionaryManager.DynamoConvertersDictionaryUri}" />
<ui:SharedResourceDictionary Source="{x:Static ui:SharedDictionaryManager.DynamoModernDictionaryUri}" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<TextBox Height="29"
<nodes:DynamoTextBox x:Name="DateTimeTb"
Height="29"
Margin="0,-5,0,0"
Padding="5,3"
HorizontalAlignment="Stretch"
Expand All @@ -30,11 +30,10 @@
CaretBrush="#6AC0E7"
FontSize="16px"
Foreground="#EEEEEE"
Style="{StaticResource SZoomFadeTextBox}"
Text="{Binding Value, Mode=TwoWay, Converter={StaticResource StringToDateTimeConverter}}">
<TextBox.ToolTip>
Style="{StaticResource SZoomFadeTextBox}" >
<nodes:DynamoTextBox.ToolTip>
<ToolTip Content="{x:Static p:CoreNodeModelWpfResources.DateTimeInputToolTip}" Style="{StaticResource GenericToolTipLight}"/>
</TextBox.ToolTip>
</TextBox>
</nodes:DynamoTextBox.ToolTip>
</nodes:DynamoTextBox>
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Windows;
using System.Windows.Forms;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using UserControl = System.Windows.Controls.UserControl;

namespace CoreNodeModelsWpf.Controls
Expand All @@ -12,15 +13,26 @@
public DateTimeInputControl()
{
InitializeComponent();
Loaded += DateTimeInputControl_Loaded;
}

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
private void DateTimeInputControl_Loaded(object sender, RoutedEventArgs e)

Check warning on line 19 in src/Libraries/CoreNodeModelsWpf/Controls/DateTimeInputControl.xaml.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make 'DateTimeInputControl_Loaded' a static method.

See more on https://sonarcloud.io/project/issues?id=DynamoDS_Dynamo&issues=AZ_bjlcFnSwiWDspNp-8&open=AZ_bjlcFnSwiWDspNp-8&pullRequest=17281
{
var picker = new DateTimePicker
Loaded -= DateTimeInputControl_Loaded;

var binding = new System.Windows.Data.Binding(nameof(CoreNodeModels.Input.DateTime.ValueText))
{
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
NotifyOnValidationError = false
};
var rule = new DateTimeValidationRule
{
Format = DateTimePickerFormat.Time,
ShowUpDown = true,
ValidationStep = ValidationStep.RawProposedValue
};
binding.ValidationRules.Add(rule);
DateTimeTb.BindToProperty(binding);
Validation.SetErrorTemplate(DateTimeTb, null);
}
}
}
Loading
Loading