Browse Source

Fill Mode and Font style

flabbet 1 year ago
parent
commit
b2f5833c84

+ 3 - 3
samples/Sample7_FlyUI/WindowContentElement.cs

@@ -15,15 +15,15 @@ public class WindowContentElement : StatelessElement
                     new Center(
                         new Text(
                             "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae neque nibh. Duis sed pharetra dolor. Donec dui sapien, aliquam id sodales in, ornare et urna. Mauris nunc odio, sagittis eget lectus at, imperdiet ornare quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam euismod pellentesque blandit. Vestibulum sagittis, ligula non finibus lobortis, dolor lacus consectetur turpis, id facilisis ligula dolor vitae augue.",
-                            TextWrap.Wrap)
+                            wrap: TextWrap.Wrap)
                     ),
                     new Align(
                         alignment: Alignment.CenterRight,
-                        child: new Text("- Paulo Coelho, The Alchemist (1233)")
+                        child: new Text("- Paulo Coelho, The Alchemist (1233)", fontStyle: FontStyle.Italic)
                     ),
                     new Container(
                         margin: Edges.Symmetric(25, 0), 
-                        backgroundColor: Color.FromRgba(25, 25, 25, 255), 
+                        backgroundColor: Color.FromRgba(25, 25, 25, 255),
                         child: new Column(
                             new Image("/Pizza.png")))
                 )

+ 9 - 0
src/PixiEditor.Extensions.CommonApi/FlyUI/Properties/FillMode.cs

@@ -0,0 +1,9 @@
+namespace PixiEditor.Extensions.CommonApi.FlyUI.Properties;
+
+public enum FillMode
+{
+    None,
+    Fill,
+    Uniform,
+    UniformToFill,
+}

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

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

+ 2 - 2
src/PixiEditor.Extensions.Wasm/Api/FlyUI/Container.cs

@@ -6,11 +6,11 @@ public class Container : SingleChildLayoutElement
 {
     public Edges Margin { get; set; }
     public Color BackgroundColor { get; set; }
-    
+
     public double Width { get; set; }
     public double Height { get; set; }
 
-    public Container(LayoutElement child = null, Edges margin = default, Color backgroundColor = default, double width = double.NaN, double height = double.NaN)
+    public Container(LayoutElement child = null, Edges margin = default, Color backgroundColor = default, double width = -1, double height = -1)
     {
         Margin = margin;
         BackgroundColor = backgroundColor;

+ 16 - 4
src/PixiEditor.Extensions.Wasm/Api/FlyUI/Image.cs

@@ -1,4 +1,5 @@
-using PixiEditor.Extensions.Wasm.Bridge;
+using PixiEditor.Extensions.CommonApi.FlyUI.Properties;
+using PixiEditor.Extensions.Wasm.Bridge;
 
 namespace PixiEditor.Extensions.Wasm.Api.FlyUI;
 
@@ -21,17 +22,28 @@ public class Image : StatelessElement
             }
         }
     }
-    
-    public Image(string source)
+
+    public double Width { get; set; } 
+    public double Height { get; set; }
+    public FillMode FillMode { get; set; }
+
+    public Image(string source, double width = -1, double height = -1, FillMode fillMode = FillMode.Uniform)
     {
         Source = source;
+        Width = width;
+        Height = height;
+        FillMode = fillMode;
     }
-    
+
     public override CompiledControl BuildNative()
     {
         CompiledControl image = new CompiledControl(UniqueId, "Image");
         
         image.AddStringProperty(Source);
+        image.AddProperty(Width);
+        image.AddProperty(Height);
+        image.AddProperty((int)FillMode);
+        
         BuildPendingEvents(image);
         return image;
     }

+ 13 - 3
src/PixiEditor.Extensions.Wasm/Api/FlyUI/Text.cs

@@ -2,17 +2,27 @@
 
 namespace PixiEditor.Extensions.Wasm.Api.FlyUI;
 
-public class Text(string value, TextWrap wrap = TextWrap.None) : StatelessElement
+public class Text : StatelessElement
 {
-    public string Value { get; set; } = value;
+    public Text(string value, TextWrap wrap = TextWrap.None, FontStyle fontStyle = FontStyle.Normal)
+    {
+        Value = value;
+        TextWrap = wrap;
+        FontStyle = fontStyle;
+    }
+
+    public string Value { get; set; }
+    
+    public TextWrap TextWrap { get; set; }
     
-    public TextWrap TextWrap { get; set; } = wrap;
+    public FontStyle FontStyle { get; set; }
 
     public override CompiledControl BuildNative()
     {
         CompiledControl text = new CompiledControl(UniqueId, "Text");
         text.AddStringProperty(Value);
         text.AddProperty((int)TextWrap);
+        text.AddProperty((int)FontStyle);
 
         BuildPendingEvents(text);
         return text;

+ 28 - 0
src/PixiEditor.Extensions/Extensions/EnumerableExtensions.cs

@@ -0,0 +1,28 @@
+namespace PixiEditor.Extensions.Extensions;
+
+public static class EnumerableExtensions
+{
+    public static T ElementAtOrDefault<T>(this IEnumerable<T> enumerable, int index, T defaultValue)
+    {
+        if (index < 0)
+        {
+            throw new ArgumentOutOfRangeException(nameof(index), "Index must be greater than or equal to 0.");
+        }
+
+        if (enumerable is IList<T> list)
+        {
+            return index < list.Count ? list[index] : defaultValue;
+        }
+
+        using IEnumerator<T> enumerator = enumerable.GetEnumerator();
+        for (int i = 0; i <= index; i++)
+        {
+            if (!enumerator.MoveNext())
+            {
+                return defaultValue;
+            }
+        }
+
+        return enumerator.Current;
+    }
+}

+ 5 - 4
src/PixiEditor.Extensions/FlyUI/Elements/Align.cs

@@ -1,4 +1,5 @@
-using Avalonia.Controls;
+using System.Collections.Immutable;
+using Avalonia.Controls;
 using Avalonia.Layout;
 using PixiEditor.Extensions.CommonApi.FlyUI;
 using PixiEditor.Extensions.CommonApi.FlyUI.Properties;
@@ -64,13 +65,13 @@ public class Align : SingleChildLayoutElement, IPropertyDeserializable
         };
     }
 
-    public void DeserializeProperties(IEnumerable<object> values)
+    public void DeserializeProperties(ImmutableList<object> values)
     {
-        Alignment = (Alignment)(int)values.FirstOrDefault();
+        Alignment = (Alignment)values.FirstOrDefault();
     }
     
     IEnumerable<object> IPropertyDeserializable.GetProperties()
     {
-        yield return (int)Alignment;
+        yield return Alignment;
     }
 }

+ 1 - 2
src/PixiEditor.Extensions/FlyUI/Elements/Column.cs

@@ -29,7 +29,6 @@ public class Column : MultiChildLayoutElement
                 foreach (LayoutElement? item in e.NewItems)
                 {
                     var newChild = item.BuildNative();
-                    DockPanel.SetDock(newChild, Dock.Top);
                     panel.Children.Add(newChild);
                 }
             }
@@ -51,7 +50,7 @@ public class Column : MultiChildLayoutElement
             HorizontalAlignment = HorizontalAlignment.Stretch,
             VerticalAlignment = VerticalAlignment.Stretch
         };
-
+        
         panel.Children.AddRange(Children.Select(x => x.BuildNative()));
 
         return panel;

+ 15 - 8
src/PixiEditor.Extensions/FlyUI/Elements/Container.cs

@@ -1,8 +1,10 @@
-using Avalonia;
+using System.Collections.Immutable;
+using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Data;
 using Avalonia.Layout;
 using PixiEditor.Extensions.CommonApi.FlyUI.Properties;
+using PixiEditor.Extensions.Extensions;
 using PixiEditor.Extensions.FlyUI.Converters;
 
 namespace PixiEditor.Extensions.FlyUI.Elements;
@@ -22,6 +24,8 @@ public class Container : SingleChildLayoutElement, IPropertyDeserializable
     {
         Panel panel = new Panel();
         
+        panel.ClipToBounds = true;
+        
         if(Child != null)
         {
             panel.Children.Add(Child.BuildNative());
@@ -55,8 +59,8 @@ public class Container : SingleChildLayoutElement, IPropertyDeserializable
         
         panel.Bind(Layoutable.MarginProperty, marginBinding);
         panel.Bind(Panel.BackgroundProperty, backgroundColorBinding);
-        panel.Bind(Panel.WidthProperty, widthBinding);
-        panel.Bind(Panel.HeightProperty, heightBinding);
+        panel.Bind(Layoutable.WidthProperty, widthBinding);
+        panel.Bind(Layoutable.HeightProperty, heightBinding);
         
         return panel;
     }
@@ -77,11 +81,14 @@ public class Container : SingleChildLayoutElement, IPropertyDeserializable
         yield return Height;
     }
 
-    public void DeserializeProperties(IEnumerable<object> values)
+    public void DeserializeProperties(ImmutableList<object> values)
     {
-        Margin = new Edges((double)values.ElementAt(0), (double)values.ElementAt(1), (double)values.ElementAt(2), (double)values.ElementAt(3));
-        BackgroundColor = new Color((byte)values.ElementAt(4), (byte)values.ElementAt(5), (byte)values.ElementAt(6), (byte)values.ElementAt(7));
-        Width = (double)values.ElementAt(8);
-        Height = (double)values.ElementAt(9);
+        Margin = new Edges((double)values.ElementAtOrDefault(0), (double)values.ElementAtOrDefault(1), (double)values.ElementAtOrDefault(2), (double)values.ElementAtOrDefault(3));
+        BackgroundColor = new Color((byte)values.ElementAtOrDefault(4), (byte)values.ElementAtOrDefault(5), (byte)values.ElementAtOrDefault(6), (byte)values.ElementAtOrDefault(7));
+        Width = (double)values.ElementAtOrDefault(8, double.NaN);
+        Height = (double)values.ElementAtOrDefault(9, double.NaN);
+        
+        Width = Width < 0 ? double.NaN : Width;
+        Height = Height < 0 ? double.NaN : Height;
     }
 }

+ 51 - 3
src/PixiEditor.Extensions/FlyUI/Elements/Image.cs

@@ -1,6 +1,11 @@
-using Avalonia;
+using System.Collections.Immutable;
+using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Data;
+using Avalonia.Layout;
+using Avalonia.Media;
+using PixiEditor.Extensions.CommonApi.FlyUI.Properties;
+using PixiEditor.Extensions.Extensions;
 using PixiEditor.Extensions.FlyUI.Converters;
 
 namespace PixiEditor.Extensions.FlyUI.Elements;
@@ -8,7 +13,14 @@ namespace PixiEditor.Extensions.FlyUI.Elements;
 public class Image : StatelessElement, IPropertyDeserializable
 {
     private string _source = null!;
+    private double _width = -1;
+    private double _height = -1;
+    private FillMode _fillMode = FillMode.Uniform;
+    
     public string Source { get => _source; set => SetField(ref _source, value); }
+    public double Width { get => _width; set => SetField(ref _width, value); }
+    public double Height { get => _height; set => SetField(ref _height, value); }
+    public FillMode FillMode { get => _fillMode; set => SetField(ref _fillMode, value); }
     
     public override Control BuildNative()
     {
@@ -21,7 +33,29 @@ public class Image : StatelessElement, IPropertyDeserializable
             Converter = new PathToBitmapConverter(),
         };
         
+        Binding widthBinding = new()
+        {
+            Source = this,
+            Path = nameof(Width),
+        };
+        
+        Binding heightBinding = new()
+        {
+            Source = this,
+            Path = nameof(Height),
+        };
+        
+        Binding fillModeBinding = new()
+        {
+            Source = this,
+            Path = nameof(FillMode),
+            Converter = new EnumToEnumConverter<FillMode, Stretch>()
+        };
+        
         image.Bind(Avalonia.Controls.Image.SourceProperty, sourceBinding);
+        image.Bind(Layoutable.WidthProperty, widthBinding);
+        image.Bind(Layoutable.HeightProperty, heightBinding);
+        image.Bind(Avalonia.Controls.Image.StretchProperty, fillModeBinding);
         
         return image;
     }
@@ -30,10 +64,24 @@ public class Image : StatelessElement, IPropertyDeserializable
     public IEnumerable<object> GetProperties()
     {
         yield return Source;
+        
+        yield return Width;
+        yield return Height;
+        
+        yield return (int)FillMode;
     }
 
-    public void DeserializeProperties(IEnumerable<object> values)
+    public void DeserializeProperties(ImmutableList<object> values)
     {
-        Source = (string)values.ElementAt(0);
+        var valuesList = values.ToList();
+        Source = (string)valuesList.ElementAtOrDefault(0);
+        
+        Width = (double)valuesList.ElementAtOrDefault(1, double.NaN);
+        Height = (double)valuesList.ElementAtOrDefault(2, double.NaN);
+        
+        Width = Width < 0 ? double.NaN : Width;
+        Height = Height < 0 ? double.NaN : Height;
+        
+        FillMode = (FillMode)valuesList.ElementAtOrDefault(3, (int)FillMode.Uniform);
     }
 }

+ 3 - 2
src/PixiEditor.Extensions/FlyUI/Elements/LayoutBuilder.cs

@@ -1,4 +1,5 @@
-using System.Text;
+using System.Collections.Immutable;
+using System.Text;
 using Avalonia.Controls;
 using PixiEditor.Extensions.CommonApi.FlyUI;
 using PixiEditor.Extensions.FlyUI.Exceptions;
@@ -98,7 +99,7 @@ public class LayoutBuilder
 
         if (element is IPropertyDeserializable deserializableProperties)
         {
-            deserializableProperties.DeserializeProperties(properties);
+            deserializableProperties.DeserializeProperties(properties.ToImmutableList());
         }
 
         if (element is IChildHost customChildrenDeserializable)

+ 3 - 2
src/PixiEditor.Extensions/FlyUI/Elements/StatefulElement.cs

@@ -1,4 +1,5 @@
-using Avalonia.Controls;
+using System.Collections.Immutable;
+using Avalonia.Controls;
 using Avalonia.Controls.Presenters;
 using PixiEditor.Extensions.CommonApi.FlyUI;
 using PixiEditor.Extensions.CommonApi.FlyUI.State;
@@ -106,7 +107,7 @@ public abstract class StatefulElement<TState> : LayoutElement, /*IPropertyDeseri
         {
             // TODO: Find a way to only apply changed properties, current solution shouldn't be a problem for most cases, but this
             // might cause unnecessary redraws, binding fires and other stuff that might be expensive if we have a lot of elements
-            propertyDeserializable.DeserializeProperties(fromProps.GetProperties());
+            propertyDeserializable.DeserializeProperties(fromProps.GetProperties().ToImmutableList());
         }
     }
 

+ 21 - 7
src/PixiEditor.Extensions/FlyUI/Elements/Text.cs

@@ -1,9 +1,11 @@
-using Avalonia;
+using System.Collections.Immutable;
+using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Data;
 using Avalonia.Media;
 using PixiEditor.Extensions.CommonApi.FlyUI.Properties;
 using PixiEditor.Extensions.FlyUI.Converters;
+using FontStyle = PixiEditor.Extensions.CommonApi.FlyUI.Properties.FontStyle;
 
 namespace PixiEditor.Extensions.FlyUI.Elements;
 
@@ -11,19 +13,21 @@ public class Text : StatelessElement, IPropertyDeserializable
 {
     private TextWrap _textWrap = TextWrap.None;
     private string _value = null!;
+    private FontStyle _fontStyle = FontStyle.Normal;
  
     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 Text()
     {
-
     }
 
-    public Text(string value = "", TextWrap textWrap = TextWrap.None)
+    public Text(string value = "", TextWrap textWrap = TextWrap.None, FontStyle fontStyle = FontStyle.Normal)
     {
         Value = value;
         TextWrap = textWrap;
+        FontStyle = fontStyle;
     }
 
     public override Control BuildNative()
@@ -41,9 +45,17 @@ public class Text : StatelessElement, IPropertyDeserializable
             Path = nameof(TextWrap),
             Converter = new EnumToEnumConverter<TextWrap, TextWrapping>(),
         };
-
+        
+        Binding fontStyleBinding = new()
+        {
+            Source = this,
+            Path = nameof(FontStyle),
+            Converter = new EnumToEnumConverter<FontStyle, Avalonia.Media.FontStyle>(),
+        };
+        
         textBlock.Bind(TextBlock.TextProperty, valueBinding);
         textBlock.Bind(TextBlock.TextWrappingProperty, textWrapBinding);
+        textBlock.Bind(TextBlock.FontStyleProperty, fontStyleBinding);
         return textBlock;
     }
 
@@ -51,11 +63,13 @@ public class Text : StatelessElement, IPropertyDeserializable
     {
         yield return Value;
         yield return TextWrap;
+        yield return FontStyle;
     }
 
-    void IPropertyDeserializable.DeserializeProperties(IEnumerable<object> values)
+    void IPropertyDeserializable.DeserializeProperties(ImmutableList<object> values)
     {
-        Value = (string)values.ElementAt(0);
-        TextWrap = (TextWrap)values.ElementAt(1);
+        Value = (string)values.ElementAtOrDefault(0);
+        TextWrap = (TextWrap)values.ElementAtOrDefault(1);
+        FontStyle = (FontStyle)values.ElementAtOrDefault(2);
     }
 }

+ 4 - 2
src/PixiEditor.Extensions/FlyUI/IPropertyDeserializable.cs

@@ -1,7 +1,9 @@
-namespace PixiEditor.Extensions.FlyUI;
+using System.Collections.Immutable;
+
+namespace PixiEditor.Extensions.FlyUI;
 
 public interface IPropertyDeserializable
 {
     public IEnumerable<object> GetProperties();
-    public void DeserializeProperties(IEnumerable<object> values);
+    public void DeserializeProperties(ImmutableList<object> values);
 }