Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #224. Border BorderBrush and Background causes compiler error when his value is -1. #225

Merged
merged 19 commits into from
Sep 3, 2023
Merged
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
2 changes: 2 additions & 0 deletions src/Design.cs
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ private IEnumerable<Property> LoadDesignableProperties()
if (this.View is Toplevel)
{
yield return this.CreateProperty(nameof(Toplevel.Modal));
yield return this.CreateProperty(nameof(Toplevel.IsMdiContainer));
}

// Allow changing the FieldName on anything but root where
Expand All @@ -673,6 +674,7 @@ private IEnumerable<Property> LoadDesignableProperties()
{
yield return this.CreateSubProperty(nameof(Border.BorderStyle), nameof(this.View.Border), this.View.Border);
yield return this.CreateSubProperty(nameof(Border.BorderBrush), nameof(this.View.Border), this.View.Border);
yield return this.CreateSubProperty(nameof(Border.Background), nameof(this.View.Border), this.View.Border);
yield return this.CreateSubProperty(nameof(Border.Effect3D), nameof(this.View.Border), this.View.Border);
yield return this.CreateSubProperty(nameof(Border.Effect3DBrush), nameof(this.View.Border), this.View.Border);
yield return this.CreateSubProperty(nameof(Border.DrawMarginFrame), nameof(this.View.Border), this.View.Border);
Expand Down
4 changes: 2 additions & 2 deletions src/FromCode/CodeToView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace TerminalGuiDesigner.FromCode;
/// </summary>
/// <remarks>
/// Compiling requires having the correct assembly references for dependencies. This is handled
/// by <see cref="CompileAssembly"/>. Most references come from <see cref="ReferenceAssemblies.Net60"/>
/// by <see cref="CompileAssembly"/>. Most references come from <see cref="Net70.References"/>
/// but also <see cref="Terminal.Gui"/>.
/// </remarks>
public class CodeToView
Expand Down Expand Up @@ -147,7 +147,7 @@ public Assembly CompileAssembly()
var dd = typeof(Enumerable).GetTypeInfo().Assembly.Location;
var coreDir = Directory.GetParent(dd) ?? throw new Exception($"Could not find parent directory of dotnet sdk. Sdk directory was {dd}");

var references = new List<MetadataReference>(ReferenceAssemblies.Net60);
var references = new List<MetadataReference>(Net70.References.All);

references.Add(MetadataReference.CreateFromFile(typeof(View).Assembly.Location));
references.Add(MetadataReference.CreateFromFile(typeof(ustring).Assembly.Location));
Expand Down
16 changes: 8 additions & 8 deletions src/TerminalGuiDesigner.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
<PackAsTool>true</PackAsTool>
<ToolCommandName>TerminalGuiDesigner</ToolCommandName>
<PackageOutputPath>./nupkg</PackageOutputPath>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<PackageId>TerminalGuiDesigner</PackageId>
<Version>1.0.24</Version>
<Authors>Thomas Nind</Authors>
<Nullable>enable</Nullable>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Description>Command line visual designer tool for creating Terminal.Gui C# applications. Create and edit Termianl.Gui views as easily as you could with the Windows Forms Designer. All generated code is contained in a seperate file (e.g. MyControl.Designer.cs). Run the tool by calling directly from the command line 'TerminalGuiDesigner'</Description>
<Description>Command line visual designer tool for creating Terminal.Gui C# applications. Create and edit Termianl.Gui views as easily as you could with the Windows Forms Designer. All generated code is contained in a separate file (e.g. MyControl.Designer.cs). Run the tool by calling directly from the command line 'TerminalGuiDesigner'</Description>
<Owners>Thomas Nind</Owners>
<Title>TerminalGuiDesigner does for Terminal.Gui what the Windows Forms Designer does for WinForms</Title>
<PackageProjectUrl>https://github.com/tznind/TerminalGuiDesigner/</PackageProjectUrl>
Expand Down Expand Up @@ -134,17 +134,17 @@
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Basic.Reference.Assemblies" Version="1.4.1" />
<PackageReference Include="Basic.Reference.Assemblies.Net70" Version="1.4.5" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageReference Include="nlog" Version="5.1.3" />
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.435">
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
<PackageReference Include="nlog" Version="5.2.3" />
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.507">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.CodeDom" Version="7.0.0" />
<PackageReference Include="Terminal.gui" Version="1.10.1" />
<PackageReference Include="YamlDotNet" Version="13.1.0" />
<PackageReference Include="Terminal.gui" Version="1.14.0" />
<PackageReference Include="YamlDotNet" Version="13.3.1" />
</ItemGroup>

</Project>
24 changes: 24 additions & 0 deletions src/ToCode/Property.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ public virtual void SetValue(object? value)
/// <exception cref="Exception">Thrown if it is not possible to generate code for the current <see cref="Property"/>.</exception>
public virtual void ToCode(CodeDomArgs args)
{
// If property value is known default then do not emit in code gen
if(this.SkipToCode())
{
return;
}

try
{
this.AddPropertyAssignment(args, this.GetLhs(), this.GetRhs());
Expand All @@ -198,6 +204,24 @@ public virtual void ToCode(CodeDomArgs args)
}
}

/// <summary>
/// Returns true if the value of the property is a known default for the API
/// and should not be included in generated code. Especially if the default is
/// odd (e.g. -1 Enum value) or assigning the default to a property breaks other things.
/// </summary>
/// <returns>True if <see cref="ToCode(CodeDomArgs)"/> should not take place.</returns>
private bool SkipToCode()
{
// Color does not contain a definition of -1 but it is used in shorthand to be 'no color'
if (this.PropertyInfo.PropertyType == typeof(Color))
{
var val = this.GetValue();
return val != null && (int)val == -1;
}

return false;
}

/// <summary>
/// Gets a CodeDOM code block for the right hand side of an assignment operation e.g.:
/// <code>"heya"</code>
Expand Down
92 changes: 92 additions & 0 deletions tests/BorderColorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using NUnit.Framework;
using System.Linq;
using System.Reflection;
using Terminal.Gui;
using TerminalGuiDesigner;
using TerminalGuiDesigner.Operations;

namespace UnitTests
{
internal class BorderColorTests : Tests
{
[Test]
public void TestRoundTrip_BorderColors_NeverSet()
{
var result = RoundTrip<Window, FrameView>((d, v) =>
{
// Our view should not have any border color to start with
Assert.AreEqual(-1, (int)v.Border.BorderBrush);
Assert.AreEqual(-1, (int)v.Border.Background);

}, out _);

// Since there were no changes we would expect them to stay the same
// after reload
Assert.AreEqual(-1, (int)result.Border.BorderBrush);
Assert.AreEqual(-1, (int)result.Border.Background);
}

[TestCase(true)]
[TestCase(false)]
public void TestCopyPasteContainer(bool alsoSelectSubElements)
{
RoundTrip<Window, FrameView>((d, v) =>
{
new AddViewOperation(new Label(), d, "lbl1").Do();
new AddViewOperation(new Label(), d, "lbl2").Do();

Assert.AreEqual(2, v.GetActualSubviews().Count(), "Expected the FrameView to have 2 children (lbl1 and lbl2)");

Design[] toCopy;

if (alsoSelectSubElements)
{
var lbl1Design = (Design)d.View.GetActualSubviews().First().Data;
Assert.AreEqual("lbl1", lbl1Design.FieldName);

toCopy = new Design[] { d, lbl1Design };
}
else
{
toCopy = new[] { d };
}

// copy the FrameView
Assert.IsTrue(new CopyOperation(toCopy).Do());

var rootDesign = d.GetRootDesign();

// paste the FrameView
Assert.IsTrue(new PasteOperation(rootDesign).Do());

var rootSubviews = rootDesign.View.GetActualSubviews();

Assert.AreEqual(2, rootSubviews.Count, "Expected root to have 2 FrameView now");
Assert.IsTrue(rootSubviews.All(v => v is FrameView));

Assert.IsTrue(
rootSubviews.All(f => f.GetActualSubviews().Count() == 2),
"Expected both FrameView (copied and pasted) to have the full contents of 2 Labels");

// Since there were no changes we would expect them to stay the same
// after reload
foreach (var rsv in rootSubviews)
{
Assert.AreEqual(-1, (int)rsv.Border.BorderBrush);
Assert.AreEqual(-1, (int)rsv.Border.Background);
Assert.Null(GetFieldValue<Color?>(rsv.Border, "borderBrush"));
Assert.Null(GetFieldValue<Color?>(rsv.Border, "background"));
}
}
, out _);
}

private T GetFieldValue<T>(object obj, string name)
{
// Set the flags so that private and public fields from instances will be found
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var field = obj.GetType().GetField(name, bindingFlags);
return (T)field?.GetValue(obj)!;
}
}
}
12 changes: 6 additions & 6 deletions tests/UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="YamlDotNet" Version="13.1.0" />
<PackageReference Include="ReportGenerator" Version="5.1.20" />
<PackageReference Include="coverlet.collector" Version="3.2.0">
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="YamlDotNet" Version="13.3.1" />
<PackageReference Include="ReportGenerator" Version="5.1.24" />
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down