Browse Source

Added Icon and Text Style

Krzysztof Krysiński 4 tháng trước cách đây
mục cha
commit
77f9951492

+ 17 - 15
src/PixiEditor.Beta/WelcomeMessageState.cs

@@ -13,9 +13,11 @@ We are extremely excited to share this version with you, early testers. Before y
 
 - App is not production ready! Expect bugs, crashes, unfinished features, placeholders and other signs of development.
 ";
-    
-private const string Body2 = "- Your feedback is the most important thing of this beta, please take a moment to report any issues and suggestions on PixiEditor Forum.";
-private const string Body3 = @"
+
+    private const string Body2 =
+        "- Your feedback is the most important thing of this beta, please take a moment to report any issues and suggestions on PixiEditor Forum.";
+
+    private const string Body3 = @"
 - We are collecting anonymous usage data to fix bugs, crashes and performance issues. This data will help us to improve the app. During the beta 
 there is no option to opt-out. No personal data is collected.
 
@@ -35,25 +37,25 @@ I understand that:
                 Alignment.TopCenter,
                 new Column(
                     new Center(new Text("Welcome to the open beta of PixiEditor 2.0!", TextWrap.Wrap,
-                        FontStyle.Normal,
-                        fontSize: 24)),
-                    new Text(Body1, TextWrap.Wrap, fontSize: 16),
+                        new TextStyle(fontSize: 24))),
+                    new Text(Body1, TextWrap.Wrap, new TextStyle(fontSize: 16)),
                     new Hyperlink("https://forum.pixieditor.net", Body2,
-                        fontSize: 16, textWrap: TextWrap.Wrap),
-                    new Text(Body3, TextWrap.Wrap, fontSize: 16),
+                        textStyle: new TextStyle(fontSize: 16), textWrap: TextWrap.Wrap),
+                    new Text(Body3, TextWrap.Wrap, new TextStyle(fontSize: 16)),
                     new CheckBox(
-                        new Text("The app may be unstable, crash or freeze", fontSize: 16,
-                            fontStyle: FontStyle.Italic),
+                        new Text("The app may be unstable, crash or freeze",
+                            textStyle: new TextStyle(fontStyle: FontStyle.Italic, fontSize: 16)),
                         onCheckedChanged: (args) => CheckboxChanged(args.Sender as CheckBox, 0)),
                     new CheckBox(
-                        new Text("I may encounter unfinished features and placeholders", fontSize: 16,
-                            fontStyle: FontStyle.Italic),
+                        new Text("I may encounter unfinished features and placeholders",
+                            textStyle: new TextStyle(fontSize: 16, fontStyle: FontStyle.Italic)),
                         onCheckedChanged: (args) => CheckboxChanged(args.Sender as CheckBox, 1)),
-                    new CheckBox(new Text("I may lose my work due to bugs", fontSize: 16, fontStyle: FontStyle.Italic),
+                    new CheckBox(new Text("I may lose my work due to bugs",
+                        textStyle: new TextStyle(fontSize: 16, fontStyle: FontStyle.Italic)),
                         onCheckedChanged: (args) => CheckboxChanged(args.Sender as CheckBox, 2)),
                     new CheckBox(
-                        new Text("I will have a lot of fun testing the app", fontSize: 16,
-                            fontStyle: FontStyle.Italic),
+                        new Text("I will have a lot of fun testing the app",
+                            textStyle: new TextStyle(fontSize: 16, fontStyle: FontStyle.Italic)),
                         onCheckedChanged: (args) => CheckboxChanged(args.Sender as CheckBox, 3)),
                     new Container(
                         margin: new Edges(0, 5, 0, 0),

+ 12 - 1
src/PixiEditor.Extensions.CommonApi/FlyUI/Properties/Color.cs

@@ -22,7 +22,7 @@ public struct Color : IStructProperty
 
     byte[] IStructProperty.Serialize()
     {
-        return new byte[] { R, G, B, A };
+        return [R, G, B, A];
     }
 
     void IStructProperty.Deserialize(byte[] data)
@@ -32,4 +32,15 @@ public struct Color : IStructProperty
         B = data[2];
         A = data[3];
     }
+
+    public static Color FromBytes(byte[] data)
+    {
+        if (data.Length < 4)
+        {
+            throw new ArgumentException("Data array must contain at least 4 bytes.");
+        }
+
+
+        return new Color(data[0], data[1], data[2], data[3]);
+    }
 }

+ 0 - 8
src/PixiEditor.Extensions.CommonApi/FlyUI/Properties/FontStyle.cs

@@ -1,8 +0,0 @@
-namespace PixiEditor.Extensions.CommonApi.FlyUI.Properties;
-
-public enum FontStyle
-{
-    Normal,
-    Italic,
-    Oblique
-}

+ 89 - 0
src/PixiEditor.Extensions.CommonApi/FlyUI/Properties/TextStyle.cs

@@ -0,0 +1,89 @@
+using System.Text;
+
+namespace PixiEditor.Extensions.CommonApi.FlyUI.Properties;
+
+public struct TextStyle : IStructProperty
+{
+    // IMPORTANT: If you change this struct, you must also change the version below and handle
+    // deserialization in the FlyUI deserializer.
+    public const int Version = 1;
+    public string FontFamily { get; set; } = "";
+    public double FontSize { get; set; } = 12;
+    public FontStyle FontStyle { get; set; } = FontStyle.Normal;
+    public FontWeight FontWeight { get; set; } = FontWeight.Normal;
+    public Color Color { get; set; } = Colors.White;
+
+    public static TextStyle Default => new TextStyle("", 12, FontStyle.Normal, FontWeight.Normal, Colors.White);
+
+    public TextStyle(string fontFamily = "", double fontSize = 12, FontStyle fontStyle = FontStyle.Normal,
+        FontWeight fontWeight = FontWeight.Normal, Color? color = null)
+    {
+        FontFamily = fontFamily;
+        FontSize = fontSize;
+        FontStyle = fontStyle;
+        FontWeight = fontWeight;
+        Color = color ?? Colors.White;
+    }
+
+    public byte[] Serialize()
+    {
+        var data = new List<byte>();
+        data.AddRange(BitConverter.GetBytes(Version));
+        data.AddRange(BitConverter.GetBytes(FontFamily?.Length ?? 0));
+        if (FontFamily != null)
+        {
+            data.AddRange(Encoding.UTF8.GetBytes(FontFamily));
+        }
+
+        data.AddRange(BitConverter.GetBytes(FontSize));
+        data.Add((byte)FontStyle);
+        data.AddRange(BitConverter.GetBytes((int)FontWeight));
+        data.AddRange(((IStructProperty)Color).Serialize());
+        return data.ToArray();
+    }
+
+    public void Deserialize(byte[] data)
+    {
+        int index = 0;
+        int version = BitConverter.ToInt32(data, index);
+        index += 4;
+        int fontFamilyLength = BitConverter.ToInt32(data, index);
+        index += 4;
+        if (fontFamilyLength > 0)
+        {
+            FontFamily = Encoding.UTF8.GetString(data, index, fontFamilyLength);
+        }
+        else
+        {
+            FontFamily = "$Default";
+        }
+
+        index += fontFamilyLength;
+        FontSize = BitConverter.ToDouble(data, index);
+        index += 8;
+        FontStyle = (FontStyle)data[index++];
+        FontWeight = (FontWeight)BitConverter.ToInt32(data, index);
+        index += 4;
+        Color = Color.FromBytes(data[index..]);
+    }
+}
+
+public enum FontStyle
+{
+    Normal,
+    Italic,
+    Oblique
+}
+
+public enum FontWeight
+{
+    Thin = 100,
+    ExtraLight = 200,
+    Light = 300,
+    Normal = 400,
+    Medium = 500,
+    SemiBold = 600,
+    Bold = 700,
+    ExtraBold = 800,
+    Black = 900
+}

+ 4 - 0
src/PixiEditor.Extensions.CommonApi/Palettes/FilteringSettings.Impl.cs

@@ -2,6 +2,10 @@
 
 public partial class FilteringSettings
 {
+    public FilteringSettings()
+    {
+
+    }
     public FilteringSettings(ColorsNumberMode colorsNumberMode, int colorsCount, string name, bool showOnlyFavourites, List<string> favourites)
     {
         ColorsNumberMode = colorsNumberMode;

+ 2 - 1
src/PixiEditor.Extensions.Sdk/Api/FlyUI/AxisAlignment.cs

@@ -14,5 +14,6 @@ public enum CrossAxisAlignment
 {
     Start,
     Center,
-    End
+    End,
+    Stretch,
 }

+ 6 - 2
src/PixiEditor.Extensions.Sdk/Api/FlyUI/Border.cs

@@ -20,7 +20,8 @@ public class Border : SingleChildLayoutElement
     public double Height { get; set; }
 
     public Border(LayoutElement child = null, Color color = default, Edges thickness = default,
-        Edges cornerRadius = default, Edges padding = default, Edges margin = default, double width = -1, double height = -1,
+        Edges cornerRadius = default, Edges padding = default, Edges margin = default, double width = -1,
+        double height = -1,
         Color backgroundColor = default)
     {
         Child = child;
@@ -37,7 +38,10 @@ public class Border : SingleChildLayoutElement
     public override CompiledControl BuildNative()
     {
         CompiledControl control = new(UniqueId, "Border");
-        control.Children.Add(Child.BuildNative());
+        if (Child != null)
+        {
+            control.Children.Add(Child.BuildNative());
+        }
 
         control.AddProperty(Color);
         control.AddProperty(Thickness);

+ 2 - 4
src/PixiEditor.Extensions.Sdk/Api/FlyUI/Hyperlink.cs

@@ -6,8 +6,7 @@ public class Hyperlink : Text
 {
     public string Url { get; set; }
 
-    public Hyperlink(string url, string text, TextWrap textWrap = TextWrap.None, FontStyle fontStyle = FontStyle.Normal,
-        double fontSize = 12) : base(text, textWrap, fontStyle, fontSize)
+    public Hyperlink(string url, string text, TextWrap textWrap = TextWrap.None, TextStyle? textStyle = null) : base(text, textWrap, textStyle)
     {
         Url = url;
     }
@@ -17,8 +16,7 @@ public class Hyperlink : Text
         CompiledControl hyperlink = new CompiledControl(UniqueId, "Hyperlink");
         hyperlink.AddProperty(Value);
         hyperlink.AddProperty(TextWrap);
-        hyperlink.AddProperty(FontStyle);
-        hyperlink.AddProperty(FontSize);
+        hyperlink.AddProperty(TextStyle);
         hyperlink.AddProperty(Url);
 
         BuildPendingEvents(hyperlink);

+ 29 - 0
src/PixiEditor.Extensions.Sdk/Api/FlyUI/Icon.cs

@@ -0,0 +1,29 @@
+using PixiEditor.Extensions.CommonApi.FlyUI.Properties;
+
+namespace PixiEditor.Extensions.Sdk.Api.FlyUI;
+
+public class Icon : StatelessElement
+{
+    public string IconName { get; set; }
+    public double Size { get; set; } = 16;
+    public Color Color { get; set; } = Colors.White;
+
+    public Icon(string iconName, double size = 16, Color? color = null)
+    {
+        IconName = iconName;
+        Size = size;
+        if (color != null)
+            Color = color.Value;
+    }
+
+    public override CompiledControl BuildNative()
+    {
+        CompiledControl icon = new CompiledControl(UniqueId, "Icon");
+        icon.AddProperty(IconName);
+        icon.AddProperty(Size);
+        icon.AddProperty(Color);
+
+        BuildPendingEvents(icon);
+        return icon;
+    }
+}

+ 5 - 9
src/PixiEditor.Extensions.Sdk/Api/FlyUI/Text.cs

@@ -7,17 +7,14 @@ public class Text : StatelessElement
     public string Value { get; set; }
     
     public TextWrap TextWrap { get; set; }
+
+    public TextStyle TextStyle { get; set; }
     
-    public FontStyle FontStyle { get; set; }
-    
-    public double FontSize { get; set; }
-    
-    public Text(string value, TextWrap wrap = TextWrap.None, FontStyle fontStyle = FontStyle.Normal, double fontSize = 12)
+    public Text(string value, TextWrap wrap = TextWrap.None, TextStyle? textStyle = null)
     {
         Value = value;
         TextWrap = wrap;
-        FontStyle = fontStyle;
-        FontSize = fontSize;
+        TextStyle = textStyle ?? TextStyle.Default;
     }
 
     public override CompiledControl BuildNative()
@@ -25,8 +22,7 @@ public class Text : StatelessElement
         CompiledControl text = new CompiledControl(UniqueId, "Text");
         text.AddProperty(Value);
         text.AddProperty(TextWrap);
-        text.AddProperty(FontStyle);
-        text.AddProperty(FontSize);
+        text.AddProperty(TextStyle);
 
         BuildPendingEvents(text);
         return text;

+ 28 - 0
src/PixiEditor.Extensions/FlyUI/Converters/IconLookupConverter.cs

@@ -0,0 +1,28 @@
+using System.Globalization;
+using Avalonia;
+using Avalonia.Data.Converters;
+
+namespace PixiEditor.Extensions.FlyUI.Converters;
+
+public class IconLookupConverter : IValueConverter
+{
+    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+    {
+        if (value is not string iconName)
+        {
+            return null;
+        }
+
+        if (Application.Current.Styles.TryGetResource(iconName, null, out object resource))
+        {
+            return resource;
+        }
+
+        return iconName;
+    }
+
+    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+    {
+        throw new NotImplementedException();
+    }
+}

+ 3 - 5
src/PixiEditor.Extensions/FlyUI/Elements/Hyperlink.cs

@@ -11,8 +11,7 @@ public class Hyperlink : Text
 {
     public string Url { get; set; }
 
-    public Hyperlink(string text, string url, TextWrap textWrap = TextWrap.None, FontStyle fontStyle = FontStyle.Normal,
-        double fontSize = 12) : base(text, textWrap, fontStyle, fontSize)
+    public Hyperlink(string text, string url, TextWrap textWrap = TextWrap.None, TextStyle textStyle = default) : base(text, textWrap, textStyle)
     {
         Url = url;
     }
@@ -32,14 +31,13 @@ public class Hyperlink : Text
     {
         yield return Value;
         yield return TextWrap;
-        yield return FontStyle;
-        yield return FontSize;
+        yield return TextStyle;
         yield return Url;
     }
 
     public override void DeserializeProperties(ImmutableList<object> values)
     {
         base.DeserializeProperties(values);
-        Url = (string)values[4];
+        Url = (string)values[3];
     }
 }

+ 66 - 0
src/PixiEditor.Extensions/FlyUI/Elements/Icon.cs

@@ -0,0 +1,66 @@
+using System.Collections.Immutable;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data;
+using Avalonia.Markup.Xaml.MarkupExtensions;
+using Avalonia.Media;
+using PixiEditor.Extensions.FlyUI.Converters;
+using Color = PixiEditor.Extensions.CommonApi.FlyUI.Properties.Color;
+using Colors = PixiEditor.Extensions.CommonApi.FlyUI.Properties.Colors;
+
+namespace PixiEditor.Extensions.FlyUI.Elements;
+
+public class Icon : StatelessElement, IPropertyDeserializable
+{
+    private double size = 16;
+    private string iconName = string.Empty;
+    private Color color;
+
+    public double Size { get => size; set => SetField(ref size, value); }
+    public string IconName { get => iconName; set => SetField(ref iconName, value); }
+    public Color Color { get => color; set => SetField(ref color, value); }
+
+    public Icon(string iconName, double size = 16, Color? color = null)
+    {
+        IconName = iconName;
+        Size = size;
+        Color = color ?? Colors.White;
+    }
+
+    public override Control BuildNative()
+    {
+        TextBlock textBlock = new TextBlock();
+        textBlock.Classes.Add("pixi-icon");
+
+        Binding iconNameBinding = new Binding()
+        {
+            Source = this, Path = nameof(IconName),
+            Converter = new IconLookupConverter()
+        };
+        Binding sizeBinding = new Binding() { Source = this, Path = nameof(Size), };
+        Binding colorBinding = new Binding()
+        {
+            Source = this, Path = nameof(Color), Converter = new ColorToAvaloniaBrushConverter()
+        };
+
+        textBlock.Bind(TextBlock.TextProperty, iconNameBinding);
+        textBlock.Bind(TextBlock.FontSizeProperty, sizeBinding);
+        textBlock.Bind(TextBlock.ForegroundProperty, colorBinding);
+
+        return textBlock;
+    }
+
+    public IEnumerable<object> GetProperties()
+    {
+        yield return IconName;
+        yield return Size;
+        yield return Color;
+    }
+
+    public void DeserializeProperties(ImmutableList<object> values)
+    {
+        IconName = (string)values[0];
+        Size = (double)values[1];
+        Color = (Color)values[2];
+    }
+}

+ 3 - 1
src/PixiEditor.Extensions/FlyUI/Elements/MainAxisAlignment.cs

@@ -14,5 +14,7 @@ public enum CrossAxisAlignment
 {
     Start,
     Center,
-    End
+    End,
+    Stretch,
+    //Baseline // Not implemented
 }

+ 33 - 14
src/PixiEditor.Extensions/FlyUI/Elements/Text.cs

@@ -7,6 +7,7 @@ using PixiEditor.Extensions.CommonApi.FlyUI.Properties;
 using PixiEditor.Extensions.Extensions;
 using PixiEditor.Extensions.FlyUI.Converters;
 using FontStyle = PixiEditor.Extensions.CommonApi.FlyUI.Properties.FontStyle;
+using FontWeight = PixiEditor.Extensions.CommonApi.FlyUI.Properties.FontWeight;
 
 namespace PixiEditor.Extensions.FlyUI.Elements;
 
@@ -14,24 +15,21 @@ public class Text : StatelessElement, IPropertyDeserializable
 {
     private TextWrap _textWrap = TextWrap.None;
     private string _value = null!;
-    private FontStyle _fontStyle = FontStyle.Normal;
-    private double _fontSize = 12;
- 
+    private TextStyle textStyle = TextStyle.Default;
+
     public string Value { get => _value; set => SetField(ref _value, value); }
     public TextWrap TextWrap { get => _textWrap; set => SetField(ref _textWrap, value); }
-    public FontStyle FontStyle { get => _fontStyle; set => SetField(ref _fontStyle, value); }
-    public double FontSize { get => _fontSize; set => SetField(ref _fontSize, value); }
 
+    public TextStyle TextStyle { get => textStyle; set => SetField(ref textStyle, value); }
     public Text()
     {
     }
 
-    public Text(string value = "", TextWrap textWrap = TextWrap.None, FontStyle fontStyle = FontStyle.Normal, double fontSize = 12)
+    public Text(string value = "", TextWrap textWrap = TextWrap.None, TextStyle? textStyle = null)
     {
         Value = value;
         TextWrap = textWrap;
-        FontStyle = fontStyle;
-        FontSize = fontSize;
+        TextStyle = textStyle ?? TextStyle.Default;
     }
 
     public override Control BuildNative()
@@ -53,19 +51,42 @@ public class Text : StatelessElement, IPropertyDeserializable
         Binding fontStyleBinding = new()
         {
             Source = this,
-            Path = nameof(FontStyle),
+            Path = "TextStyle.FontStyle",
             Converter = new EnumToEnumConverter<FontStyle, Avalonia.Media.FontStyle>(),
         };
         
         Binding fontSizeBinding = new()
         {
             Source = this,
-            Path = nameof(FontSize),
+            Path = "TextStyle.FontSize",
+        };
+
+        Binding fontWeightBinding = new()
+        {
+            Source = this,
+            Path = "TextStyle.FontWeight",
+            Converter = new EnumToEnumConverter<FontWeight, Avalonia.Media.FontWeight>(),
+        };
+
+        Binding fontFamilyBinding = new()
+        {
+            Source = this,
+            Path = "TextStyle.FontFamily",
+        };
+
+        Binding colorBinding = new()
+        {
+            Source = this,
+            Path = "TextStyle.Color",
+            Converter = new ColorToAvaloniaBrushConverter(),
         };
         
         textBlock.Bind(TextBlock.TextProperty, valueBinding);
         textBlock.Bind(TextBlock.TextWrappingProperty, textWrapBinding);
         textBlock.Bind(TextBlock.FontStyleProperty, fontStyleBinding);
+        textBlock.Bind(TextBlock.ForegroundProperty, colorBinding);
+        textBlock.Bind(TextBlock.FontFamilyProperty, fontFamilyBinding);
+        textBlock.Bind(TextBlock.FontWeightProperty, fontWeightBinding);
         textBlock.Bind(TextBlock.FontSizeProperty, fontSizeBinding);
         return textBlock;
     }
@@ -74,15 +95,13 @@ public class Text : StatelessElement, IPropertyDeserializable
     {
         yield return Value;
         yield return TextWrap;
-        yield return FontStyle;
-        yield return FontSize;
+        yield return TextStyle;
     }
 
     public virtual void DeserializeProperties(ImmutableList<object> values)
     {
         Value = (string)values.ElementAtOrDefault(0);
         TextWrap = (TextWrap)values.ElementAtOrDefault(1);
-        FontStyle = (FontStyle)values.ElementAtOrDefault(2);
-        FontSize = (double)values.ElementAtOrDefault(3, 12.0);
+        TextStyle = (TextStyle)values.ElementAtOrDefault(2, TextStyle.Default);
     }
 }

+ 16 - 1
src/PixiEditor.Extensions/UI/Panels/ColumnPanel.cs

@@ -17,7 +17,15 @@ public class ColumnPanel : Panel
         {
             child.Measure(availableSize);
             size += new Size(0, child.DesiredSize.Height);
-            size = new Size(Math.Max(size.Width, child.DesiredSize.Width), size.Height);
+
+            if (CrossAxisAlignment == CrossAxisAlignment.Stretch)
+            {
+                size = new Size(availableSize.Width, size.Height);
+            }
+            else
+            {
+                size = new Size(Math.Max(size.Width, child.DesiredSize.Width), size.Height);
+            }
         }
 
         if (MainAxisAlignment == MainAxisAlignment.SpaceBetween)
@@ -86,6 +94,13 @@ public class ColumnPanel : Panel
             {
                 xOffset = finalSize.Width - child.DesiredSize.Width;
             }
+            else if (CrossAxisAlignment == CrossAxisAlignment.Stretch)
+            {
+                xOffset = 0;
+                child.Arrange(new Rect(0, yOffset, finalSize.Width, child.DesiredSize.Height));
+                yOffset += child.DesiredSize.Height + spaceBetween;
+                continue;
+            }
 
             child.Arrange(new Rect(xOffset, yOffset, child.DesiredSize.Width, child.DesiredSize.Height));
             yOffset += child.DesiredSize.Height + spaceBetween;

+ 10 - 2
src/PixiEditor.Extensions/UI/Panels/RowPanel.cs

@@ -17,7 +17,15 @@ public class RowPanel : Panel
         {
             child.Measure(availableSize);
             size += new Size(child.DesiredSize.Width, 0);
-            size = new Size(size.Width, Math.Max(size.Height, child.DesiredSize.Height));
+
+            if (CrossAxisAlignment == CrossAxisAlignment.Stretch)
+            {
+                size = new Size(size.Width, availableSize.Height);
+            }
+            else
+            {
+                size = new Size(size.Width, Math.Max(size.Height, child.DesiredSize.Height));
+            }
         }
 
         if (MainAxisAlignment == MainAxisAlignment.SpaceBetween)
@@ -30,7 +38,7 @@ public class RowPanel : Panel
         }
         else if (MainAxisAlignment == MainAxisAlignment.SpaceEvenly)
         {
-            size = new Size (availableSize.Width, size.Height);
+            size = new Size(availableSize.Width, size.Height);
         }
 
         return size;