diff --git a/src/AlohaKit.UI.Figma/AlohaKit.UI.Figma.csproj b/src/AlohaKit.UI.Figma/AlohaKit.UI.Figma.csproj new file mode 100644 index 0000000..c50c322 --- /dev/null +++ b/src/AlohaKit.UI.Figma/AlohaKit.UI.Figma.csproj @@ -0,0 +1,61 @@ + + + + net7.0-maccatalyst + $(TargetFrameworks);net7.0-windows10.0.19041.0 + + + Exe + AlohaKit.UI.Figma + true + true + enable + + + AlohaKit.UI.Figma + + + com.companyname.alohakit.ui.figma + bd33300f-7d11-47df-95ae-c835a27d86e1 + + + 1.0 + 1 + + 11.0 + 13.1 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + 6.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AlohaKit.UI.Figma/App.xaml b/src/AlohaKit.UI.Figma/App.xaml new file mode 100644 index 0000000..ecc0acc --- /dev/null +++ b/src/AlohaKit.UI.Figma/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/src/AlohaKit.UI.Figma/App.xaml.cs b/src/AlohaKit.UI.Figma/App.xaml.cs new file mode 100644 index 0000000..75a21de --- /dev/null +++ b/src/AlohaKit.UI.Figma/App.xaml.cs @@ -0,0 +1,12 @@ +namespace AlohaKit.UI.Figma +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + + MainPage = new AppShell(); + } + } +} \ No newline at end of file diff --git a/src/AlohaKit.UI.Figma/AppShell.xaml b/src/AlohaKit.UI.Figma/AppShell.xaml new file mode 100644 index 0000000..4b3a7bd --- /dev/null +++ b/src/AlohaKit.UI.Figma/AppShell.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/AlohaKit.UI.Figma/AppShell.xaml.cs b/src/AlohaKit.UI.Figma/AppShell.xaml.cs new file mode 100644 index 0000000..d7e6dc8 --- /dev/null +++ b/src/AlohaKit.UI.Figma/AppShell.xaml.cs @@ -0,0 +1,10 @@ +namespace AlohaKit.UI.Figma +{ + public partial class AppShell : Shell + { + public AppShell() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/src/AlohaKit.UI.Figma/Converters/IsGeneratingToVisibleConverter.cs b/src/AlohaKit.UI.Figma/Converters/IsGeneratingToVisibleConverter.cs new file mode 100644 index 0000000..92c31e8 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Converters/IsGeneratingToVisibleConverter.cs @@ -0,0 +1,19 @@ +using System.Globalization; + +namespace AlohaKit.UI.Figma.Converters +{ + internal class IsGeneratingToVisibleConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var text = (string)value; + + return !string.IsNullOrEmpty(text); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Converters/ElipseConverter.cs b/src/AlohaKit.UI.Figma/Figma/Converters/ElipseConverter.cs new file mode 100644 index 0000000..99082dd --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Converters/ElipseConverter.cs @@ -0,0 +1,96 @@ +using FigmaSharp.Converters; +using AlohaKit.UI.Figma.Extensions; +using FigmaSharp.Models; +using FigmaSharp.Services; +using System.Globalization; +using System.Text; + +namespace AlohaKit.UI.Figma.Converters +{ + internal class ElipseConverter : ElipseConverterBase + { + public override string ConvertToCode(CodeNode currentNode, CodeNode parentNode, ICodeRenderService rendererService) + { + if (currentNode.Node is not FigmaElipse elipseNode) + { + return string.Empty; + } + + StringBuilder builder = new StringBuilder(); + + builder.AppendLine(""); + + if (elipseNode.HasFills) + { + var backgroundPaint = elipseNode.fills.FirstOrDefault(); + + if (backgroundPaint != null && backgroundPaint.visible) + { + builder.AppendLine("\n\t"); + + if (backgroundPaint.color != null) + { + builder.AppendLine($"\t\t"); + } + + if (backgroundPaint.gradientStops != null) + { + if (backgroundPaint.type.Equals("GRADIENT_LINEAR", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToLinearGradientPaint()}"); + + if (backgroundPaint.type.Equals("GRADIENT_RADIAL", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToRadialGradientPaint()}"); + } + + if (backgroundPaint.imageRef != null) + builder.AppendLine("\t\t"); + + builder.AppendLine("\t"); + } + } + + builder.AppendLine(""); + + return builder.ToString(); + } + + public override FigmaSharp.Views.IView ConvertToView(FigmaNode currentNode, ViewNode parent, ViewRenderService rendererService) + { + throw new NotImplementedException(); + } + + public override Type GetControlType(FigmaNode currentNode) + => typeof(View); + } +} \ No newline at end of file diff --git a/src/AlohaKit.UI.Figma/Figma/Converters/FrameConverter.cs b/src/AlohaKit.UI.Figma/Figma/Converters/FrameConverter.cs new file mode 100644 index 0000000..ab0d2c4 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Converters/FrameConverter.cs @@ -0,0 +1,102 @@ +using AlohaKit.UI.Figma.Extensions; +using FigmaSharp.Converters; +using FigmaSharp.Models; +using FigmaSharp.Services; +using System.Globalization; +using System.Text; + +namespace AlohaKit.UI.Figma.Converters +{ + public class FrameConverter : FrameConverterBase + { + public override string ConvertToCode(CodeNode currentNode, CodeNode parentNode, ICodeRenderService rendererService) + { + if (currentNode.Node is not FigmaFrame frameNode) + { + return string.Empty; + } + + StringBuilder builder = new StringBuilder(); + + builder.AppendLine(""); + + if (frameNode.HasFills) + { + var backgroundPaint = frameNode.fills.FirstOrDefault(); + + if (backgroundPaint != null && backgroundPaint.visible) + { + builder.AppendLine("\n\t"); + + if (backgroundPaint.color != null) + { + builder.AppendLine($"\t\t"); + } + + if (backgroundPaint.gradientStops != null) + { + if (backgroundPaint.type.Equals("GRADIENT_LINEAR", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToLinearGradientPaint()}"); + + if (backgroundPaint.type.Equals("GRADIENT_RADIAL", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToRadialGradientPaint()}"); + } + + if (backgroundPaint.imageRef != null) + builder.AppendLine("\t\t"); + + builder.AppendLine("\t"); + } + } + + builder.AppendLine(""); + + return builder.ToString(); + } + + public override FigmaSharp.Views.IView ConvertToView(FigmaNode currentNode, ViewNode parent, ViewRenderService rendererService) + { + throw new NotImplementedException(); + } + + public override Type GetControlType(FigmaNode currentNode) + => typeof(View); + + public override bool ScanChildren(FigmaNode currentNode) + => true; + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Converters/ImageConverter.cs b/src/AlohaKit.UI.Figma/Figma/Converters/ImageConverter.cs new file mode 100644 index 0000000..7d3d963 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Converters/ImageConverter.cs @@ -0,0 +1,111 @@ +using AlohaKit.UI.Figma.Extensions; +using FigmaSharp.Converters; +using FigmaSharp.Models; +using FigmaSharp.Services; +using System.Globalization; +using System.Text; +using System.Xml.Linq; + +namespace AlohaKit.UI.Figma.Converters +{ + internal class ImageConverter : NodeConverter + { + public override bool CanConvert(FigmaNode currentNode) + => currentNode.GetType() == typeof(FigmaVector); + + public override string ConvertToCode(CodeNode currentNode, CodeNode parentNode, ICodeRenderService rendererService) + { + if (currentNode.Node is not FigmaVector figmaVector) + { + return string.Empty; + } + + if (figmaVector.fillGeometry == null || figmaVector.fillGeometry.Length == 0) + { + return string.Empty; + } + + StringBuilder builder = new StringBuilder(); + + NumberFormatInfo nfi = new NumberFormatInfo + { + NumberDecimalSeparator = "." + }; + + builder.AppendLine(" 0) + { + var geometry = figmaVector.fillGeometry[0]; + builder.AppendLine($"\tData=\"{geometry.path}\""); + } + + if (figmaVector.HasStrokes) + { + var strokePaint = figmaVector.strokes.FirstOrDefault(); + + if (strokePaint.color != null) + { + builder.AppendLine($"\tStroke=\"{strokePaint.color.ToCodeString()}\""); + } + + if (figmaVector.strokeWeight != 0) + { + var strokeSize = figmaVector.strokeWeight; + builder.AppendLine($"\tStrokeThickness=\"{strokeSize}\""); + } + } + + builder.Append("\t>"); + + if (figmaVector.HasFills) + { + var backgroundPaint = figmaVector.fills.FirstOrDefault(); + + if (backgroundPaint != null && backgroundPaint.visible) + { + builder.AppendLine("\n\t"); + + if (backgroundPaint.color != null) + { + builder.AppendLine($"\t\t"); + } + + if (backgroundPaint.gradientStops != null) + { + if (backgroundPaint.type.Equals("GRADIENT_LINEAR", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToLinearGradientPaint()}"); + + if (backgroundPaint.type.Equals("GRADIENT_RADIAL", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToRadialGradientPaint()}"); + } + + if (backgroundPaint.imageRef != null) + builder.AppendLine("\t\t"); + + builder.AppendLine("\t"); + } + } + + builder.AppendLine(""); + + return builder.ToString(); + } + + public override FigmaSharp.Views.IView ConvertToView(FigmaNode currentNode, ViewNode parent, ViewRenderService rendererService) + { + throw new NotImplementedException(); + } + + public override Type GetControlType(FigmaNode currentNode) + => typeof(View); + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Converters/LineConverter.cs b/src/AlohaKit.UI.Figma/Figma/Converters/LineConverter.cs new file mode 100644 index 0000000..1b7a4b4 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Converters/LineConverter.cs @@ -0,0 +1,22 @@ +using FigmaSharp.Converters; +using FigmaSharp.Models; +using FigmaSharp.Services; + +namespace AlohaKit.UI.Figma.Converters +{ + internal class LineConverter : LineConverterBase + { + public override string ConvertToCode(CodeNode currentNode, CodeNode parentNode, ICodeRenderService rendererService) + { + return ""; + } + + public override FigmaSharp.Views.IView ConvertToView(FigmaNode currentNode, ViewNode parent, ViewRenderService rendererService) + { + throw new NotImplementedException(); + } + + public override Type GetControlType(FigmaNode currentNode) + => typeof(View); + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Converters/PolygonConverter.cs b/src/AlohaKit.UI.Figma/Figma/Converters/PolygonConverter.cs new file mode 100644 index 0000000..324304b --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Converters/PolygonConverter.cs @@ -0,0 +1,22 @@ +using FigmaSharp.Converters; +using FigmaSharp.Models; +using FigmaSharp.Services; + +namespace AlohaKit.UI.Figma.Converters +{ + internal class PolygonConverter : RegularPolygonConverterBase + { + public override string ConvertToCode(CodeNode currentNode, CodeNode parentNode, ICodeRenderService rendererService) + { + return ""; + } + + public override FigmaSharp.Views.IView ConvertToView(FigmaNode currentNode, ViewNode parent, ViewRenderService rendererService) + { + throw new NotImplementedException(); + } + + public override Type GetControlType(FigmaNode currentNode) + => typeof(View); + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Converters/RectangleConverter.cs b/src/AlohaKit.UI.Figma/Figma/Converters/RectangleConverter.cs new file mode 100644 index 0000000..5d93875 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Converters/RectangleConverter.cs @@ -0,0 +1,96 @@ +using AlohaKit.UI.Figma.Extensions; +using FigmaSharp.Converters; +using FigmaSharp.Models; +using FigmaSharp.Services; +using System.Globalization; +using System.Text; + +namespace AlohaKit.UI.Figma.Converters +{ + internal class RectangleConverter : RectangleVectorConverterBase + { + public override string ConvertToCode(CodeNode currentNode, CodeNode parentNode, ICodeRenderService rendererService) + { + if (currentNode.Node is not RectangleVector rectangleVector) + { + return string.Empty; + } + + StringBuilder builder = new StringBuilder(); + + builder.AppendLine(""); + + if (rectangleVector.HasFills) + { + var backgroundPaint = rectangleVector.fills.FirstOrDefault(); + + if (backgroundPaint != null && backgroundPaint.visible) + { + builder.AppendLine("\n\t"); + + if (backgroundPaint.color != null) + { + builder.AppendLine($"\t\t"); + } + + if (backgroundPaint.gradientStops != null) + { + if (backgroundPaint.type.Equals("GRADIENT_LINEAR", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToLinearGradientPaint()}"); + + if (backgroundPaint.type.Equals("GRADIENT_RADIAL", StringComparison.CurrentCultureIgnoreCase)) + builder.AppendLine($"{backgroundPaint.gradientStops.ToRadialGradientPaint()}"); + } + + if (backgroundPaint.imageRef != null) + builder.AppendLine("\t\t"); + + builder.AppendLine("\t"); + } + } + + builder.AppendLine(""); + + return builder.ToString(); + } + + public override FigmaSharp.Views.IView ConvertToView(FigmaNode currentNode, ViewNode parent, ViewRenderService rendererService) + { + throw new NotImplementedException(); + } + + public override Type GetControlType(FigmaNode currentNode) + => typeof(View); + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Converters/TextConverter.cs b/src/AlohaKit.UI.Figma/Figma/Converters/TextConverter.cs new file mode 100644 index 0000000..0b74a69 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Converters/TextConverter.cs @@ -0,0 +1,70 @@ +using FigmaSharp.Converters; +using AlohaKit.UI.Figma.Extensions; +using FigmaSharp.Models; +using FigmaSharp.Services; +using System.Globalization; +using System.Text; + +namespace AlohaKit.UI.Figma.Converters +{ + internal class TextConverter : TextConverterBase + { + public override string ConvertToCode(CodeNode currentNode, CodeNode parentNode, ICodeRenderService rendererService) + { + if (currentNode.Node is not FigmaText textNode) + { + return string.Empty; + } + + StringBuilder builder = new StringBuilder(); + + builder.AppendLine(""); + + return builder.ToString(); + } + + public override FigmaSharp.Views.IView ConvertToView(FigmaNode currentNode, ViewNode parent, ViewRenderService rendererService) + { + throw new NotImplementedException(); + } + + public override Type GetControlType(FigmaNode currentNode) + => typeof(View); + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Extensions/CodeGenerationExtensions.cs b/src/AlohaKit.UI.Figma/Figma/Extensions/CodeGenerationExtensions.cs new file mode 100644 index 0000000..bd4e079 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Extensions/CodeGenerationExtensions.cs @@ -0,0 +1,174 @@ +using AlohaKit.UI.Figma.Helpers; +using FigmaSharp; +using FigmaSharp.Models; +using FigmaSharp.Services; +using System.Text; + +namespace AlohaKit.UI.Figma.Extensions +{ + public static class CodeGenerationExtensions + { + public static string GetFullProperty(this Enum enumeration, string property) + { + return enumeration.GetType().WithProperty(property.ToCamelCase()); + } + + public static string WithProperty(this Type type, string property) + { + return string.Format("{0}.{1}", type.FullName, property); + } + + public static string CreatePropertyName(this CodeNode sender, string propertyName) + { + return string.Format("{0}.{1}", sender.Name, propertyName); + } + + public static string CreateChildObjectName(this CodeNode sender, string propertyName) + { + return string.Format("{0}{1}", sender.Name, propertyName); + } + + public static string GetConstructor(this Type type, params string[] parameters) + { + string args; + if (parameters.Length > 0) + { + args = string.Join(", ", parameters); + } + else + { + args = string.Empty; + } + return $"new {type.FullName} ({args})"; + } + + public static string GetMethod(this Type type, string methodName, string parameters, bool inQuotes = false, bool includesSemicolon = true) + { + return CodeGenerationHelpers.GetMethod(type.FullName, methodName, parameters, inQuotes, includesSemicolon); + } + + public static string GetFullName(this Enum myEnum) + { + return string.Format("{0}.{1}", myEnum.GetType().Name, myEnum.ToString()); + } + + public static string GetConstructor(this CodeNode sender, Type type, bool includesVar = true) + { + return GetConstructor(sender, type.FullName, includesVar); + } + + public static string GetConstructor(this CodeNode sender, string typeFullName, bool includesVar = true) + { + return CodeGenerationHelpers.GetConstructor(sender.Name, typeFullName, includesVar); + } + + public static string GetPropertyEquality(this CodeNode sender, string propertyName, Enum value) + { + return GetPropertyEquality(sender, propertyName, value.GetFullName()); + } + + public static string GetPropertyEquality(this CodeNode sender, string propertyName, bool value) + { + return GetPropertyEquality(sender, propertyName, value.ToString()); + } + + public static string GetPropertyEquality(this CodeNode sender, string propertyName, string value, bool inQuotes = false) + { + return CodeGenerationHelpers.GetPropertyEquality(sender.Name, propertyName, value, inQuotes); + } + + public static string GetMethod(this CodeNode sender, string methodName, Enum parameter) + { + return GetMethod(sender, methodName, parameter.GetFullName()); + } + + public static string GetMethod(this CodeNode sender, string methodName, bool parameter) + { + return CodeGenerationHelpers.GetMethod(sender.Name, methodName, parameter); + } + + public static string GetMethod(this CodeNode sender, string methodName, string parameters, bool inQuotes = false) + { + return CodeGenerationHelpers.GetMethod(sender.Name, methodName, parameters, inQuotes); + } + + #region StringBuilder Code Generation + + public static void WriteConstructor(this StringBuilder builder, string viewName, Type type, bool includesVar = true) + { + WriteConstructor(builder, viewName, type.FullName, includesVar); + } + + public static void WriteConstructor(this StringBuilder builder, string viewName, string typeFullName, bool includesVar = true) + { + builder.AppendLine(CodeGenerationHelpers.GetConstructor(viewName, typeFullName, includesVar)); + } + + public static void WritePropertyEquality(this StringBuilder builder, string viewName, string propertyName, Enum value) + { + WritePropertyEquality(builder, viewName, propertyName, value.GetFullName()); + } + + public static void WriteEquality(this StringBuilder builder, string viewName, string value, bool inQuotes = false, bool instanciate = false) + { + builder.AppendLine(CodeGenerationHelpers.GetEquality(viewName, value, inQuotes, instanciate)); + } + + public static void WritePropertyEquality(this StringBuilder builder, string viewName, string propertyName, bool value) + { + WritePropertyEquality(builder, viewName, propertyName, value.ToString()); + } + + public static void WritePropertyEquality(this StringBuilder builder, string viewName, string propertyName, string value, bool inQuotes = false, bool instanciate = false) + { + builder.AppendLine(CodeGenerationHelpers.GetPropertyEquality(viewName, propertyName, value, inQuotes, instanciate)); + } + + public static void WriteTranslatedEquality(this StringBuilder builder, string viewName, string propertyName, FigmaText value, ICodeRenderService codeRenderService, bool instanciate = false) + { + WriteTranslatedEquality(builder, viewName, propertyName, value.characters, codeRenderService, instanciate, value.visible); + } + + public static void WriteTranslatedEquality(this StringBuilder builder, string viewName, string propertyName, string value, ICodeRenderService codeRenderService, bool instanciate = false, bool textCondition = true) + { + bool needQuotes; + string result; + if (textCondition && !string.IsNullOrEmpty(value)) + { + if (codeRenderService.Options != null && codeRenderService.Options.TranslateLabels) + { + result = codeRenderService.GetTranslatedText(value); + needQuotes = false; + } + else + { + result = value; + needQuotes = true; + } + } + else + { + result = string.Empty; + needQuotes = true; + } + builder.AppendLine(CodeGenerationHelpers.GetPropertyEquality(viewName, propertyName, result, inQuotes: needQuotes, instanciate: instanciate)); + } + + public static void WriteMethod(this StringBuilder builder, string viewName, string methodName, Enum parameter) + { + WriteMethod(builder, viewName, methodName, parameter.GetFullName()); + } + + public static void WriteMethod(this StringBuilder builder, string viewName, string methodName, bool parameter) + { + WriteMethod(builder, viewName, methodName, parameter.ToString()); + } + + public static void WriteMethod(this StringBuilder builder, string viewName, string methodName, string parameters, bool inQuotes = false) + { + builder.AppendLine(CodeGenerationHelpers.GetMethod(viewName, methodName, parameters, inQuotes)); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/AlohaKit.UI.Figma/Figma/Extensions/FigmaExtensions.cs b/src/AlohaKit.UI.Figma/Figma/Extensions/FigmaExtensions.cs new file mode 100644 index 0000000..76c7e68 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Extensions/FigmaExtensions.cs @@ -0,0 +1,136 @@ +using FigmaSharp.Models; +using System.Text; + +namespace AlohaKit.UI.Figma.Extensions +{ + public static class FigmaExtensions + { + public static string ToCodeString(this FigmaSharp.Color color) + { + int red = Convert.ToInt32(color.R * 255); + int green = Convert.ToInt32(color.G * 255); + int blue = Convert.ToInt32(color.B * 255); + + return "#" + red.ToString("X2") + green.ToString("X2") + blue.ToString("X2"); + } + + public static string ToLinearGradientPaint(this ColorStop[] colorStops) + { + StringBuilder builder = new StringBuilder(); + + builder.Append("\t\t"); + builder.AppendLine("\n\t\t\t"); + + foreach (var colorStop in colorStops) + { + var color = colorStop.color; + string hexColor = color.ToCodeString(); + + builder.AppendLine($"\t\t\t\t"); + } + + builder.AppendLine("\t\t\t"); + + builder.Append("\t\t"); + + return builder.ToString(); + } + + public static string ToRadialGradientPaint(this ColorStop[] colorStops) + { + StringBuilder builder = new StringBuilder(); + + builder.Append("\t\t"); + builder.AppendLine("\n\t\t\t"); + + foreach (var colorStop in colorStops) + { + var color = colorStop.color; + string hexColor = color.ToCodeString(); + + builder.AppendLine($"\t\t\t\t"); + } + + builder.AppendLine("\t\t\t"); + + builder.Append("\t\t"); + + return builder.ToString(); + } + + public static string ToCodeString(this float[] values) + { + StringBuilder builder = new StringBuilder(); + + builder.Append("new float[] {"); + var separator = ","; + int i = 0; + + foreach (var value in values) + { + builder.Append($"{ToCodeString(value)}{(i < values.Length ? separator : string.Empty)}"); + i++; + } + + builder.Append("}"); + + return builder.ToString(); + } + + public static string ToCodeString(this float value) + { + return string.Concat(value.ToString(), "f"); + } + + public static string ToCodeString(this double value) + { + return string.Concat(value.ToString(), "f"); + } + + public static string ToCodeString(this FigmaTypeStyle style) + { + var fontFamily = style.fontPostScriptName ?? style.fontFamily; + var fontWeight = style.fontWeight; + + string fontStyleType = "FontStyleType.Normal"; + + if (!string.IsNullOrEmpty(fontFamily) && fontFamily.Contains("Italic", StringComparison.CurrentCultureIgnoreCase)) + fontStyleType = "FontStyleType.Italic"; + + return $"new Microsoft.Maui.Graphics.Font(\"{fontFamily}\", {fontWeight}, {fontStyleType})"; + } + + public static string ToHorizontalAignment(this string value) + { + switch(value) + { + case "LEFT": + return "HorizontalAlignment.Left"; + case "CENTER": + return "HorizontalAlignment.Center"; + case "RIGHT": + return "HorizontalAlignment.Right"; + case "SCALE": + return "HorizontalAlignment.Justified"; + default: + return "HorizontalAlignment.Left"; + } + } + + public static string ToVerticalAlignment(this string value) + { + switch (value) + { + case "TOP": + return "VerticalAlignment.Top"; + case "CENTER": + case "SCALE": + return "VerticalAlignment.Center"; + case "BOTTOM": + return "VerticalAlignment.Bottom"; + default: + return "VerticalAlignment.Top"; + } + } + } +} \ No newline at end of file diff --git a/src/AlohaKit.UI.Figma/Figma/FigmaApplication.cs b/src/AlohaKit.UI.Figma/Figma/FigmaApplication.cs new file mode 100644 index 0000000..c113f62 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/FigmaApplication.cs @@ -0,0 +1,12 @@ +namespace AlohaKit.UI.Figma +{ + public class FigmaApplication + { + public static void Init(string token) + { + var applicationDelegate = new FigmaDelegate(); + + FigmaSharp.AppContext.Current.Configuration(applicationDelegate, token); + } + } +} \ No newline at end of file diff --git a/src/AlohaKit.UI.Figma/Figma/FigmaDelegate.cs b/src/AlohaKit.UI.Figma/Figma/FigmaDelegate.cs new file mode 100644 index 0000000..ea1f7d5 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/FigmaDelegate.cs @@ -0,0 +1,77 @@ +using AlohaKit.UI.Figma.Converters; +using FigmaSharp; +using FigmaSharp.Converters; +using FigmaSharp.PropertyConfigure; +using FigmaSharp.Views; +using System.Reflection; + +namespace AlohaKit.UI.Figma +{ + public class FigmaDelegate : IFigmaDelegate + { + public bool IsVerticalAxisFlipped => false; + + public void BeginInvoke(Action handler) + { + throw new NotImplementedException(); + } + + public FigmaSharp.Views.IView CreateEmptyView() + { + throw new NotImplementedException(); + } + + public CodePropertyConfigureBase GetCodePropertyConfigure() + { + throw new NotImplementedException(); + } + + public NodeConverter[] GetFigmaConverters() + { + return new NodeConverter[]{ + new ElipseConverter(), + new FrameConverter(), + new ImageConverter(), + new LineConverter(), + new PolygonConverter(), + new RectangleConverter(), + new TextConverter() + }; + } + + public FigmaSharp.Views.IImage GetImage(string url) + { + throw new NotImplementedException(); + } + + public FigmaSharp.Views.IImage GetImageFromFilePath(string filePath) + { + throw new NotImplementedException(); + } + + public FigmaSharp.Views.IImage GetImageFromManifest(Assembly assembly, string imageRef) + { + throw new NotImplementedException(); + } + + public IImageView GetImageView(FigmaSharp.Views.IImage image) + { + throw new NotImplementedException(); + } + + public string GetManifestResource(Assembly assembly, string file) + { + throw new NotImplementedException(); + } + + public string GetSvgData(string url) + { + throw new NotImplementedException(); + } + + public ViewPropertyConfigureBase GetViewPropertyConfigure() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/Helpers/CodeGenerationHelpers.cs b/src/AlohaKit.UI.Figma/Figma/Helpers/CodeGenerationHelpers.cs new file mode 100644 index 0000000..141f7e6 --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/Helpers/CodeGenerationHelpers.cs @@ -0,0 +1,65 @@ +using AlohaKit.UI.Figma.Extensions; + +namespace AlohaKit.UI.Figma.Helpers +{ + public static class CodeGenerationHelpers + { + public static string GetConstructor(string viewName, Type type, bool includesVar = true) + { + return GetConstructor(viewName, type.FullName, includesVar); + } + + public static string GetConstructor(string viewName, string typeFullName, bool includesVar = true) + { + return $"{(includesVar ? "var " : string.Empty)}{viewName} = new {typeFullName}();"; + } + + public static string GetPropertyEquality(string viewName, string propertyName, Enum value) + { + return GetPropertyEquality(viewName, propertyName, value.GetFullName()); + } + + public static string GetPropertyEquality(string viewName, string propertyName, bool value) + { + return GetPropertyEquality(viewName, propertyName, value.ToString()); + } + + public static string GetPropertyEquality(string viewName, string propertyName, string value, bool inQuotes = false, bool instanciate = false) + { + string fullPropertyName; + if (string.IsNullOrEmpty(propertyName)) + fullPropertyName = viewName; + else + fullPropertyName = $"{viewName}.{propertyName}"; + return GetEquality(fullPropertyName, value, inQuotes, instanciate); + } + + public static string GetEquality(string viewName, string value, bool inQuotes = false, bool instanciate = false) + { + if (inQuotes) + { + value = string.Format("\"{0}\"", value.Replace("\n", "\\n")); + } + + var instanciateText = instanciate ? "var " : ""; + return $"{instanciateText}{viewName} = {value};"; + } + + public static string GetMethod(string viewName, string methodName, Enum parameter) + { + return GetMethod(viewName, methodName, parameter.GetFullName()); + } + + public static string GetMethod(string viewName, string methodName, bool value) + { + return GetMethod(viewName, methodName, value.ToString()); + } + + public static string GetMethod(string viewName, string methodName, string parameters, bool inQuotes = false, bool includesSemicolon = true) + { + parameters = inQuotes ? $"\"{parameters}\"" : parameters; + var semicolon = includesSemicolon ? ";" : ""; + return $"{viewName}.{methodName} ({parameters}){semicolon}"; + } + } +} diff --git a/src/AlohaKit.UI.Figma/Figma/PropertyConfigure/CodePropertyConfigure.cs b/src/AlohaKit.UI.Figma/Figma/PropertyConfigure/CodePropertyConfigure.cs new file mode 100644 index 0000000..5307c4d --- /dev/null +++ b/src/AlohaKit.UI.Figma/Figma/PropertyConfigure/CodePropertyConfigure.cs @@ -0,0 +1,14 @@ +using FigmaSharp.Converters; +using FigmaSharp.PropertyConfigure; +using FigmaSharp.Services; + +namespace AlohaKit.UI.Figma.PropertyConfigure +{ + public class CodePropertyConfigure : CodePropertyConfigureBase + { + public override string ConvertToCode(string propertyName, CodeNode currentNode, CodeNode parentNode, NodeConverter converter, CodeRenderService rendererService) + { + return string.Empty; + } + } +} \ No newline at end of file diff --git a/src/AlohaKit.UI.Figma/MainPage.xaml b/src/AlohaKit.UI.Figma/MainPage.xaml new file mode 100644 index 0000000..056bb40 --- /dev/null +++ b/src/AlohaKit.UI.Figma/MainPage.xaml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +