diff --git a/samples/BindingDemo/App.xaml b/samples/BindingDemo/App.xaml
index 9260dd280f..3e312c8685 100644
--- a/samples/BindingDemo/App.xaml
+++ b/samples/BindingDemo/App.xaml
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="BindingDemo.App">
-
+
-
\ No newline at end of file
+
diff --git a/samples/BindingDemo/BindingDemo.csproj b/samples/BindingDemo/BindingDemo.csproj
index bd6054327f..056d3bf552 100644
--- a/samples/BindingDemo/BindingDemo.csproj
+++ b/samples/BindingDemo/BindingDemo.csproj
@@ -5,7 +5,7 @@
-
+
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 54acdd9114..a43ea4539a 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -9,7 +9,6 @@
1.0
apk
true
- android-arm64;android-x64
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index fab4622303..b228e72f72 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -5,6 +5,13 @@
x:CompileBindings="True"
Name="Avalonia ControlCatalog"
x:Class="ControlCatalog.App">
+
+
+
+
+
+
+
-
diff --git a/samples/ControlCatalog/Pages/ButtonsPage.xaml b/samples/ControlCatalog/Pages/ButtonsPage.xaml
index 059b4d9788..8a474a203d 100644
--- a/samples/ControlCatalog/Pages/ButtonsPage.xaml
+++ b/samples/ControlCatalog/Pages/ButtonsPage.xaml
@@ -90,6 +90,7 @@
+
-
+
Expanded content
-
+
Expanded content
-
+
Expanded content
-
+
Expanded content
-
+ Rounded
+
diff --git a/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs b/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs
index 52166d1a5f..e8a080899a 100644
--- a/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs
@@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
+using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
@@ -8,6 +9,7 @@ namespace ControlCatalog.Pages
public ExpanderPage()
{
this.InitializeComponent();
+ DataContext = new ExpanderPageViewModel();
}
private void InitializeComponent()
diff --git a/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs b/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
index cb79bf219a..f37e0f8701 100644
--- a/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
@@ -90,7 +90,6 @@ namespace ControlCatalog.Pages
private int _vertexBufferObject;
private int _indexBufferObject;
private int _vertexArrayObject;
- private GlExtrasInterface _glExt;
private string GetShader(bool fragment, string shader)
{
@@ -258,7 +257,6 @@ namespace ControlCatalog.Pages
protected unsafe override void OnOpenGlInit(GlInterface GL, int fb)
{
CheckError(GL);
- _glExt = new GlExtrasInterface(GL);
Info = $"Renderer: {GL.GetString(GL_RENDERER)} Version: {GL.GetString(GL_VERSION)}";
@@ -298,8 +296,8 @@ namespace ControlCatalog.Pages
GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, new IntPtr(_indices.Length * sizeof(ushort)), new IntPtr(pdata),
GL_STATIC_DRAW);
CheckError(GL);
- _vertexArrayObject = _glExt.GenVertexArray();
- _glExt.BindVertexArray(_vertexArrayObject);
+ _vertexArrayObject = GL.GenVertexArray();
+ GL.BindVertexArray(_vertexArrayObject);
CheckError(GL);
GL.VertexAttribPointer(positionLocation, 3, GL_FLOAT,
0, vertexSize, IntPtr.Zero);
@@ -316,12 +314,13 @@ namespace ControlCatalog.Pages
// Unbind everything
GL.BindBuffer(GL_ARRAY_BUFFER, 0);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- _glExt.BindVertexArray(0);
+ GL.BindVertexArray(0);
GL.UseProgram(0);
// Delete all resources.
- GL.DeleteBuffers(2, new[] { _vertexBufferObject, _indexBufferObject });
- _glExt.DeleteVertexArrays(1, new[] { _vertexArrayObject });
+ GL.DeleteBuffer(_vertexBufferObject);
+ GL.DeleteBuffer(_indexBufferObject);
+ GL.DeleteVertexArray(_vertexArrayObject);
GL.DeleteProgram(_shaderProgram);
GL.DeleteShader(_fragmentShader);
GL.DeleteShader(_vertexShader);
@@ -338,7 +337,7 @@ namespace ControlCatalog.Pages
GL.BindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);
- _glExt.BindVertexArray(_vertexArrayObject);
+ GL.BindVertexArray(_vertexArrayObject);
GL.UseProgram(_shaderProgram);
CheckError(GL);
var projection =
@@ -369,34 +368,5 @@ namespace ControlCatalog.Pages
if (_disco > 0.01)
Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
}
-
- class GlExtrasInterface : GlInterfaceBase
- {
- public GlExtrasInterface(GlInterface gl) : base(gl.GetProcAddress, gl.ContextInfo)
- {
- }
-
- public delegate void GlDeleteVertexArrays(int count, int[] buffers);
- [GlMinVersionEntryPoint("glDeleteVertexArrays", 3,0)]
- [GlExtensionEntryPoint("glDeleteVertexArraysOES", "GL_OES_vertex_array_object")]
- public GlDeleteVertexArrays DeleteVertexArrays { get; }
-
- public delegate void GlBindVertexArray(int array);
- [GlMinVersionEntryPoint("glBindVertexArray", 3,0)]
- [GlExtensionEntryPoint("glBindVertexArrayOES", "GL_OES_vertex_array_object")]
- public GlBindVertexArray BindVertexArray { get; }
- public delegate void GlGenVertexArrays(int n, int[] rv);
-
- [GlMinVersionEntryPoint("glGenVertexArrays",3,0)]
- [GlExtensionEntryPoint("glGenVertexArraysOES", "GL_OES_vertex_array_object")]
- public GlGenVertexArrays GenVertexArrays { get; }
-
- public int GenVertexArray()
- {
- var rv = new int[1];
- GenVertexArrays(1, rv);
- return rv[0];
- }
- }
}
}
diff --git a/samples/ControlCatalog/Pages/TextBlockPage.xaml b/samples/ControlCatalog/Pages/TextBlockPage.xaml
index cb49ba96c6..32914428ed 100644
--- a/samples/ControlCatalog/Pages/TextBlockPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBlockPage.xaml
@@ -118,7 +118,7 @@
-
+
This is a
TextBlock
with several
diff --git a/samples/ControlCatalog/ViewModels/ExpanderPageViewModel.cs b/samples/ControlCatalog/ViewModels/ExpanderPageViewModel.cs
new file mode 100644
index 0000000000..aa7f710ee0
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/ExpanderPageViewModel.cs
@@ -0,0 +1,27 @@
+using Avalonia;
+using MiniMvvm;
+
+namespace ControlCatalog.ViewModels
+{
+ public class ExpanderPageViewModel : ViewModelBase
+ {
+ private object _cornerRadius = AvaloniaProperty.UnsetValue;
+ private bool _rounded;
+
+ public object CornerRadius
+ {
+ get => _cornerRadius;
+ private set => RaiseAndSetIfChanged(ref _cornerRadius, value);
+ }
+
+ public bool Rounded
+ {
+ get => _rounded;
+ set
+ {
+ if (RaiseAndSetIfChanged(ref _rounded, value))
+ CornerRadius = _rounded ? new CornerRadius(25) : AvaloniaProperty.UnsetValue;
+ }
+ }
+ }
+}
diff --git a/samples/RenderDemo/App.xaml b/samples/RenderDemo/App.xaml
index 66d97a6444..8ea792de19 100644
--- a/samples/RenderDemo/App.xaml
+++ b/samples/RenderDemo/App.xaml
@@ -3,6 +3,12 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
-
+
+
+
+
+
+
+
diff --git a/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml b/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml
index 1d58c465a0..fbc51414e3 100644
--- a/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml
+++ b/samples/SampleControls/HamburgerMenu/HamburgerMenu.xaml
@@ -1,6 +1,6 @@
-
+
@@ -20,25 +20,136 @@
-
- 40
- 220
- 36
- 36
- 32
- 12,0,0,0
- 52,0,0,0
- 212,0,0,0
- 1 1 1 1 #2000, 0 0 1 1 #2fff
- 0 0 1 1 #2000
-
+ 40
+ 220
+ 36
+ 36
+ 32
+ 12,0,0,0
+ 52,0,0,0
+ 212,0,0,0
+ 1 1 1 1 #2000, 0 0 1 1 #2fff
+ 0 0 1 1 #2000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/Avalonia.Base/Input/Cursor.cs b/src/Avalonia.Base/Input/Cursor.cs
index 122838f682..98c4258a90 100644
--- a/src/Avalonia.Base/Input/Cursor.cs
+++ b/src/Avalonia.Base/Input/Cursor.cs
@@ -32,10 +32,7 @@ namespace Avalonia.Input
DragCopy,
DragLink,
None,
-
- [Obsolete("Use BottomSide")]
- BottomSize = BottomSide
-
+
// Not available in GTK directly, see http://www.pixelbeat.org/programming/x_cursors/
// We might enable them later, preferably, by loading pixmax directly from theme with fallback image
// SizeNorthWestSouthEast,
diff --git a/src/Avalonia.Base/Input/DragEventArgs.cs b/src/Avalonia.Base/Input/DragEventArgs.cs
index 22ca8358ff..0e613c0f21 100644
--- a/src/Avalonia.Base/Input/DragEventArgs.cs
+++ b/src/Avalonia.Base/Input/DragEventArgs.cs
@@ -13,9 +13,6 @@ namespace Avalonia.Input
public IDataObject Data { get; private set; }
- [Obsolete("Use KeyModifiers")]
- public InputModifiers Modifiers { get; private set; }
-
public KeyModifiers KeyModifiers { get; private set; }
public Point GetPosition(IVisual relativeTo)
@@ -35,17 +32,6 @@ namespace Avalonia.Input
return point;
}
- [Obsolete("Use constructor taking KeyModifiers")]
- public DragEventArgs(RoutedEvent routedEvent, IDataObject data, Interactive target, Point targetLocation, InputModifiers modifiers)
- : base(routedEvent)
- {
- Data = data;
- _target = target;
- _targetLocation = targetLocation;
- Modifiers = modifiers;
- KeyModifiers = (KeyModifiers)(((int)modifiers) & 0xF);
- }
-
public DragEventArgs(RoutedEvent routedEvent, IDataObject data, Interactive target, Point targetLocation, KeyModifiers keyModifiers)
: base(routedEvent)
{
@@ -53,10 +39,6 @@ namespace Avalonia.Input
_target = target;
_targetLocation = targetLocation;
KeyModifiers = keyModifiers;
-#pragma warning disable CS0618 // Type or member is obsolete
- Modifiers = (InputModifiers)keyModifiers;
-#pragma warning restore CS0618 // Type or member is obsolete
}
-
}
}
diff --git a/src/Avalonia.Base/Input/GotFocusEventArgs.cs b/src/Avalonia.Base/Input/GotFocusEventArgs.cs
index 9d958823fe..5cce138ee0 100644
--- a/src/Avalonia.Base/Input/GotFocusEventArgs.cs
+++ b/src/Avalonia.Base/Input/GotFocusEventArgs.cs
@@ -1,4 +1,3 @@
-using System;
using Avalonia.Interactivity;
namespace Avalonia.Input
@@ -13,16 +12,6 @@ namespace Avalonia.Input
///
public NavigationMethod NavigationMethod { get; set; }
- ///
- /// Gets or sets any input modifiers active at the time of focus.
- ///
- [Obsolete("Use KeyModifiers")]
- public InputModifiers InputModifiers
- {
- get => (InputModifiers)KeyModifiers;
- set => KeyModifiers = (KeyModifiers)((int)value & 0xF);
- }
-
///
/// Gets or sets any key modifiers active at the time of focus.
///
diff --git a/src/Avalonia.Base/Input/IInputRoot.cs b/src/Avalonia.Base/Input/IInputRoot.cs
index 7edc69df52..344a4eefd7 100644
--- a/src/Avalonia.Base/Input/IInputRoot.cs
+++ b/src/Avalonia.Base/Input/IInputRoot.cs
@@ -27,10 +27,5 @@ namespace Avalonia.Input
/// Gets or sets a value indicating whether access keys are shown in the window.
///
bool ShowAccessKeys { get; set; }
-
- ///
- /// Gets associated mouse device
- ///
- IMouseDevice? MouseDevice { get; }
}
}
diff --git a/src/Avalonia.Base/Input/IKeyboardDevice.cs b/src/Avalonia.Base/Input/IKeyboardDevice.cs
index 80aebc02bc..0b7b5aaecc 100644
--- a/src/Avalonia.Base/Input/IKeyboardDevice.cs
+++ b/src/Avalonia.Base/Input/IKeyboardDevice.cs
@@ -4,19 +4,6 @@ using Avalonia.Metadata;
namespace Avalonia.Input
{
- [Flags, Obsolete("Use KeyModifiers and PointerPointProperties")]
- public enum InputModifiers
- {
- None = 0,
- Alt = 1,
- Control = 2,
- Shift = 4,
- Windows = 8,
- LeftMouseButton = 16,
- RightMouseButton = 32,
- MiddleMouseButton = 64
- }
-
[Flags]
public enum KeyModifiers
{
diff --git a/src/Avalonia.Base/Input/IMouseDevice.cs b/src/Avalonia.Base/Input/IMouseDevice.cs
index 2d66397d63..00c436bf21 100644
--- a/src/Avalonia.Base/Input/IMouseDevice.cs
+++ b/src/Avalonia.Base/Input/IMouseDevice.cs
@@ -1,4 +1,3 @@
-using System;
using Avalonia.Metadata;
namespace Avalonia.Input
@@ -9,16 +8,5 @@ namespace Avalonia.Input
[NotClientImplementable]
public interface IMouseDevice : IPointerDevice
{
- ///
- /// Gets the mouse position, in screen coordinates.
- ///
- [Obsolete("Use PointerEventArgs.GetPosition")]
- PixelPoint Position { get; }
-
- [Obsolete]
- void TopLevelClosed(IInputRoot root);
-
- [Obsolete]
- void SceneInvalidated(IInputRoot root, Rect rect);
}
}
diff --git a/src/Avalonia.Base/Input/IPointerDevice.cs b/src/Avalonia.Base/Input/IPointerDevice.cs
index 0993835feb..e0aebda9c5 100644
--- a/src/Avalonia.Base/Input/IPointerDevice.cs
+++ b/src/Avalonia.Base/Input/IPointerDevice.cs
@@ -1,5 +1,3 @@
-using System;
-using Avalonia.VisualTree;
using Avalonia.Input.Raw;
using Avalonia.Metadata;
@@ -8,18 +6,6 @@ namespace Avalonia.Input
[NotClientImplementable]
public interface IPointerDevice : IInputDevice
{
- ///
- [Obsolete("Use IPointer")]
- IInputElement? Captured { get; }
-
- ///
- [Obsolete("Use IPointer")]
- void Capture(IInputElement? control);
-
- ///
- [Obsolete("Use PointerEventArgs.GetPosition")]
- Point GetPosition(IVisual relativeTo);
-
///
/// Gets a pointer for specific event args.
///
diff --git a/src/Avalonia.Base/Input/KeyEventArgs.cs b/src/Avalonia.Base/Input/KeyEventArgs.cs
index 67cd5a520a..b8291e9096 100644
--- a/src/Avalonia.Base/Input/KeyEventArgs.cs
+++ b/src/Avalonia.Base/Input/KeyEventArgs.cs
@@ -9,8 +9,6 @@ namespace Avalonia.Input
public Key Key { get; set; }
- [Obsolete("Use KeyModifiers")]
- public InputModifiers Modifiers => (InputModifiers)KeyModifiers;
public KeyModifiers KeyModifiers { get; set; }
}
}
diff --git a/src/Avalonia.Base/Input/KeyGesture.cs b/src/Avalonia.Base/Input/KeyGesture.cs
index 3b7a828b86..e79e9341a9 100644
--- a/src/Avalonia.Base/Input/KeyGesture.cs
+++ b/src/Avalonia.Base/Input/KeyGesture.cs
@@ -15,13 +15,6 @@ namespace Avalonia.Input
{ "+", Key.OemPlus }, { "-", Key.OemMinus }, { ".", Key.OemPeriod }, { ",", Key.OemComma }
};
- [Obsolete("Use constructor taking KeyModifiers")]
- public KeyGesture(Key key, InputModifiers modifiers)
- {
- Key = key;
- KeyModifiers = (KeyModifiers)(((int)modifiers) & 0xf);
- }
-
public KeyGesture(Key key, KeyModifiers modifiers = KeyModifiers.None)
{
Key = key;
@@ -63,10 +56,7 @@ namespace Avalonia.Input
}
public Key Key { get; }
-
- [Obsolete("Use KeyModifiers")]
- public InputModifiers Modifiers => (InputModifiers)KeyModifiers;
-
+
public KeyModifiers KeyModifiers { get; }
public static KeyGesture Parse(string gesture)
diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs
index 5f8ab24b79..055c9cf1fd 100644
--- a/src/Avalonia.Base/Input/MouseDevice.cs
+++ b/src/Avalonia.Base/Input/MouseDevice.cs
@@ -21,7 +21,6 @@ namespace Avalonia.Input
private readonly Pointer _pointer;
private bool _disposed;
- private PixelPoint? _position;
private MouseButton _lastMouseDownButton;
public MouseDevice(Pointer? pointer = null)
@@ -29,43 +28,6 @@ namespace Avalonia.Input
_pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
}
- [Obsolete("Use IPointer instead")]
- public IInputElement? Captured => _pointer.Captured;
-
- [Obsolete("Use events instead")]
- public PixelPoint Position
- {
- get => _position ?? new PixelPoint(-1, -1);
- protected set => _position = value;
- }
-
- [Obsolete("Use IPointer instead")]
- public void Capture(IInputElement? control)
- {
- _pointer.Capture(control);
- }
-
- ///
- /// Gets the mouse position relative to a control.
- ///
- /// The control.
- /// The mouse position in the control's coordinates.
- public Point GetPosition(IVisual relativeTo)
- {
- relativeTo = relativeTo ?? throw new ArgumentNullException(nameof(relativeTo));
-
- if (relativeTo.VisualRoot == null)
- {
- throw new InvalidOperationException("Control is not attached to visual tree.");
- }
-
-#pragma warning disable CS0618 // Type or member is obsolete
- var rootPoint = relativeTo.VisualRoot.PointToClient(Position);
-#pragma warning restore CS0618 // Type or member is obsolete
- var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo);
- return rootPoint * transform!.Value;
- }
-
public void ProcessRawEvent(RawInputEventArgs e)
{
if (!e.Handled && e is RawPointerEventArgs margs)
@@ -96,7 +58,6 @@ namespace Avalonia.Input
if(mouse._disposed)
return;
- _position = e.Root.PointToScreen(e.Position);
var props = CreateProperties(e);
var keyModifiers = e.InputModifiers.ToKeyModifiers();
switch (e.Type)
@@ -145,7 +106,6 @@ namespace Avalonia.Input
private void LeaveWindow()
{
- _position = null;
}
PointerPointProperties CreateProperties(RawPointerEventArgs args)
@@ -324,19 +284,7 @@ namespace Avalonia.Input
_disposed = true;
_pointer?.Dispose();
}
-
- [Obsolete]
- public void TopLevelClosed(IInputRoot root)
- {
- // no-op
- }
-
- [Obsolete]
- public void SceneInvalidated(IInputRoot root, Rect rect)
- {
- // no-op
- }
-
+
public IPointer? TryGetPointer(RawPointerEventArgs ev)
{
return _pointer;
diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs
index d22b48562c..f5f0e90a45 100644
--- a/src/Avalonia.Base/Input/PenDevice.cs
+++ b/src/Avalonia.Base/Input/PenDevice.cs
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Reactive.Linq;
using Avalonia.Input.Raw;
using Avalonia.Platform;
-using Avalonia.VisualTree;
namespace Avalonia.Input
{
@@ -14,7 +12,6 @@ namespace Avalonia.Input
public class PenDevice : IPenDevice, IDisposable
{
private readonly Dictionary _pointers = new();
- private readonly Dictionary _lastPositions = new();
private int _clickCount;
private Rect _lastClickRect;
private ulong _lastClickTime;
@@ -41,9 +38,7 @@ namespace Avalonia.Input
_pointers[e.RawPointerId] = pointer = new Pointer(Pointer.GetNextFreeId(),
PointerType.Pen, _pointers.Count == 0);
}
-
- _lastPositions[e.RawPointerId] = e.Root.PointToScreen(e.Position);
-
+
var props = new PointerPointProperties(e.InputModifiers, e.Type.ToUpdateKind(),
e.Point.Twist, e.Point.Pressure, e.Point.XTilt, e.Point.YTilt);
var keyModifiers = e.InputModifiers.ToKeyModifiers();
@@ -69,7 +64,6 @@ namespace Avalonia.Input
{
pointer.Dispose();
_pointers.Remove(e.RawPointerId);
- _lastPositions.Remove(e.RawPointerId);
}
}
@@ -153,17 +147,6 @@ namespace Avalonia.Input
p.Dispose();
}
- [Obsolete]
- IInputElement? IPointerDevice.Captured => _pointers.Values
- .FirstOrDefault(p => p.IsPrimary)?.Captured;
-
- [Obsolete]
- void IPointerDevice.Capture(IInputElement? control) => _pointers.Values
- .FirstOrDefault(p => p.IsPrimary)?.Capture(control);
-
- [Obsolete]
- Point IPointerDevice.GetPosition(IVisual relativeTo) => new Point(-1, -1);
-
public IPointer? TryGetPointer(RawPointerEventArgs ev)
{
return _pointers.TryGetValue(ev.RawPointerId, out var pointer)
diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs
index 058c2f9cc1..1f3c726e7b 100644
--- a/src/Avalonia.Base/Input/PointerEventArgs.cs
+++ b/src/Avalonia.Base/Input/PointerEventArgs.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Input
private readonly IVisual? _rootVisual;
private readonly Point _rootVisualPosition;
private readonly PointerPointProperties _properties;
- private Lazy?>? _previousPoints;
+ private readonly Lazy?>? _previousPoints;
public PointerEventArgs(RoutedEvent routedEvent,
IInteractive? source,
@@ -43,29 +43,6 @@ namespace Avalonia.Input
{
_previousPoints = previousPoints;
}
-
-
- class EmulatedDevice : IPointerDevice
- {
- private readonly PointerEventArgs _ev;
-
- public EmulatedDevice(PointerEventArgs ev)
- {
- _ev = ev;
- }
-
- public void ProcessRawEvent(RawInputEventArgs ev) => throw new NotSupportedException();
-
- public IInputElement? Captured => _ev.Pointer.Captured;
- public void Capture(IInputElement? control)
- {
- _ev.Pointer.Capture(control);
- }
-
- public Point GetPosition(IVisual relativeTo) => _ev.GetPosition(relativeTo);
-
- public IPointer? TryGetPointer(RawPointerEventArgs ev) => _ev.Pointer;
- }
///
/// Gets specific pointer generated by input device.
@@ -77,28 +54,6 @@ namespace Avalonia.Input
///
public ulong Timestamp { get; }
- private IPointerDevice? _device;
-
- [Obsolete("Use Pointer to get pointer-specific information")]
- public IPointerDevice Device => _device ?? (_device = new EmulatedDevice(this));
-
- [Obsolete("Use KeyModifiers and PointerPointProperties")]
- public InputModifiers InputModifiers
- {
- get
- {
- var mods = (InputModifiers)KeyModifiers;
- if (_properties.IsLeftButtonPressed)
- mods |= InputModifiers.LeftMouseButton;
- if (_properties.IsMiddleButtonPressed)
- mods |= InputModifiers.MiddleMouseButton;
- if (_properties.IsRightButtonPressed)
- mods |= InputModifiers.RightMouseButton;
-
- return mods;
- }
- }
-
///
/// Gets a value that indicates which key modifiers were active at the time that the pointer event was initiated.
///
@@ -120,9 +75,6 @@ namespace Avalonia.Input
/// The pointer position in the control's coordinates.
public Point GetPosition(IVisual? relativeTo) => GetPosition(_rootVisualPosition, relativeTo);
- [Obsolete("Use GetCurrentPoint")]
- public PointerPoint GetPointerPoint(IVisual? relativeTo) => GetCurrentPoint(relativeTo);
-
///
/// Returns the PointerPoint associated with the current event
///
@@ -171,8 +123,6 @@ namespace Avalonia.Input
public class PointerPressedEventArgs : PointerEventArgs
{
- private readonly int _clickCount;
-
public PointerPressedEventArgs(
IInteractive source,
IPointer pointer,
@@ -184,13 +134,10 @@ namespace Avalonia.Input
: base(InputElement.PointerPressedEvent, source, pointer, rootVisual, rootVisualPosition,
timestamp, properties, modifiers)
{
- _clickCount = clickCount;
+ ClickCount = clickCount;
}
- public int ClickCount => _clickCount;
-
- [Obsolete("Use PointerPressedEventArgs.GetCurrentPoint(this).Properties")]
- public MouseButton MouseButton => Properties.PointerUpdateKind.GetMouseButton();
+ public int ClickCount { get; }
}
public class PointerReleasedEventArgs : PointerEventArgs
@@ -210,9 +157,6 @@ namespace Avalonia.Input
/// Gets the mouse button that triggered the corresponding PointerPressed event
///
public MouseButton InitialPressMouseButton { get; }
-
- [Obsolete("Use InitialPressMouseButton")]
- public MouseButton MouseButton => InitialPressMouseButton;
}
public class PointerCaptureLostEventArgs : RoutedEventArgs
diff --git a/src/Avalonia.Base/Input/PointerOverPreProcessor.cs b/src/Avalonia.Base/Input/PointerOverPreProcessor.cs
index 67d1eea7e3..a95d66346a 100644
--- a/src/Avalonia.Base/Input/PointerOverPreProcessor.cs
+++ b/src/Avalonia.Base/Input/PointerOverPreProcessor.cs
@@ -15,6 +15,8 @@ namespace Avalonia.Input
_inputRoot = inputRoot ?? throw new ArgumentNullException(nameof(inputRoot));
}
+ public PixelPoint? LastPosition => _lastPointer?.position;
+
public void OnCompleted()
{
ClearPointerOver();
diff --git a/src/Avalonia.Base/Input/Raw/RawDragEvent.cs b/src/Avalonia.Base/Input/Raw/RawDragEvent.cs
index 652bad7115..c903aad684 100644
--- a/src/Avalonia.Base/Input/Raw/RawDragEvent.cs
+++ b/src/Avalonia.Base/Input/Raw/RawDragEvent.cs
@@ -8,8 +8,6 @@ namespace Avalonia.Input.Raw
public IDataObject Data { get; }
public DragDropEffects Effects { get; set; }
public RawDragEventType Type { get; }
- [Obsolete("Use KeyModifiers")]
- public InputModifiers Modifiers { get; }
public KeyModifiers KeyModifiers { get; }
public RawDragEvent(IDragDropDevice inputDevice, RawDragEventType type,
@@ -21,9 +19,6 @@ namespace Avalonia.Input.Raw
Data = data;
Effects = effects;
KeyModifiers = modifiers.ToKeyModifiers();
-#pragma warning disable CS0618 // Type or member is obsolete
- Modifiers = (InputModifiers)modifiers;
-#pragma warning restore CS0618 // Type or member is obsolete
}
}
}
diff --git a/src/Avalonia.Base/Input/Raw/RawTouchEventArgs.cs b/src/Avalonia.Base/Input/Raw/RawTouchEventArgs.cs
index 6706a45f48..3e842e6e3f 100644
--- a/src/Avalonia.Base/Input/Raw/RawTouchEventArgs.cs
+++ b/src/Avalonia.Base/Input/Raw/RawTouchEventArgs.cs
@@ -19,8 +19,5 @@ namespace Avalonia.Input.Raw
{
RawPointerId = rawPointerId;
}
-
- [Obsolete("Use RawPointerId")]
- public long TouchPointId { get => RawPointerId; set => RawPointerId = value; }
}
}
diff --git a/src/Avalonia.Base/Input/TouchDevice.cs b/src/Avalonia.Base/Input/TouchDevice.cs
index e914d860fd..1d5b1d6bbf 100644
--- a/src/Avalonia.Base/Input/TouchDevice.cs
+++ b/src/Avalonia.Base/Input/TouchDevice.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.Input.Raw;
using Avalonia.Platform;
-using Avalonia.VisualTree;
namespace Avalonia.Input
{
@@ -20,9 +19,6 @@ namespace Avalonia.Input
private int _clickCount;
private Rect _lastClickRect;
private ulong _lastClickTime;
- private Pointer? _lastPointer;
-
- IInputElement? IPointerDevice.Captured => _lastPointer?.Captured;
RawInputModifiers GetModifiers(RawInputModifiers modifiers, bool isLeftButtonDown)
{
@@ -32,10 +28,6 @@ namespace Avalonia.Input
return rv;
}
- void IPointerDevice.Capture(IInputElement? control) => _lastPointer?.Capture(control);
-
- Point IPointerDevice.GetPosition(IVisual relativeTo) => default;
-
public void ProcessRawEvent(RawInputEventArgs ev)
{
if (ev.Handled || _disposed)
@@ -51,7 +43,6 @@ namespace Avalonia.Input
PointerType.Touch, _pointers.Count == 0);
pointer.Capture(hit);
}
- _lastPointer = pointer;
var target = pointer.Captured ?? args.Root;
var updateKind = args.Type.ToUpdateKind();
@@ -96,7 +87,6 @@ namespace Avalonia.Input
new PointerPointProperties(GetModifiers(args.InputModifiers, false), updateKind),
keyModifier, MouseButton.Left));
}
- _lastPointer = null;
}
if (args.Type == RawPointerEventType.TouchCancel)
@@ -104,7 +94,6 @@ namespace Avalonia.Input
_pointers.Remove(args.RawPointerId);
using (pointer)
pointer.Capture(null);
- _lastPointer = null;
}
if (args.Type == RawPointerEventType.TouchUpdate)
diff --git a/src/Avalonia.Base/Media/GlyphRun.cs b/src/Avalonia.Base/Media/GlyphRun.cs
index ac87d521a5..2a7f3360ad 100644
--- a/src/Avalonia.Base/Media/GlyphRun.cs
+++ b/src/Avalonia.Base/Media/GlyphRun.cs
@@ -445,7 +445,7 @@ namespace Avalonia.Media
///
public int FindGlyphIndex(int characterIndex)
{
- if (GlyphClusters == null)
+ if (GlyphClusters == null || GlyphClusters.Count == 0)
{
return characterIndex;
}
@@ -614,17 +614,29 @@ namespace Avalonia.Media
private GlyphRunMetrics CreateGlyphRunMetrics()
{
+ var firstCluster = 0;
+ var lastCluster = Characters.Length - 1;
+
+ if (!IsLeftToRight)
+ {
+ var cluster = firstCluster;
+ firstCluster = lastCluster;
+ lastCluster = cluster;
+ }
+
if (GlyphClusters != null && GlyphClusters.Count > 0)
{
- var firstCluster = GlyphClusters[0];
+ firstCluster = GlyphClusters[0];
+ lastCluster = GlyphClusters[GlyphClusters.Count - 1];
_offsetToFirstCharacter = Math.Max(0, Characters.Start - firstCluster);
}
+ var isReversed = firstCluster > lastCluster;
var height = (GlyphTypeface.Descent - GlyphTypeface.Ascent + GlyphTypeface.LineGap) * Scale;
var widthIncludingTrailingWhitespace = 0d;
- var trailingWhitespaceLength = GetTrailingWhitespaceLength(out var newLineLength, out var glyphCount);
+ var trailingWhitespaceLength = GetTrailingWhitespaceLength(isReversed, out var newLineLength, out var glyphCount);
for (var index = 0; index < GlyphIndices.Count; index++)
{
@@ -635,16 +647,16 @@ namespace Avalonia.Media
var width = widthIncludingTrailingWhitespace;
- if (IsLeftToRight)
+ if (isReversed)
{
- for (var index = GlyphIndices.Count - glyphCount; index < GlyphIndices.Count; index++)
+ for (var index = 0; index < glyphCount; index++)
{
width -= GetGlyphAdvance(index, out _);
}
}
else
{
- for (var index = 0; index < glyphCount; index++)
+ for (var index = GlyphIndices.Count - glyphCount; index < GlyphIndices.Count; index++)
{
width -= GetGlyphAdvance(index, out _);
}
@@ -654,16 +666,15 @@ namespace Avalonia.Media
height);
}
- private int GetTrailingWhitespaceLength(out int newLineLength, out int glyphCount)
- {
- glyphCount = 0;
- newLineLength = 0;
-
- if (Characters.IsEmpty)
+ private int GetTrailingWhitespaceLength(bool isReversed, out int newLineLength, out int glyphCount)
+ {
+ if (isReversed)
{
- return 0;
+ return GetTralingWhitespaceLengthRightToLeft(out newLineLength, out glyphCount);
}
+ glyphCount = 0;
+ newLineLength = 0;
var trailingWhitespaceLength = 0;
if (GlyphClusters == null)
@@ -732,6 +743,78 @@ namespace Avalonia.Media
return trailingWhitespaceLength;
}
+ private int GetTralingWhitespaceLengthRightToLeft(out int newLineLength, out int glyphCount)
+ {
+ glyphCount = 0;
+ newLineLength = 0;
+ var trailingWhitespaceLength = 0;
+
+ if (GlyphClusters == null)
+ {
+ for (var i = 0; i < Characters.Length;)
+ {
+ var codepoint = Codepoint.ReadAt(_characters, i, out var count);
+
+ if (!codepoint.IsWhiteSpace)
+ {
+ break;
+ }
+
+ if (codepoint.IsBreakChar)
+ {
+ newLineLength++;
+ }
+
+ trailingWhitespaceLength++;
+
+ i += count;
+ glyphCount++;
+ }
+ }
+ else
+ {
+ for (var i = 0; i < GlyphClusters.Count; i++)
+ {
+ var currentCluster = GlyphClusters[i];
+ var characterIndex = Math.Max(0, currentCluster - _characters.BufferOffset);
+ var codepoint = Codepoint.ReadAt(_characters, characterIndex, out _);
+
+ if (!codepoint.IsWhiteSpace)
+ {
+ break;
+ }
+
+ var clusterLength = 1;
+
+ while (i - 1 >= 0)
+ {
+ var nextCluster = GlyphClusters[i - 1];
+
+ if (currentCluster == nextCluster)
+ {
+ clusterLength++;
+ i--;
+
+ continue;
+ }
+
+ break;
+ }
+
+ if (codepoint.IsBreakChar)
+ {
+ newLineLength += clusterLength;
+ }
+
+ trailingWhitespaceLength += clusterLength;
+
+ glyphCount++;
+ }
+ }
+
+ return trailingWhitespaceLength;
+ }
+
private void Set(ref T field, T value)
{
_glyphRunImpl?.Dispose();
diff --git a/src/Avalonia.Base/Media/TextDecoration.cs b/src/Avalonia.Base/Media/TextDecoration.cs
index 8eeb86c555..4c9764af96 100644
--- a/src/Avalonia.Base/Media/TextDecoration.cs
+++ b/src/Avalonia.Base/Media/TextDecoration.cs
@@ -209,7 +209,7 @@ namespace Avalonia.Media
var pen = new Pen(Stroke ?? defaultBrush, thickness,
new DashStyle(StrokeDashArray, StrokeDashOffset), StrokeLineCap);
- drawingContext.DrawLine(pen, origin, origin + new Point(glyphRun.Size.Width, 0));
+ drawingContext.DrawLine(pen, origin, origin + new Point(glyphRun.Metrics.Width, 0));
}
}
}
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs b/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
index f3af240c58..f3e8b5969c 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextLayout.cs
@@ -63,7 +63,7 @@ namespace Avalonia.Media.TextFormatting
MaxHeight = maxHeight;
- MaxLines = maxLines;
+ MaxLines = maxLines;
TextLines = CreateTextLines();
}
@@ -80,7 +80,7 @@ namespace Avalonia.Media.TextFormatting
/// The maximum number of text lines.
public TextLayout(
ITextSource textSource,
- TextParagraphProperties paragraphProperties,
+ TextParagraphProperties paragraphProperties,
TextTrimming? textTrimming = null,
double maxWidth = double.PositiveInfinity,
double maxHeight = double.PositiveInfinity,
@@ -178,24 +178,18 @@ namespace Avalonia.Media.TextFormatting
return new Rect();
}
- if (textPosition < 0 || textPosition >= _textSourceLength)
+ if (textPosition < 0)
{
- var lastLine = TextLines[TextLines.Count - 1];
-
- var lineX = lastLine.Width;
-
- var lineY = Bounds.Bottom - lastLine.Height;
-
- return new Rect(lineX, lineY, 0, lastLine.Height);
+ textPosition = _textSourceLength;
}
var currentY = 0.0;
foreach (var textLine in TextLines)
{
- var end = textLine.FirstTextSourceIndex + textLine.Length - 1;
+ var end = textLine.FirstTextSourceIndex + textLine.Length;
- if (end < textPosition)
+ if (end <= textPosition && end < _textSourceLength)
{
currentY += textLine.Height;
@@ -224,7 +218,7 @@ namespace Avalonia.Media.TextFormatting
}
var result = new List(TextLines.Count);
-
+
var currentY = 0d;
foreach (var textLine in TextLines)
@@ -239,7 +233,7 @@ namespace Avalonia.Media.TextFormatting
var textBounds = textLine.GetTextBounds(start, length);
- if(textBounds.Count > 0)
+ if (textBounds.Count > 0)
{
foreach (var bounds in textBounds)
{
@@ -262,7 +256,7 @@ namespace Avalonia.Media.TextFormatting
}
}
- if(textLine.FirstTextSourceIndex + textLine.Length >= start + length)
+ if (textLine.FirstTextSourceIndex + textLine.Length >= start + length)
{
break;
}
@@ -305,7 +299,7 @@ namespace Avalonia.Media.TextFormatting
return GetHitTestResult(currentLine, characterHit, point);
}
-
+
public int GetLineIndexFromCharacterIndex(int charIndex, bool trailingEdge)
{
if (charIndex < 0)
@@ -327,7 +321,7 @@ namespace Avalonia.Media.TextFormatting
continue;
}
- if (charIndex >= textLine.FirstTextSourceIndex &&
+ if (charIndex >= textLine.FirstTextSourceIndex &&
charIndex <= textLine.FirstTextSourceIndex + textLine.Length - (trailingEdge ? 0 : 1))
{
return index;
@@ -398,7 +392,7 @@ namespace Avalonia.Media.TextFormatting
/// The current left.
/// The current width.
/// The current height.
- private static void UpdateBounds(TextLine textLine,ref double left, ref double width, ref double height)
+ private static void UpdateBounds(TextLine textLine, ref double left, ref double width, ref double height)
{
var lineWidth = textLine.WidthIncludingTrailingWhitespace;
@@ -421,7 +415,7 @@ namespace Avalonia.Media.TextFormatting
{
var textLine = TextFormatterImpl.CreateEmptyTextLine(0, double.PositiveInfinity, _paragraphProperties);
- Bounds = new Rect(0,0,0, textLine.Height);
+ Bounds = new Rect(0, 0, 0, textLine.Height);
return new List { textLine };
}
@@ -439,9 +433,9 @@ namespace Avalonia.Media.TextFormatting
var textLine = TextFormatter.Current.FormatLine(_textSource, _textSourceLength, MaxWidth,
_paragraphProperties, previousLine?.TextLineBreak);
- if(textLine == null || textLine.Length == 0 || textLine.TextRuns.Count == 0 && textLine.TextLineBreak?.TextEndOfLine is TextEndOfParagraph)
+ if (textLine == null || textLine.Length == 0 || textLine.TextRuns.Count == 0 && textLine.TextLineBreak?.TextEndOfLine is TextEndOfParagraph)
{
- if(previousLine != null && previousLine.NewLineLength > 0)
+ if (previousLine != null && previousLine.NewLineLength > 0)
{
var emptyTextLine = TextFormatterImpl.CreateEmptyTextLine(_textSourceLength, MaxWidth, _paragraphProperties);
@@ -454,7 +448,7 @@ namespace Avalonia.Media.TextFormatting
}
_textSourceLength += textLine.Length;
-
+
//Fulfill max height constraint
if (textLines.Count > 0 && !double.IsPositiveInfinity(MaxHeight) && height + textLine.Height > MaxHeight)
{
@@ -485,12 +479,17 @@ namespace Avalonia.Media.TextFormatting
//Fulfill max lines constraint
if (MaxLines > 0 && textLines.Count >= MaxLines)
{
+ if(textLine.TextLineBreak is TextLineBreak lineBreak && lineBreak.RemainingRuns != null)
+ {
+ textLines[textLines.Count - 1] = textLine.Collapse(GetCollapsingProperties(width));
+ }
+
break;
}
}
//Make sure the TextLayout always contains at least on empty line
- if(textLines.Count == 0)
+ if (textLines.Count == 0)
{
var textLine = TextFormatterImpl.CreateEmptyTextLine(0, MaxWidth, _paragraphProperties);
@@ -501,7 +500,7 @@ namespace Avalonia.Media.TextFormatting
Bounds = new Rect(left, 0, width, height);
- if(_paragraphProperties.TextAlignment == TextAlignment.Justify)
+ if (_paragraphProperties.TextAlignment == TextAlignment.Justify)
{
var whitespaceWidth = 0d;
@@ -509,7 +508,7 @@ namespace Avalonia.Media.TextFormatting
{
var lineWhitespaceWidth = line.Width - line.WidthIncludingTrailingWhitespace;
- if(lineWhitespaceWidth > whitespaceWidth)
+ if (lineWhitespaceWidth > whitespaceWidth)
{
whitespaceWidth = lineWhitespaceWidth;
}
@@ -517,7 +516,7 @@ namespace Avalonia.Media.TextFormatting
var justificationWidth = width - whitespaceWidth;
- if(justificationWidth > 0)
+ if (justificationWidth > 0)
{
var justificationProperties = new InterWordJustification(justificationWidth);
diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
index 7c686358e2..f3c62f4994 100644
--- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
+++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
@@ -166,58 +166,74 @@ namespace Avalonia.Media.TextFormatting
if (distance <= 0)
{
- // hit happens before the line, return the first position
var firstRun = _textRuns[0];
- if (firstRun is ShapedTextCharacters shapedTextCharacters)
- {
- return shapedTextCharacters.GlyphRun.GetCharacterHitFromDistance(distance, out _);
- }
+ return GetRunCharacterHit(firstRun, FirstTextSourceIndex, 0);
+ }
- return _resolvedFlowDirection == FlowDirection.LeftToRight ?
- new CharacterHit(FirstTextSourceIndex) :
- new CharacterHit(FirstTextSourceIndex + Length);
+ if (distance > WidthIncludingTrailingWhitespace)
+ {
+ var lastRun = _textRuns[_textRuns.Count - 1];
+
+ return GetRunCharacterHit(lastRun, FirstTextSourceIndex + Length - lastRun.TextSourceLength, lastRun.Size.Width);
}
// process hit that happens within the line
var characterHit = new CharacterHit();
var currentPosition = FirstTextSourceIndex;
+ var currentDistance = 0.0;
foreach (var currentRun in _textRuns)
{
- switch (currentRun)
+ if (currentDistance + currentRun.Size.Width < distance)
{
- case ShapedTextCharacters shapedRun:
- {
- characterHit = shapedRun.GlyphRun.GetCharacterHitFromDistance(distance, out _);
+ currentDistance += currentRun.Size.Width;
+ currentPosition += currentRun.TextSourceLength;
- var offset = Math.Max(0, currentPosition - shapedRun.Text.Start);
+ continue;
+ }
- characterHit = new CharacterHit(characterHit.FirstCharacterIndex + offset, characterHit.TrailingLength);
+ characterHit = GetRunCharacterHit(currentRun, currentPosition, distance - currentDistance);
- break;
- }
- default:
+ break;
+ }
+
+ return characterHit;
+ }
+
+ private static CharacterHit GetRunCharacterHit(DrawableTextRun run, int currentPosition, double distance)
+ {
+ CharacterHit characterHit;
+
+ switch (run)
+ {
+ case ShapedTextCharacters shapedRun:
+ {
+ characterHit = shapedRun.GlyphRun.GetCharacterHitFromDistance(distance, out _);
+
+ var offset = Math.Max(0, currentPosition - shapedRun.Text.Start);
+
+ if (!shapedRun.GlyphRun.IsLeftToRight)
{
- if (distance < currentRun.Size.Width / 2)
- {
- characterHit = new CharacterHit(currentPosition);
- }
- else
- {
- characterHit = new CharacterHit(currentPosition, currentRun.TextSourceLength);
- }
- break;
+ offset = Math.Max(0, offset - shapedRun.Text.End);
}
- }
- if (distance <= currentRun.Size.Width)
- {
- break;
- }
+ characterHit = new CharacterHit(characterHit.FirstCharacterIndex + offset, characterHit.TrailingLength);
- distance -= currentRun.Size.Width;
- currentPosition += currentRun.TextSourceLength;
+ break;
+ }
+ default:
+ {
+ if (distance < run.Size.Width / 2)
+ {
+ characterHit = new CharacterHit(currentPosition);
+ }
+ else
+ {
+ characterHit = new CharacterHit(currentPosition, run.TextSourceLength);
+ }
+ break;
+ }
}
return characterHit;
@@ -226,136 +242,122 @@ namespace Avalonia.Media.TextFormatting
///
public override double GetDistanceFromCharacterHit(CharacterHit characterHit)
{
- var isTrailingHit = characterHit.TrailingLength > 0;
+ var flowDirection = _paragraphProperties.FlowDirection;
var characterIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
- var currentDistance = Start;
var currentPosition = FirstTextSourceIndex;
var remainingLength = characterIndex - FirstTextSourceIndex;
- GlyphRun? lastRun = null;
+ var currentDistance = Start;
- for (var index = 0; index < _textRuns.Count; index++)
+ if (flowDirection == FlowDirection.LeftToRight)
+ {
+ for (var index = 0; index < _textRuns.Count; index++)
+ {
+ var currentRun = _textRuns[index];
+
+ if (TryGetDistanceFromCharacterHit(currentRun, characterHit, currentPosition, remainingLength,
+ flowDirection, out var distance, out _))
+ {
+ return currentDistance + distance;
+ }
+
+ //No hit hit found so we add the full width
+ currentDistance += currentRun.Size.Width;
+ currentPosition += currentRun.TextSourceLength;
+ remainingLength -= currentRun.TextSourceLength;
+ }
+ }
+ else
{
- var textRun = _textRuns[index];
+ currentDistance += WidthIncludingTrailingWhitespace;
- switch (textRun)
+ for (var index = _textRuns.Count - 1; index >= 0; index--)
{
- case ShapedTextCharacters shapedTextCharacters:
- {
- var currentRun = shapedTextCharacters.GlyphRun;
+ var currentRun = _textRuns[index];
- if (lastRun != null)
- {
- if (!lastRun.IsLeftToRight && currentRun.IsLeftToRight &&
- currentRun.Characters.Start == characterHit.FirstCharacterIndex &&
- characterHit.TrailingLength == 0)
- {
- return currentDistance;
- }
- }
+ if (TryGetDistanceFromCharacterHit(currentRun, characterHit, currentPosition, remainingLength,
+ flowDirection, out var distance, out var currentGlyphRun))
+ {
+ if (currentGlyphRun != null)
+ {
+ distance = currentGlyphRun.Size.Width - distance;
+ }
- //Look for a hit in within the current run
- if (currentPosition + remainingLength <= currentPosition + textRun.Text.Length)
- {
- characterHit = new CharacterHit(textRun.Text.Start + remainingLength);
+ return currentDistance - distance;
+ }
- var distance = currentRun.GetDistanceFromCharacterHit(characterHit);
+ //No hit hit found so we add the full width
+ currentDistance -= currentRun.Size.Width;
+ currentPosition += currentRun.TextSourceLength;
+ remainingLength -= currentRun.TextSourceLength;
+ }
+ }
- return currentDistance + distance;
- }
+ return currentDistance;
+ }
- //Look at the left and right edge of the current run
- if (currentRun.IsLeftToRight)
- {
- if (_resolvedFlowDirection == FlowDirection.LeftToRight && (lastRun == null || lastRun.IsLeftToRight))
- {
- if (characterIndex <= currentPosition)
- {
- return currentDistance;
- }
- }
- else
- {
- if (characterIndex == currentPosition)
- {
- return currentDistance;
- }
- }
+ private static bool TryGetDistanceFromCharacterHit(
+ DrawableTextRun currentRun,
+ CharacterHit characterHit,
+ int currentPosition,
+ int remainingLength,
+ FlowDirection flowDirection,
+ out double distance,
+ out GlyphRun? currentGlyphRun)
+ {
+ var characterIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+ var isTrailingHit = characterHit.TrailingLength > 0;
- if (characterIndex == currentPosition + textRun.Text.Length && isTrailingHit)
- {
- return currentDistance + currentRun.Size.Width;
- }
- }
- else
- {
- if (characterIndex == currentPosition)
- {
- return currentDistance + currentRun.Size.Width;
- }
+ distance = 0;
+ currentGlyphRun = null;
- var nextRun = index + 1 < _textRuns.Count ?
- _textRuns[index + 1] as ShapedTextCharacters :
- null;
+ switch (currentRun)
+ {
+ case ShapedTextCharacters shapedTextCharacters:
+ {
+ currentGlyphRun = shapedTextCharacters.GlyphRun;
- if (nextRun != null)
- {
- if (nextRun.ShapedBuffer.IsLeftToRight)
- {
- if (characterIndex == currentPosition + textRun.Text.Length)
- {
- return currentDistance;
- }
- }
- else
- {
- if (currentPosition + nextRun.Text.Length == characterIndex)
- {
- return currentDistance;
- }
- }
- }
- else
- {
- if (characterIndex > currentPosition + textRun.Text.Length)
- {
- return currentDistance;
- }
- }
- }
+ if (currentPosition + remainingLength <= currentPosition + currentRun.Text.Length)
+ {
+ characterHit = new CharacterHit(currentRun.Text.Start + remainingLength);
- lastRun = currentRun;
+ distance = currentGlyphRun.GetDistanceFromCharacterHit(characterHit);
- break;
+ return true;
}
- default:
+
+ if (currentPosition + remainingLength == currentPosition + currentRun.Text.Length && isTrailingHit)
{
- if (characterIndex == currentPosition)
+ if (currentGlyphRun.IsLeftToRight || flowDirection == FlowDirection.RightToLeft)
{
- return currentDistance;
+ distance = currentGlyphRun.Size.Width;
}
- if (characterIndex == currentPosition + textRun.TextSourceLength)
- {
- return currentDistance + textRun.Size.Width;
- }
+ return true;
+ }
- break;
+ break;
+ }
+ default:
+ {
+ if (characterIndex == currentPosition)
+ {
+ return true;
}
- }
- //No hit hit found so we add the full width
- currentDistance += textRun.Size.Width;
- currentPosition += textRun.TextSourceLength;
- remainingLength -= textRun.TextSourceLength;
+ if (characterIndex == currentPosition + currentRun.TextSourceLength)
+ {
+ distance = currentRun.Size.Width;
- if (remainingLength <= 0)
- {
- break;
- }
+ return true;
+
+ }
+
+ break;
+ }
}
- return currentDistance;
+ return false;
}
///
@@ -460,20 +462,33 @@ namespace Avalonia.Media.TextFormatting
var startIndex = currentRun.Text.Start + offset;
- var endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(
- currentShapedRun.ShapedBuffer.IsLeftToRight ?
- new CharacterHit(startIndex + remainingLength) :
- new CharacterHit(startIndex));
+ double startOffset;
+ double endOffset;
- endX += endOffset;
+ if (currentShapedRun.ShapedBuffer.IsLeftToRight)
+ {
+ startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
+
+ endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
+ }
+ else
+ {
+ endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
- var startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(
- currentShapedRun.ShapedBuffer.IsLeftToRight ?
- new CharacterHit(startIndex) :
- new CharacterHit(startIndex + remainingLength));
+ if (currentPosition < startIndex)
+ {
+ startOffset = endOffset;
+ }
+ else
+ {
+ startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
+ }
+ }
startX += startOffset;
+ endX += endOffset;
+
var endHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(endOffset, out _);
var startHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(startOffset, out _);
@@ -504,47 +519,40 @@ namespace Avalonia.Media.TextFormatting
}
//Lines that only contain a linebreak need to be covered here
- if(characterLength == 0)
+ if (characterLength == 0)
{
characterLength = NewLineLength;
}
- var runwidth = endX - startX;
- var currentRunBounds = new TextRunBounds(new Rect(startX, 0, runwidth, Height), currentPosition, characterLength, currentRun);
+ var runWidth = endX - startX;
+ var currentRunBounds = new TextRunBounds(new Rect(startX, 0, runWidth, Height), currentPosition, characterLength, currentRun);
- if (lastDirection == currentDirection && result.Count > 0 && MathUtilities.AreClose(currentRect.Right, startX))
+ if (!MathUtilities.IsZero(runWidth) || NewLineLength > 0)
{
- currentRect = currentRect.WithWidth(currentWidth + runwidth);
+ if (lastDirection == currentDirection && result.Count > 0 && MathUtilities.AreClose(currentRect.Right, startX))
+ {
+ currentRect = currentRect.WithWidth(currentWidth + runWidth);
- var textBounds = result[result.Count - 1];
+ var textBounds = result[result.Count - 1];
- textBounds.Rectangle = currentRect;
+ textBounds.Rectangle = currentRect;
- textBounds.TextRunBounds.Add(currentRunBounds);
- }
- else
- {
- currentRect = currentRunBounds.Rectangle;
+ textBounds.TextRunBounds.Add(currentRunBounds);
+ }
+ else
+ {
+ currentRect = currentRunBounds.Rectangle;
- result.Add(new TextBounds(currentRect, currentDirection, new List { currentRunBounds }));
+ result.Add(new TextBounds(currentRect, currentDirection, new List { currentRunBounds }));
+ }
}
- currentWidth += runwidth;
+ currentWidth += runWidth;
currentPosition += characterLength;
- if (currentDirection == FlowDirection.LeftToRight)
- {
- if (currentPosition > characterIndex)
- {
- break;
- }
- }
- else
+ if (currentPosition > characterIndex)
{
- if (currentPosition <= firstTextSourceIndex)
- {
- break;
- }
+ break;
}
startX = endX;
@@ -571,7 +579,7 @@ namespace Avalonia.Media.TextFormatting
var currentPosition = FirstTextSourceIndex;
var remainingLength = textLength;
- var startX = Start + WidthIncludingTrailingWhitespace;
+ var startX = WidthIncludingTrailingWhitespace;
double currentWidth = 0;
var currentRect = Rect.Empty;
@@ -582,7 +590,7 @@ namespace Avalonia.Media.TextFormatting
continue;
}
- if (currentPosition + currentRun.TextSourceLength <= firstTextSourceIndex)
+ if (currentPosition + currentRun.TextSourceLength < firstTextSourceIndex)
{
startX -= currentRun.Size.Width;
@@ -601,20 +609,31 @@ namespace Avalonia.Media.TextFormatting
currentPosition += offset;
var startIndex = currentRun.Text.Start + offset;
+ double startOffset;
+ double endOffset;
- var endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(
- currentShapedRun.ShapedBuffer.IsLeftToRight ?
- new CharacterHit(startIndex + remainingLength) :
- new CharacterHit(startIndex));
+ if (currentShapedRun.ShapedBuffer.IsLeftToRight)
+ {
+ if (currentPosition < startIndex)
+ {
+ startOffset = endOffset = 0;
+ }
+ else
+ {
+ endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
- endX += endOffset - currentShapedRun.Size.Width;
+ startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
+ }
+ }
+ else
+ {
+ endOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex));
- var startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(
- currentShapedRun.ShapedBuffer.IsLeftToRight ?
- new CharacterHit(startIndex) :
- new CharacterHit(startIndex + remainingLength));
+ startOffset = currentShapedRun.GlyphRun.GetDistanceFromCharacterHit(new CharacterHit(startIndex + remainingLength));
+ }
- startX += startOffset - currentShapedRun.Size.Width;
+ startX -= currentRun.Size.Width - startOffset;
+ endX -= currentRun.Size.Width - endOffset;
var endHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(endOffset, out _);
var startHit = currentShapedRun.GlyphRun.GetCharacterHitFromDistance(startOffset, out _);
@@ -652,41 +671,35 @@ namespace Avalonia.Media.TextFormatting
}
var runWidth = endX - startX;
- var currentRunBounds = new TextRunBounds(new Rect(startX, 0, runWidth, Height), currentPosition, characterLength, currentRun);
- if (lastDirection == currentDirection && result.Count > 0 && MathUtilities.AreClose(currentRect.Right, startX))
+ var currentRunBounds = new TextRunBounds(new Rect(Start + startX, 0, runWidth, Height), currentPosition, characterLength, currentRun);
+
+ if(!MathUtilities.IsZero(runWidth) || NewLineLength > 0)
{
- currentRect = currentRect.WithWidth(currentWidth + runWidth);
+ if (lastDirection == currentDirection && result.Count > 0 && MathUtilities.AreClose(currentRect.Right, Start + startX))
+ {
+ currentRect = currentRect.WithWidth(currentWidth + runWidth);
- var textBounds = result[result.Count - 1];
+ var textBounds = result[result.Count - 1];
- textBounds.Rectangle = currentRect;
+ textBounds.Rectangle = currentRect;
- textBounds.TextRunBounds.Add(currentRunBounds);
- }
- else
- {
- currentRect = currentRunBounds.Rectangle;
+ textBounds.TextRunBounds.Add(currentRunBounds);
+ }
+ else
+ {
+ currentRect = currentRunBounds.Rectangle;
- result.Add(new TextBounds(currentRect, currentDirection, new List { currentRunBounds }));
- }
+ result.Add(new TextBounds(currentRect, currentDirection, new List { currentRunBounds }));
+ }
+ }
currentWidth += runWidth;
currentPosition += characterLength;
- if (currentDirection == FlowDirection.LeftToRight)
- {
- if (currentPosition > characterIndex)
- {
- break;
- }
- }
- else
+ if (currentPosition > characterIndex)
{
- if (currentPosition <= firstTextSourceIndex)
- {
- break;
- }
+ break;
}
lastDirection = currentDirection;
@@ -698,6 +711,8 @@ namespace Avalonia.Media.TextFormatting
}
}
+ result.Reverse();
+
return result;
}
@@ -1302,8 +1317,14 @@ namespace Avalonia.Media.TextFormatting
switch (textAlignment)
{
case TextAlignment.Center:
- return Math.Max(0, (_paragraphWidth - width) / 2);
+ var start = (_paragraphWidth - width) / 2;
+
+ if(paragraphFlowDirection == FlowDirection.RightToLeft)
+ {
+ start -= (widthIncludingTrailingWhitespace - width);
+ }
+ return Math.Max(0, start);
case TextAlignment.Right:
return Math.Max(0, _paragraphWidth - widthIncludingTrailingWhitespace);
diff --git a/src/Markup/Avalonia.Markup.Xaml/IAddChild.cs b/src/Avalonia.Base/Metadata/IAddChild.cs
similarity index 61%
rename from src/Markup/Avalonia.Markup.Xaml/IAddChild.cs
rename to src/Avalonia.Base/Metadata/IAddChild.cs
index 993eb6142d..8ef02912a6 100644
--- a/src/Markup/Avalonia.Markup.Xaml/IAddChild.cs
+++ b/src/Avalonia.Base/Metadata/IAddChild.cs
@@ -1,11 +1,11 @@
-namespace Avalonia.Markup.Xaml
+namespace Avalonia.Metadata
{
public interface IAddChild
{
void AddChild(object child);
}
- public interface IAddChild : IAddChild
+ public interface IAddChild
{
void AddChild(T child);
}
diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs
index f98d2cdbcc..3a42e9bdfe 100644
--- a/src/Avalonia.Base/StyledElement.cs
+++ b/src/Avalonia.Base/StyledElement.cs
@@ -12,8 +12,6 @@ using Avalonia.Logging;
using Avalonia.LogicalTree;
using Avalonia.Styling;
-#nullable enable
-
namespace Avalonia
{
///
@@ -55,7 +53,14 @@ namespace Avalonia
nameof(TemplatedParent),
o => o.TemplatedParent,
(o ,v) => o.TemplatedParent = v);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty ThemeProperty =
+ AvaloniaProperty.Register(nameof(Theme));
+ private static readonly ControlTheme s_invalidTheme = new ControlTheme();
private int _initCount;
private string? _name;
private readonly Classes _classes = new Classes();
@@ -67,6 +72,8 @@ namespace Avalonia
private List? _appliedStyles;
private ITemplatedControl? _templatedParent;
private bool _dataContextUpdating;
+ private bool _hasPromotedTheme;
+ private ControlTheme? _implicitTheme;
///
/// Initializes static members of the class.
@@ -230,6 +237,15 @@ namespace Avalonia
internal set => SetAndRaise(TemplatedParentProperty, ref _templatedParent, value);
}
+ ///
+ /// Gets or sets the theme to be applied to the element.
+ ///
+ public ControlTheme? Theme
+ {
+ get => GetValue(ThemeProperty);
+ set => SetValue(ThemeProperty, value);
+ }
+
///
/// Gets the styled element's logical children.
///
@@ -302,6 +318,7 @@ namespace Avalonia
///
IStyleHost? IStyleHost.StylingParent => (IStyleHost?)InheritanceParent;
+
///
public virtual void BeginInit()
{
@@ -341,10 +358,15 @@ namespace Avalonia
}
finally
{
+ _styled = true;
EndBatchUpdate();
}
- _styled = true;
+ if (_hasPromotedTheme)
+ {
+ _hasPromotedTheme = false;
+ ClearValue(ThemeProperty);
+ }
}
return _styled;
@@ -475,6 +497,31 @@ namespace Avalonia
};
}
+ ControlTheme? IStyleable.GetEffectiveTheme()
+ {
+ var theme = Theme;
+
+ // Explitly set Theme property takes precedence.
+ if (theme is not null)
+ return theme;
+
+ // If the Theme property is not set, try to find a ControlTheme resource with our StyleKey.
+ if (_implicitTheme is null)
+ {
+ var key = ((IStyleable)this).StyleKey;
+
+ if (this.TryFindResource(key, out var value) && value is ControlTheme t)
+ _implicitTheme = t;
+ else
+ _implicitTheme = s_invalidTheme;
+ }
+
+ if (_implicitTheme != s_invalidTheme)
+ return _implicitTheme;
+
+ return null;
+ }
+
void IStyleable.StyleApplied(IStyleInstance instance)
{
instance = instance ?? throw new ArgumentNullException(nameof(instance));
@@ -590,6 +637,30 @@ namespace Avalonia
{
}
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == ThemeProperty)
+ {
+ // Changing the theme detaches all styles, meaning that if the theme property was
+ // set via a style, it will get cleared! To work around this, if the value was
+ // applied at less than local value priority then promote the value to local value
+ // priority until styling is re-applied.
+ if (change.Priority > BindingPriority.LocalValue)
+ {
+ Theme = change.GetNewValue();
+ _hasPromotedTheme = true;
+ }
+ else if (_hasPromotedTheme && change.Priority == BindingPriority.LocalValue)
+ {
+ _hasPromotedTheme = false;
+ }
+
+ InvalidateStyles();
+ }
+ }
+
private static void DataContextNotifying(IAvaloniaObject o, bool updateStarted)
{
if (o is StyledElement element)
@@ -696,6 +767,7 @@ namespace Avalonia
if (_logicalRoot != null)
{
_logicalRoot = null;
+ _implicitTheme = null;
DetachStyles();
OnDetachedFromLogicalTree(e);
DetachedFromLogicalTree?.Invoke(this, e);
@@ -760,7 +832,7 @@ namespace Avalonia
private void DetachStyles()
{
- if (_appliedStyles is object)
+ if (_appliedStyles?.Count > 0)
{
BeginBatchUpdate();
@@ -801,9 +873,12 @@ namespace Avalonia
if (applied.Source == styles[i])
{
- applied.Dispose();
_appliedStyles.RemoveAt(j);
+ applied.Dispose();
}
+
+ if (j > _appliedStyles.Count)
+ j = _appliedStyles.Count;
}
}
}
diff --git a/src/Avalonia.Base/Styling/ChildSelector.cs b/src/Avalonia.Base/Styling/ChildSelector.cs
index 34f3a76b61..9512dc34df 100644
--- a/src/Avalonia.Base/Styling/ChildSelector.cs
+++ b/src/Avalonia.Base/Styling/ChildSelector.cs
@@ -65,6 +65,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
- internal override bool HasValidNestingSelector() => _parent.HasValidNestingSelector();
+ protected override Selector? MovePreviousOrParent() => _parent;
}
}
diff --git a/src/Avalonia.Base/Styling/ControlTheme.cs b/src/Avalonia.Base/Styling/ControlTheme.cs
new file mode 100644
index 0000000000..644e8b32d4
--- /dev/null
+++ b/src/Avalonia.Base/Styling/ControlTheme.cs
@@ -0,0 +1,67 @@
+using System;
+
+namespace Avalonia.Styling
+{
+ ///
+ /// Defines a switchable theme for a control.
+ ///
+ public class ControlTheme : StyleBase
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ControlTheme() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value for .
+ public ControlTheme(Type targetType) => TargetType = targetType;
+
+ ///
+ /// Gets or sets the type for which this control theme is intended.
+ ///
+ public Type? TargetType { get; set; }
+
+ ///
+ /// Gets or sets a control theme that is the basis of the current theme.
+ ///
+ public ControlTheme? BasedOn { get; set; }
+
+ public override SelectorMatchResult TryAttach(IStyleable target, object? host)
+ {
+ _ = target ?? throw new ArgumentNullException(nameof(target));
+
+ if (TargetType is null)
+ throw new InvalidOperationException("ControlTheme has no TargetType.");
+
+ var result = BasedOn?.TryAttach(target, host) ?? SelectorMatchResult.NeverThisType;
+
+ if (HasSettersOrAnimations && TargetType.IsAssignableFrom(target.StyleKey))
+ {
+ Attach(target, null);
+ result = SelectorMatchResult.AlwaysThisType;
+ }
+
+ var childResult = TryAttachChildren(target, host);
+
+ if (childResult > result)
+ result = childResult;
+
+ return result;
+ }
+
+ public override string ToString()
+ {
+ if (TargetType is not null)
+ return "ControlTheme: " + TargetType.Name;
+ else
+ return "ControlTheme";
+ }
+
+ internal override void SetParent(StyleBase? parent)
+ {
+ throw new InvalidOperationException("ControlThemes cannot be added as a nested style.");
+ }
+ }
+}
diff --git a/src/Avalonia.Base/Styling/DescendentSelector.cs b/src/Avalonia.Base/Styling/DescendentSelector.cs
index 4ffaff6861..677a924189 100644
--- a/src/Avalonia.Base/Styling/DescendentSelector.cs
+++ b/src/Avalonia.Base/Styling/DescendentSelector.cs
@@ -70,6 +70,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
- internal override bool HasValidNestingSelector() => _parent.HasValidNestingSelector();
+ protected override Selector? MovePreviousOrParent() => _parent;
}
}
diff --git a/src/Avalonia.Base/Styling/IStyle.cs b/src/Avalonia.Base/Styling/IStyle.cs
index e9faf82c07..417739fb28 100644
--- a/src/Avalonia.Base/Styling/IStyle.cs
+++ b/src/Avalonia.Base/Styling/IStyle.cs
@@ -23,6 +23,6 @@ namespace Avalonia.Styling
///
/// A describing how the style matches the control.
///
- SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host);
+ SelectorMatchResult TryAttach(IStyleable target, object? host);
}
}
diff --git a/src/Avalonia.Base/Styling/IStyleable.cs b/src/Avalonia.Base/Styling/IStyleable.cs
index 5bc972e7ab..254da4d85c 100644
--- a/src/Avalonia.Base/Styling/IStyleable.cs
+++ b/src/Avalonia.Base/Styling/IStyleable.cs
@@ -3,8 +3,6 @@ using System.Collections.Generic;
using Avalonia.Collections;
using Avalonia.Metadata;
-#nullable enable
-
namespace Avalonia.Styling
{
///
@@ -28,6 +26,11 @@ namespace Avalonia.Styling
///
ITemplatedControl? TemplatedParent { get; }
+ ///
+ /// Gets the effective theme for the control as used by the syling system.
+ ///
+ ControlTheme? GetEffectiveTheme();
+
///
/// Notifies the element that a style has been applied.
///
diff --git a/src/Avalonia.Base/Styling/NestingSelector.cs b/src/Avalonia.Base/Styling/NestingSelector.cs
index 481a937867..77c5b719c6 100644
--- a/src/Avalonia.Base/Styling/NestingSelector.cs
+++ b/src/Avalonia.Base/Styling/NestingSelector.cs
@@ -15,9 +15,17 @@ namespace Avalonia.Styling
protected override SelectorMatch Evaluate(IStyleable control, IStyle? parent, bool subscribe)
{
- if (parent is Style s && s.Selector is Selector selector)
+ if (parent is Style s && s.Selector is not null)
{
- return selector.Match(control, (parent as Style)?.Parent, subscribe);
+ return s.Selector.Match(control, s.Parent, subscribe);
+ }
+ else if (parent is ControlTheme theme)
+ {
+ if (theme.TargetType is null)
+ throw new InvalidOperationException("ControlTheme has no TargetType.");
+ return theme.TargetType.IsAssignableFrom(control.StyleKey) ?
+ SelectorMatch.AlwaysThisType :
+ SelectorMatch.NeverThisType;
}
throw new InvalidOperationException(
@@ -25,6 +33,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
- internal override bool HasValidNestingSelector() => true;
+ protected override Selector? MovePreviousOrParent() => null;
}
}
diff --git a/src/Avalonia.Base/Styling/NotSelector.cs b/src/Avalonia.Base/Styling/NotSelector.cs
index cdc3254d38..c7727bb6b8 100644
--- a/src/Avalonia.Base/Styling/NotSelector.cs
+++ b/src/Avalonia.Base/Styling/NotSelector.cs
@@ -67,6 +67,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
- internal override bool HasValidNestingSelector() => _argument.HasValidNestingSelector();
+ protected override Selector? MovePreviousOrParent() => _previous;
}
}
diff --git a/src/Avalonia.Base/Styling/NthChildSelector.cs b/src/Avalonia.Base/Styling/NthChildSelector.cs
index 047bf434da..f473791664 100644
--- a/src/Avalonia.Base/Styling/NthChildSelector.cs
+++ b/src/Avalonia.Base/Styling/NthChildSelector.cs
@@ -105,7 +105,7 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
- internal override bool HasValidNestingSelector() => _previous?.HasValidNestingSelector() ?? false;
+ protected override Selector? MovePreviousOrParent() => _previous;
public override string ToString()
{
diff --git a/src/Avalonia.Base/Styling/OrSelector.cs b/src/Avalonia.Base/Styling/OrSelector.cs
index 913c27bf0c..af9249864f 100644
--- a/src/Avalonia.Base/Styling/OrSelector.cs
+++ b/src/Avalonia.Base/Styling/OrSelector.cs
@@ -103,18 +103,12 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
+ protected override Selector? MovePreviousOrParent() => null;
- internal override bool HasValidNestingSelector()
+ internal override void ValidateNestingSelector(bool inControlTheme)
{
foreach (var selector in _selectors)
- {
- if (!selector.HasValidNestingSelector())
- {
- return false;
- }
- }
-
- return true;
+ selector.ValidateNestingSelector(inControlTheme);
}
private Type? EvaluateTargetType()
diff --git a/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs b/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs
index 7a37daf087..48136ba2de 100644
--- a/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs
+++ b/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs
@@ -90,7 +90,7 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
- internal override bool HasValidNestingSelector() => _previous?.HasValidNestingSelector() ?? false;
+ protected override Selector? MovePreviousOrParent() => _previous;
internal static bool Compare(Type propertyType, object? propertyValue, object? value)
{
diff --git a/src/Avalonia.Base/Styling/Selector.cs b/src/Avalonia.Base/Styling/Selector.cs
index 1e06f3d375..7ce17518dd 100644
--- a/src/Avalonia.Base/Styling/Selector.cs
+++ b/src/Avalonia.Base/Styling/Selector.cs
@@ -86,7 +86,36 @@ namespace Avalonia.Styling
///
protected abstract Selector? MovePrevious();
- internal abstract bool HasValidNestingSelector();
+ ///
+ /// Moves to the previous selector or the parent selector.
+ ///
+ protected abstract Selector? MovePreviousOrParent();
+
+ internal virtual void ValidateNestingSelector(bool inControlTheme)
+ {
+ var s = this;
+ var templateCount = 0;
+
+ do
+ {
+ if (inControlTheme)
+ {
+ if (!s.InTemplate && s.IsCombinator)
+ throw new InvalidOperationException(
+ "ControlTheme style may not directly contain a child or descendent selector.");
+ if (s is TemplateSelector && templateCount++ > 0)
+ throw new InvalidOperationException(
+ "ControlTemplate styles cannot contain multiple template selectors.");
+ }
+
+ var previous = s.MovePreviousOrParent();
+
+ if (previous is null && s is not NestingSelector)
+ throw new InvalidOperationException("Child styles must have a nesting selector.");
+
+ s = previous;
+ } while (s is not null);
+ }
private static SelectorMatch MatchUntilCombinator(
IStyleable control,
diff --git a/src/Avalonia.Base/Styling/Style.cs b/src/Avalonia.Base/Styling/Style.cs
index 000e588bad..c61b08b2a1 100644
--- a/src/Avalonia.Base/Styling/Style.cs
+++ b/src/Avalonia.Base/Styling/Style.cs
@@ -1,22 +1,13 @@
using System;
-using System.Collections.Generic;
-using Avalonia.Animation;
-using Avalonia.Controls;
-using Avalonia.Metadata;
namespace Avalonia.Styling
{
///
/// Defines a style.
///
- public class Style : AvaloniaObject, IStyle, IResourceProvider
+ public class Style : StyleBase
{
- private IResourceHost? _owner;
- private StyleChildren? _children;
- private IResourceDictionary? _resources;
- private List? _setters;
- private List? _animations;
- private StyleCache? _childCache;
+ private Selector? _selector;
///
/// Initializes a new instance of the class.
@@ -35,113 +26,41 @@ namespace Avalonia.Styling
}
///
- /// Gets the children of the style.
- ///
- public IList Children => _children ??= new(this);
-
- ///
- /// Gets the or Application that hosts the style.
+ /// Gets or sets the style's selector.
///
- public IResourceHost? Owner
+ public Selector? Selector
{
- get => _owner;
- private set
- {
- if (_owner != value)
- {
- _owner = value;
- OwnerChanged?.Invoke(this, EventArgs.Empty);
- }
- }
+ get => _selector;
+ set => _selector = ValidateSelector(value);
}
- ///
- /// Gets the parent style if this style is hosted in a collection.
- ///
- public Style? Parent { get; private set; }
-
- ///
- /// Gets or sets a dictionary of style resources.
- ///
- public IResourceDictionary Resources
+ public override SelectorMatchResult TryAttach(IStyleable target, object? host)
{
- get => _resources ?? (Resources = new ResourceDictionary());
- set
- {
- value = value ?? throw new ArgumentNullException(nameof(value));
-
- var hadResources = _resources?.HasResources ?? false;
-
- _resources = value;
-
- if (Owner is object)
- {
- _resources.AddOwner(Owner);
-
- if (hadResources || _resources.HasResources)
- {
- Owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
- }
- }
- }
- }
-
- ///
- /// Gets or sets the style's selector.
- ///
- public Selector? Selector { get; set; }
-
- ///
- /// Gets the style's setters.
- ///
- public IList Setters => _setters ??= new List();
-
- ///
- /// Gets the style's animations.
- ///
- public IList Animations => _animations ??= new List();
-
- bool IResourceNode.HasResources => _resources?.Count > 0;
- IReadOnlyList IStyle.Children => (IReadOnlyList?)_children ?? Array.Empty();
+ _ = target ?? throw new ArgumentNullException(nameof(target));
- public event EventHandler? OwnerChanged;
+ var result = SelectorMatchResult.NeverThisType;
- public void Add(ISetter setter) => Setters.Add(setter);
- public void Add(IStyle style) => Children.Add(style);
-
- public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)
- {
- target = target ?? throw new ArgumentNullException(nameof(target));
+ if (HasSettersOrAnimations)
+ {
+ var match = Selector?.Match(target, Parent, true) ??
+ (target == host ?
+ SelectorMatch.AlwaysThisInstance :
+ SelectorMatch.NeverThisInstance);
- var match = Selector is object ? Selector.Match(target, Parent) :
- target == host ? SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance;
+ if (match.IsMatch)
+ Attach(target, match.Activator);
- if (match.IsMatch && (_setters is object || _animations is object))
- {
- var instance = new StyleInstance(this, target, _setters, _animations, match.Activator);
- target.StyleApplied(instance);
- instance.Start();
+ result = match.Result;
}
- var result = match.Result;
+ var childResult = TryAttachChildren(target, host);
- if (_children is not null)
- {
- _childCache ??= new StyleCache();
- var childResult = _childCache.TryAttach(_children, target, host);
- if (childResult > result)
- result = childResult;
- }
+ if (childResult > result)
+ result = childResult;
return result;
}
- public bool TryGetResource(object key, out object? result)
- {
- result = null;
- return _resources?.TryGetResource(key, out result) ?? false;
- }
-
///
/// Returns a string representation of the style.
///
@@ -158,41 +77,30 @@ namespace Avalonia.Styling
}
}
- void IResourceProvider.AddOwner(IResourceHost owner)
+ internal override void SetParent(StyleBase? parent)
{
- owner = owner ?? throw new ArgumentNullException(nameof(owner));
-
- if (Owner != null)
+ if (parent is Style parentStyle && parentStyle.Selector is not null)
{
- throw new InvalidOperationException("The Style already has a parent.");
- }
-
- Owner = owner;
- _resources?.AddOwner(owner);
- }
-
- void IResourceProvider.RemoveOwner(IResourceHost owner)
- {
- owner = owner ?? throw new ArgumentNullException(nameof(owner));
-
- if (Owner == owner)
- {
- Owner = null;
- _resources?.RemoveOwner(owner);
+ if (Selector is null)
+ throw new InvalidOperationException("Child styles must have a selector.");
+ Selector.ValidateNestingSelector(false);
}
- }
-
- internal void SetParent(Style? parent)
- {
- if (parent?.Selector is not null)
+ else if (parent is ControlTheme)
{
if (Selector is null)
throw new InvalidOperationException("Child styles must have a selector.");
- if (!Selector.HasValidNestingSelector())
- throw new InvalidOperationException("Child styles must have a nesting selector.");
+ Selector.ValidateNestingSelector(true);
}
- Parent = parent;
+ base.SetParent(parent);
+ }
+
+ private static Selector? ValidateSelector(Selector? selector)
+ {
+ if (selector is TemplateSelector)
+ throw new InvalidOperationException(
+ "Invalid selector: Template selector must be followed by control selector.");
+ return selector;
}
}
}
diff --git a/src/Avalonia.Base/Styling/StyleBase.cs b/src/Avalonia.Base/Styling/StyleBase.cs
new file mode 100644
index 0000000000..306a4cf010
--- /dev/null
+++ b/src/Avalonia.Base/Styling/StyleBase.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Animation;
+using Avalonia.Controls;
+using Avalonia.Metadata;
+using Avalonia.Styling.Activators;
+
+namespace Avalonia.Styling
+{
+ ///
+ /// Base class for and .
+ ///
+ public abstract class StyleBase : AvaloniaObject, IStyle, IResourceProvider
+ {
+ private IResourceHost? _owner;
+ private StyleChildren? _children;
+ private IResourceDictionary? _resources;
+ private List? _setters;
+ private List? _animations;
+ private StyleCache? _childCache;
+
+ public IList Children => _children ??= new(this);
+
+ public IResourceHost? Owner
+ {
+ get => _owner;
+ private set
+ {
+ if (_owner != value)
+ {
+ _owner = value;
+ OwnerChanged?.Invoke(this, EventArgs.Empty);
+ }
+ }
+ }
+
+ public IStyle? Parent { get; private set; }
+
+ public IResourceDictionary Resources
+ {
+ get => _resources ?? (Resources = new ResourceDictionary());
+ set
+ {
+ value = value ?? throw new ArgumentNullException(nameof(value));
+
+ var hadResources = _resources?.HasResources ?? false;
+
+ _resources = value;
+
+ if (Owner is object)
+ {
+ _resources.AddOwner(Owner);
+
+ if (hadResources || _resources.HasResources)
+ {
+ Owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
+ }
+ }
+ }
+ }
+
+ public IList Setters => _setters ??= new List();
+ public IList Animations => _animations ??= new List();
+
+ bool IResourceNode.HasResources => _resources?.Count > 0;
+ IReadOnlyList IStyle.Children => (IReadOnlyList?)_children ?? Array.Empty();
+
+ internal bool HasSettersOrAnimations => _setters?.Count > 0 || _animations?.Count > 0;
+
+ public void Add(ISetter setter) => Setters.Add(setter);
+ public void Add(IStyle style) => Children.Add(style);
+
+ public event EventHandler? OwnerChanged;
+
+ public abstract SelectorMatchResult TryAttach(IStyleable target, object? host);
+
+ public bool TryGetResource(object key, out object? result)
+ {
+ result = null;
+ return _resources?.TryGetResource(key, out result) ?? false;
+ }
+
+ internal void Attach(IStyleable target, IStyleActivator? activator)
+ {
+ var instance = new StyleInstance(this, target, _setters, _animations, activator);
+ target.StyleApplied(instance);
+ instance.Start();
+ }
+
+ internal SelectorMatchResult TryAttachChildren(IStyleable target, object? host)
+ {
+ if (_children is null || _children.Count == 0)
+ return SelectorMatchResult.NeverThisType;
+ _childCache ??= new StyleCache();
+ return _childCache.TryAttach(_children, target, host);
+ }
+
+ internal virtual void SetParent(StyleBase? parent) => Parent = parent;
+
+ void IResourceProvider.AddOwner(IResourceHost owner)
+ {
+ owner = owner ?? throw new ArgumentNullException(nameof(owner));
+
+ if (Owner != null)
+ {
+ throw new InvalidOperationException("The Style already has a parent.");
+ }
+
+ Owner = owner;
+ _resources?.AddOwner(owner);
+ }
+
+ void IResourceProvider.RemoveOwner(IResourceHost owner)
+ {
+ owner = owner ?? throw new ArgumentNullException(nameof(owner));
+
+ if (Owner == owner)
+ {
+ Owner = null;
+ _resources?.RemoveOwner(owner);
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.Base/Styling/StyleCache.cs b/src/Avalonia.Base/Styling/StyleCache.cs
index 3285476880..81196f6a27 100644
--- a/src/Avalonia.Base/Styling/StyleCache.cs
+++ b/src/Avalonia.Base/Styling/StyleCache.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Styling
///
internal class StyleCache : Dictionary?>
{
- public SelectorMatchResult TryAttach(IList styles, IStyleable target, IStyleHost? host)
+ public SelectorMatchResult TryAttach(IList styles, IStyleable target, object? host)
{
if (TryGetValue(target.StyleKey, out var cached))
{
diff --git a/src/Avalonia.Base/Styling/StyleChildren.cs b/src/Avalonia.Base/Styling/StyleChildren.cs
index 5f8635f155..42b0a331ee 100644
--- a/src/Avalonia.Base/Styling/StyleChildren.cs
+++ b/src/Avalonia.Base/Styling/StyleChildren.cs
@@ -5,20 +5,20 @@ namespace Avalonia.Styling
{
internal class StyleChildren : Collection
{
- private readonly Style _owner;
+ private readonly StyleBase _owner;
- public StyleChildren(Style owner) => _owner = owner;
+ public StyleChildren(StyleBase owner) => _owner = owner;
protected override void InsertItem(int index, IStyle item)
{
- (item as Style)?.SetParent(_owner);
+ (item as StyleBase)?.SetParent(_owner);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
var item = Items[index];
- (item as Style)?.SetParent(null);
+ (item as StyleBase)?.SetParent(null);
if (_owner.Owner is IResourceHost host)
(item as IResourceProvider)?.RemoveOwner(host);
base.RemoveItem(index);
@@ -26,7 +26,7 @@ namespace Avalonia.Styling
protected override void SetItem(int index, IStyle item)
{
- (item as Style)?.SetParent(_owner);
+ (item as StyleBase)?.SetParent(_owner);
base.SetItem(index, item);
if (_owner.Owner is IResourceHost host)
(item as IResourceProvider)?.AddOwner(host);
diff --git a/src/Avalonia.Base/Styling/Styler.cs b/src/Avalonia.Base/Styling/Styler.cs
index 74cf77ea40..ad5c1cd102 100644
--- a/src/Avalonia.Base/Styling/Styler.cs
+++ b/src/Avalonia.Base/Styling/Styler.cs
@@ -1,19 +1,24 @@
using System;
-#nullable enable
-
namespace Avalonia.Styling
{
public class Styler : IStyler
{
public void ApplyStyles(IStyleable target)
{
- target = target ?? throw new ArgumentNullException(nameof(target));
+ _ = target ?? throw new ArgumentNullException(nameof(target));
+
+ // Apply the control theme.
+ target.GetEffectiveTheme()?.TryAttach(target, target);
+
+ // If the control has a themed templated parent then apply the styles from the
+ // templated parent theme.
+ if (target.TemplatedParent is IStyleable styleableParent)
+ styleableParent.GetEffectiveTheme()?.TryAttach(target, styleableParent);
+ // Apply styles from the rest of the tree.
if (target is IStyleHost styleHost)
- {
ApplyStyles(target, styleHost);
- }
}
private void ApplyStyles(IStyleable target, IStyleHost host)
@@ -21,14 +26,10 @@ namespace Avalonia.Styling
var parent = host.StylingParent;
if (parent != null)
- {
ApplyStyles(target, parent);
- }
if (host.IsStylesInitialized)
- {
host.Styles.TryAttach(target, host);
- }
}
}
}
diff --git a/src/Avalonia.Base/Styling/Styles.cs b/src/Avalonia.Base/Styling/Styles.cs
index e4c3371007..c213475bb7 100644
--- a/src/Avalonia.Base/Styling/Styles.cs
+++ b/src/Avalonia.Base/Styling/Styles.cs
@@ -26,6 +26,11 @@ namespace Avalonia.Styling
{
_styles.ResetBehavior = ResetBehavior.Remove;
_styles.CollectionChanged += OnCollectionChanged;
+ _styles.Validate = i =>
+ {
+ if (i is ControlTheme)
+ throw new InvalidOperationException("ControlThemes cannot be added to a Styles collection.");
+ };
}
public Styles(IResourceHost owner)
@@ -111,7 +116,7 @@ namespace Avalonia.Styling
set => _styles[index] = value;
}
- public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)
+ public SelectorMatchResult TryAttach(IStyleable target, object? host)
{
_cache ??= new StyleCache();
return _cache.TryAttach(this, target, host);
diff --git a/src/Avalonia.Base/Styling/TemplateSelector.cs b/src/Avalonia.Base/Styling/TemplateSelector.cs
index b0a2dae8d6..278e24a203 100644
--- a/src/Avalonia.Base/Styling/TemplateSelector.cs
+++ b/src/Avalonia.Base/Styling/TemplateSelector.cs
@@ -49,6 +49,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
- internal override bool HasValidNestingSelector() => _parent?.HasValidNestingSelector() ?? false;
+ protected override Selector? MovePreviousOrParent() => _parent;
}
}
diff --git a/src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs b/src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs
index d52c8c7d5c..94a6db41f6 100644
--- a/src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs
+++ b/src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs
@@ -141,7 +141,7 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
- internal override bool HasValidNestingSelector() => _previous?.HasValidNestingSelector() ?? false;
+ protected override Selector? MovePreviousOrParent() => _previous;
private string BuildSelectorString()
{
diff --git a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
index a801d338c3..dc9064b262 100644
--- a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
+++ b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
@@ -95,6 +95,9 @@
Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
Markup/%(RecursiveDir)%(FileName)%(Extension)
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index b39ceab1b6..39a83c00c4 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -251,7 +251,8 @@ namespace Avalonia.Build.Tasks
var populateBuilder = classTypeDefinition == null ?
builder :
typeSystem.CreateTypeBuilder(classTypeDefinition);
- compiler.Compile(parsed, contextClass,
+ compiler.Compile(parsed,
+ contextClass,
compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
classTypeDefinition == null),
buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, true),
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Default/Default.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Default/Default.xaml
index ebecd65cc3..db1fa3ee4e 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Default/Default.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Default/Default.xaml
@@ -37,4 +37,8 @@
+
+
+
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPicker.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPicker.xaml
index a4d5ff673f..907b00dfff 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPicker.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPicker.xaml
@@ -1,14 +1,13 @@
-
+
-
-
- 5,5,0,0
-
+
+ 5,5,0,0
-
+
-
+ -->
-
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml
index 74f33d1258..1c4a44d081 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorPreviewer.xaml
@@ -1,15 +1,14 @@
-
+
-
-
- 80
- 40
-
+
+ 80
+ 40
-
+
-
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml
index 162ac372de..eb67ada334 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSlider.xaml
@@ -1,188 +1,190 @@
-
+
-
+
-
+
-
+
-
-
+
+
+
+
+
+
-
-
-
-
+
+
-
-
+
-
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml
index dba4ad19f5..f95721c881 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorSpectrum.xaml
@@ -1,9 +1,10 @@
-
+
-
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
+
+
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
index e25e822f3f..993745b1e5 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
@@ -1,86 +1,85 @@
-
+
-
-
-
-
-
-
- 48
- 30
- 80
-
-
- M3 2C3.27614 2 3.5 2.22386 3.5 2.5V5.5C3.5 5.77614 3.72386 6 4 6H16C16.2761 6 16.5 5.77614
- 16.5 5.5V2.5C16.5 2.22386 16.7239 2 17 2C17.2761 2 17.5 2.22386 17.5 2.5V5.5C17.5 6.32843
- 16.8284 7 16 7H15.809L12.2236 14.1708C12.0615 14.4951 11.7914 14.7431 11.4695
- 14.8802C11.4905 15.0808 11.5 15.2891 11.5 15.5C11.5 16.0818 11.4278 16.6623 11.2268
- 17.1165C11.019 17.5862 10.6266 18 10 18C9.37343 18 8.98105 17.5862 8.77323 17.1165C8.57222
- 16.6623 8.5 16.0818 8.5 15.5C8.5 15.2891 8.50952 15.0808 8.53051 14.8802C8.20863 14.7431
- 7.93851 14.4951 7.77639 14.1708L4.19098 7H4C3.17157 7 2.5 6.32843 2.5 5.5V2.5C2.5 2.22386
- 2.72386 2 3 2ZM9.11803 14H10.882C11.0714 14 11.2445 13.893 11.3292 13.7236L14.691
- 7H5.30902L8.67082 13.7236C8.75552 13.893 8.92865 14 9.11803 14ZM9.52346 15C9.50787 15.1549
- 9.5 15.3225 9.5 15.5C9.5 16.0228 9.56841 16.4423 9.6877 16.7119C9.8002 16.9661 9.90782 17
- 10 17C10.0922 17 10.1998 16.9661 10.3123 16.7119C10.4316 16.4423 10.5 16.0228 10.5
- 15.5C10.5 15.3225 10.4921 15.1549 10.4765 15H9.52346Z
-
-
-
- M9.75003 6.5C10.1642 6.5 10.5 6.16421 10.5 5.75C10.5 5.33579 10.1642 5 9.75003 5C9.33582
- 5 9.00003 5.33579 9.00003 5.75C9.00003 6.16421 9.33582 6.5 9.75003 6.5ZM12.75 7.5C13.1642
- 7.5 13.5 7.16421 13.5 6.75C13.5 6.33579 13.1642 6 12.75 6C12.3358 6 12 6.33579 12 6.75C12
- 7.16421 12.3358 7.5 12.75 7.5ZM15.25 9C15.25 9.41421 14.9142 9.75 14.5 9.75C14.0858 9.75
- 13.75 9.41421 13.75 9C13.75 8.58579 14.0858 8.25 14.5 8.25C14.9142 8.25 15.25 8.58579
- 15.25 9ZM14.5 12.75C14.9142 12.75 15.25 12.4142 15.25 12C15.25 11.5858 14.9142 11.25 14.5
- 11.25C14.0858 11.25 13.75 11.5858 13.75 12C13.75 12.4142 14.0858 12.75 14.5 12.75ZM13.25
- 14C13.25 14.4142 12.9142 14.75 12.5 14.75C12.0858 14.75 11.75 14.4142 11.75 14C11.75
- 13.5858 12.0858 13.25 12.5 13.25C12.9142 13.25 13.25 13.5858 13.25 14ZM13.6972
- 2.99169C10.9426 1.57663 8.1432 1.7124 5.77007 3.16636C4.55909 3.9083 3.25331 5.46925
- 2.51605 7.05899C2.14542 7.85816 1.89915 8.70492 1.90238 9.49318C1.90566 10.2941 2.16983
- 11.0587 2.84039 11.6053C3.45058 12.1026 3.98165 12.353 4.49574 12.3784C5.01375 12.404
- 5.41804 12.1942 5.73429 12.0076C5.80382 11.9666 5.86891 11.927 5.93113 11.8892C6.17332
- 11.7421 6.37205 11.6214 6.62049 11.5426C6.90191 11.4534 7.2582 11.4205 7.77579
- 11.5787C7.96661 11.637 8.08161 11.7235 8.16212 11.8229C8.24792 11.9289 8.31662 12.0774
- 8.36788 12.2886C8.41955 12.5016 8.44767 12.7527 8.46868 13.0491C8.47651 13.1594 8.48379
- 13.2855 8.49142 13.4176C8.50252 13.6098 8.51437 13.8149 8.52974 14.0037C8.58435 14.6744
- 8.69971 15.4401 9.10362 16.1357C9.51764 16.8488 10.2047 17.439 11.307 17.8158C12.9093
- 18.3636 14.3731 17.9191 15.5126 17.0169C16.6391 16.125 17.4691 14.7761 17.8842
- 13.4272C19.1991 9.15377 17.6728 5.03394 13.6972 2.99169ZM6.29249 4.01905C8.35686 2.75426
- 10.7844 2.61959 13.2403 3.88119C16.7473 5.68275 18.1135 9.28161 16.9284 13.1332C16.5624
- 14.3227 15.8338 15.4871 14.8919 16.2329C13.963 16.9684 12.8486 17.286 11.6305
- 16.8696C10.7269 16.5607 10.2467 16.1129 9.96842 15.6336C9.68001 15.1369 9.57799 14.5556
- 9.52644 13.9225C9.51101 13.733 9.50132 13.5621 9.49147 13.3884C9.48399 13.2564 9.47642
- 13.1229 9.46618 12.9783C9.44424 12.669 9.41175 12.3499 9.33968 12.0529C9.26719 11.7541
- 9.14902 11.4527 8.93935 11.1937C8.72439 10.9282 8.43532 10.7346 8.06801 10.6223C7.36648
- 10.408 6.80266 10.4359 6.31839 10.5893C5.94331 10.7082 5.62016 10.9061 5.37179
- 11.0582C5.31992 11.0899 5.2713 11.1197 5.22616 11.1463C4.94094 11.3146 4.75357 11.39
- 4.54514 11.3796C4.33279 11.3691 4.00262 11.2625 3.47218 10.8301C3.0866 10.5158 2.90473
- 10.0668 2.90237 9.48908C2.89995 8.89865 3.08843 8.20165 3.42324 7.47971C4.09686 6.0272
- 5.28471 4.63649 6.29249 4.01905Z
-
-
-
- M14.95 5C14.7184 3.85888 13.7095 3 12.5 3C11.2905 3 10.2816 3.85888 10.05 5H2.5C2.22386
- 5 2 5.22386 2 5.5C2 5.77614 2.22386 6 2.5 6H10.05C10.2816 7.14112 11.2905 8 12.5 8C13.7297
- 8 14.752 7.11217 14.961 5.94254C14.9575 5.96177 14.9539 5.98093 14.95 6H17.5C17.7761 6 18
- 5.77614 18 5.5C18 5.22386 17.7761 5 17.5 5H14.95ZM12.5 7C11.6716 7 11 6.32843 11 5.5C11
- 4.67157 11.6716 4 12.5 4C13.3284 4 14 4.67157 14 5.5C14 6.32843 13.3284 7 12.5 7ZM9.94999
- 14C9.71836 12.8589 8.70948 12 7.5 12C6.29052 12 5.28164 12.8589 5.05001 14H2.5C2.22386
- 14 2 14.2239 2 14.5C2 14.7761 2.22386 15 2.5 15H5.05001C5.28164 16.1411 6.29052 17 7.5
- 17C8.70948 17 9.71836 16.1411 9.94999 15H17.5C17.7761 15 18 14.7761 18 14.5C18 14.2239
- 17.7761 14 17.5 14H9.94999ZM7.5 16C6.67157 16 6 15.3284 6 14.5C6 13.6716 6.67157 13 7.5
- 13C8.32843 13 9 13.6716 9 14.5C9 15.3284 8.32843 16 7.5 16Z
-
-
+
+
+
+
+
+ 48
+ 30
+ 80
+
+
+ M3 2C3.27614 2 3.5 2.22386 3.5 2.5V5.5C3.5 5.77614 3.72386 6 4 6H16C16.2761 6 16.5 5.77614
+ 16.5 5.5V2.5C16.5 2.22386 16.7239 2 17 2C17.2761 2 17.5 2.22386 17.5 2.5V5.5C17.5 6.32843
+ 16.8284 7 16 7H15.809L12.2236 14.1708C12.0615 14.4951 11.7914 14.7431 11.4695
+ 14.8802C11.4905 15.0808 11.5 15.2891 11.5 15.5C11.5 16.0818 11.4278 16.6623 11.2268
+ 17.1165C11.019 17.5862 10.6266 18 10 18C9.37343 18 8.98105 17.5862 8.77323 17.1165C8.57222
+ 16.6623 8.5 16.0818 8.5 15.5C8.5 15.2891 8.50952 15.0808 8.53051 14.8802C8.20863 14.7431
+ 7.93851 14.4951 7.77639 14.1708L4.19098 7H4C3.17157 7 2.5 6.32843 2.5 5.5V2.5C2.5 2.22386
+ 2.72386 2 3 2ZM9.11803 14H10.882C11.0714 14 11.2445 13.893 11.3292 13.7236L14.691
+ 7H5.30902L8.67082 13.7236C8.75552 13.893 8.92865 14 9.11803 14ZM9.52346 15C9.50787 15.1549
+ 9.5 15.3225 9.5 15.5C9.5 16.0228 9.56841 16.4423 9.6877 16.7119C9.8002 16.9661 9.90782 17
+ 10 17C10.0922 17 10.1998 16.9661 10.3123 16.7119C10.4316 16.4423 10.5 16.0228 10.5
+ 15.5C10.5 15.3225 10.4921 15.1549 10.4765 15H9.52346Z
+
+
+
+ M9.75003 6.5C10.1642 6.5 10.5 6.16421 10.5 5.75C10.5 5.33579 10.1642 5 9.75003 5C9.33582
+ 5 9.00003 5.33579 9.00003 5.75C9.00003 6.16421 9.33582 6.5 9.75003 6.5ZM12.75 7.5C13.1642
+ 7.5 13.5 7.16421 13.5 6.75C13.5 6.33579 13.1642 6 12.75 6C12.3358 6 12 6.33579 12 6.75C12
+ 7.16421 12.3358 7.5 12.75 7.5ZM15.25 9C15.25 9.41421 14.9142 9.75 14.5 9.75C14.0858 9.75
+ 13.75 9.41421 13.75 9C13.75 8.58579 14.0858 8.25 14.5 8.25C14.9142 8.25 15.25 8.58579
+ 15.25 9ZM14.5 12.75C14.9142 12.75 15.25 12.4142 15.25 12C15.25 11.5858 14.9142 11.25 14.5
+ 11.25C14.0858 11.25 13.75 11.5858 13.75 12C13.75 12.4142 14.0858 12.75 14.5 12.75ZM13.25
+ 14C13.25 14.4142 12.9142 14.75 12.5 14.75C12.0858 14.75 11.75 14.4142 11.75 14C11.75
+ 13.5858 12.0858 13.25 12.5 13.25C12.9142 13.25 13.25 13.5858 13.25 14ZM13.6972
+ 2.99169C10.9426 1.57663 8.1432 1.7124 5.77007 3.16636C4.55909 3.9083 3.25331 5.46925
+ 2.51605 7.05899C2.14542 7.85816 1.89915 8.70492 1.90238 9.49318C1.90566 10.2941 2.16983
+ 11.0587 2.84039 11.6053C3.45058 12.1026 3.98165 12.353 4.49574 12.3784C5.01375 12.404
+ 5.41804 12.1942 5.73429 12.0076C5.80382 11.9666 5.86891 11.927 5.93113 11.8892C6.17332
+ 11.7421 6.37205 11.6214 6.62049 11.5426C6.90191 11.4534 7.2582 11.4205 7.77579
+ 11.5787C7.96661 11.637 8.08161 11.7235 8.16212 11.8229C8.24792 11.9289 8.31662 12.0774
+ 8.36788 12.2886C8.41955 12.5016 8.44767 12.7527 8.46868 13.0491C8.47651 13.1594 8.48379
+ 13.2855 8.49142 13.4176C8.50252 13.6098 8.51437 13.8149 8.52974 14.0037C8.58435 14.6744
+ 8.69971 15.4401 9.10362 16.1357C9.51764 16.8488 10.2047 17.439 11.307 17.8158C12.9093
+ 18.3636 14.3731 17.9191 15.5126 17.0169C16.6391 16.125 17.4691 14.7761 17.8842
+ 13.4272C19.1991 9.15377 17.6728 5.03394 13.6972 2.99169ZM6.29249 4.01905C8.35686 2.75426
+ 10.7844 2.61959 13.2403 3.88119C16.7473 5.68275 18.1135 9.28161 16.9284 13.1332C16.5624
+ 14.3227 15.8338 15.4871 14.8919 16.2329C13.963 16.9684 12.8486 17.286 11.6305
+ 16.8696C10.7269 16.5607 10.2467 16.1129 9.96842 15.6336C9.68001 15.1369 9.57799 14.5556
+ 9.52644 13.9225C9.51101 13.733 9.50132 13.5621 9.49147 13.3884C9.48399 13.2564 9.47642
+ 13.1229 9.46618 12.9783C9.44424 12.669 9.41175 12.3499 9.33968 12.0529C9.26719 11.7541
+ 9.14902 11.4527 8.93935 11.1937C8.72439 10.9282 8.43532 10.7346 8.06801 10.6223C7.36648
+ 10.408 6.80266 10.4359 6.31839 10.5893C5.94331 10.7082 5.62016 10.9061 5.37179
+ 11.0582C5.31992 11.0899 5.2713 11.1197 5.22616 11.1463C4.94094 11.3146 4.75357 11.39
+ 4.54514 11.3796C4.33279 11.3691 4.00262 11.2625 3.47218 10.8301C3.0866 10.5158 2.90473
+ 10.0668 2.90237 9.48908C2.89995 8.89865 3.08843 8.20165 3.42324 7.47971C4.09686 6.0272
+ 5.28471 4.63649 6.29249 4.01905Z
+
+
+
+ M14.95 5C14.7184 3.85888 13.7095 3 12.5 3C11.2905 3 10.2816 3.85888 10.05 5H2.5C2.22386
+ 5 2 5.22386 2 5.5C2 5.77614 2.22386 6 2.5 6H10.05C10.2816 7.14112 11.2905 8 12.5 8C13.7297
+ 8 14.752 7.11217 14.961 5.94254C14.9575 5.96177 14.9539 5.98093 14.95 6H17.5C17.7761 6 18
+ 5.77614 18 5.5C18 5.22386 17.7761 5 17.5 5H14.95ZM12.5 7C11.6716 7 11 6.32843 11 5.5C11
+ 4.67157 11.6716 4 12.5 4C13.3284 4 14 4.67157 14 5.5C14 6.32843 13.3284 7 12.5 7ZM9.94999
+ 14C9.71836 12.8589 8.70948 12 7.5 12C6.29052 12 5.28164 12.8589 5.05001 14H2.5C2.22386
+ 14 2 14.2239 2 14.5C2 14.7761 2.22386 15 2.5 15H5.05001C5.28164 16.1411 6.29052 17 7.5
+ 17C8.70948 17 9.71836 16.1411 9.94999 15H17.5C17.7761 15 18 14.7761 18 14.5C18 14.2239
+ 17.7761 14 17.5 14H9.94999ZM7.5 16C6.67157 16 6 15.3284 6 14.5C6 13.6716 6.67157 13 7.5
+ 13C8.32843 13 9 13.6716 9 14.5C9 15.3284 8.32843 16 7.5 16Z
+
-
+
-
+
diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml
index 186b6de9bc..a5a94a2322 100644
--- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml
+++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml
@@ -3,42 +3,48 @@
xmlns:converters="using:Avalonia.Controls.Converters">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Controls/Chrome/CaptionButtons.cs b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
index d5923a8b37..6d7e542bb2 100644
--- a/src/Avalonia.Controls/Chrome/CaptionButtons.cs
+++ b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
@@ -8,10 +8,10 @@ namespace Avalonia.Controls.Chrome
///
/// Draws window minimize / maximize / close buttons in a when managed client decorations are enabled.
///
- [TemplatePart("PART_CloseButton", typeof(Panel))]
- [TemplatePart("PART_RestoreButton", typeof(Panel))]
- [TemplatePart("PART_MinimiseButton", typeof(Panel))]
- [TemplatePart("PART_FullScreenButton", typeof(Panel))]
+ [TemplatePart("PART_CloseButton", typeof(Button))]
+ [TemplatePart("PART_RestoreButton", typeof(Button))]
+ [TemplatePart("PART_MinimiseButton", typeof(Button))]
+ [TemplatePart("PART_FullScreenButton", typeof(Button))]
[PseudoClasses(":minimized", ":normal", ":maximized", ":fullscreen")]
public class CaptionButtons : TemplatedControl
{
@@ -88,18 +88,15 @@ namespace Avalonia.Controls.Chrome
{
base.OnApplyTemplate(e);
- var closeButton = e.NameScope.Get("PART_CloseButton");
- var restoreButton = e.NameScope.Get("PART_RestoreButton");
- var minimiseButton = e.NameScope.Get("PART_MinimiseButton");
- var fullScreenButton = e.NameScope.Get("PART_FullScreenButton");
+ var closeButton = e.NameScope.Get
public static readonly AttachedProperty FontWeightProperty =
- AvaloniaProperty.RegisterAttached(
+ AvaloniaProperty.RegisterAttached(
nameof(FontWeight),
inherits: true,
defaultValue: FontWeight.Normal);
@@ -53,7 +53,7 @@ namespace Avalonia.Controls.Documents
/// Defines the property.
///
public static readonly AttachedProperty FontStretchProperty =
- AvaloniaProperty.RegisterAttached(
+ AvaloniaProperty.RegisterAttached(
nameof(FontStretch),
inherits: true,
defaultValue: FontStretch.Normal);
@@ -62,7 +62,7 @@ namespace Avalonia.Controls.Documents
/// Defines the property.
///
public static readonly AttachedProperty ForegroundProperty =
- AvaloniaProperty.RegisterAttached(
+ AvaloniaProperty.RegisterAttached(
nameof(Foreground),
Brushes.Black,
inherits: true);
diff --git a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
index 70d9dbec08..f9772cb399 100644
--- a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Avalonia.Controls.Templates;
+using Avalonia.Styling;
namespace Avalonia.Controls.Generators
{
@@ -14,6 +15,11 @@ namespace Avalonia.Controls.Generators
///
IEnumerable Containers { get; }
+ ///
+ /// Gets or sets the theme to be applied to the items in the control.
+ ///
+ ControlTheme? ItemContainerTheme { get; set; }
+
///
/// Gets or sets the data template used to display the items in the control.
///
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
index a76dcbe9c8..8b36b07cec 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
@@ -4,6 +4,7 @@ using System.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.Data;
+using Avalonia.Styling;
namespace Avalonia.Controls.Generators
{
@@ -35,6 +36,11 @@ namespace Avalonia.Controls.Generators
///
public event EventHandler? Recycled;
+ ///
+ /// Gets or sets the theme to be applied to the items in the control.
+ ///
+ public ControlTheme? ItemContainerTheme { get; set; }
+
///
/// Gets or sets the data template used to display the items in the control.
///
@@ -190,10 +196,18 @@ namespace Avalonia.Controls.Generators
result.SetValue(
ContentPresenter.ContentTemplateProperty,
ItemTemplate,
- BindingPriority.TemplatedParent);
+ BindingPriority.Style);
}
}
+ if (ItemContainerTheme != null)
+ {
+ result.SetValue(
+ StyledElement.ThemeProperty,
+ ItemContainerTheme,
+ BindingPriority.TemplatedParent);
+ }
+
return result;
}
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
index 635f3a7d37..3ff1b0702d 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
@@ -44,28 +44,29 @@ namespace Avalonia.Controls.Generators
{
var container = item as T;
- if (container != null)
+ if (container is null)
{
- return container;
- }
- else
- {
- var result = new T();
+ container = new T();
if (ContentTemplateProperty != null)
{
- result.SetValue(ContentTemplateProperty, ItemTemplate, BindingPriority.Style);
+ container.SetValue(ContentTemplateProperty, ItemTemplate, BindingPriority.Style);
}
- result.SetValue(ContentProperty, item, BindingPriority.Style);
+ container.SetValue(ContentProperty, item, BindingPriority.Style);
if (!(item is IControl))
{
- result.DataContext = item;
+ container.DataContext = item;
}
+ }
- return result;
+ if (ItemContainerTheme != null)
+ {
+ container.SetValue(StyledElement.ThemeProperty, ItemContainerTheme, BindingPriority.Style);
}
+
+ return container;
}
///
diff --git a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
index 536a5fdd06..4e3deb5552 100644
--- a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
@@ -71,6 +71,11 @@ namespace Avalonia.Controls.Generators
var template = GetTreeDataTemplate(item, ItemTemplate);
var result = new T();
+ if (ItemContainerTheme != null)
+ {
+ result.SetValue(Control.ThemeProperty, ItemContainerTheme, BindingPriority.Style);
+ }
+
result.SetValue(ContentProperty, template.Build(item), BindingPriority.Style);
var itemsSelector = template.ItemsSelector(item);
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index 1ac642c22b..345e7fcac8 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -15,6 +15,7 @@ using Avalonia.Input;
using Avalonia.LogicalTree;
using Avalonia.Metadata;
using Avalonia.VisualTree;
+using Avalonia.Styling;
namespace Avalonia.Controls
{
@@ -36,6 +37,12 @@ namespace Avalonia.Controls
public static readonly DirectProperty ItemsProperty =
AvaloniaProperty.RegisterDirect(nameof(Items), o => o.Items, (o, v) => o.Items = v);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty ItemContainerThemeProperty =
+ AvaloniaProperty.Register(nameof(ItemContainerTheme));
+
///
/// Defines the property.
///
@@ -88,6 +95,7 @@ namespace Avalonia.Controls
{
_itemContainerGenerator = CreateItemContainerGenerator();
+ _itemContainerGenerator.ItemContainerTheme = ItemContainerTheme;
_itemContainerGenerator.ItemTemplate = ItemTemplate;
_itemContainerGenerator.Materialized += (_, e) => OnContainersMaterialized(e);
_itemContainerGenerator.Dematerialized += (_, e) => OnContainersDematerialized(e);
@@ -108,6 +116,15 @@ namespace Avalonia.Controls
set { SetAndRaise(ItemsProperty, ref _items, value); }
}
+ ///
+ /// Gets or sets the that is applied to the container element generated for each item.
+ ///
+ public ControlTheme? ItemContainerTheme
+ {
+ get { return GetValue(ItemContainerThemeProperty); }
+ set { SetValue(ItemContainerThemeProperty, value); }
+ }
+
///
/// Gets the number of items in .
///
@@ -349,6 +366,10 @@ namespace Avalonia.Controls
{
UpdatePseudoClasses(change.GetNewValue());
}
+ else if (change.Property == ItemContainerThemeProperty && _itemContainerGenerator is not null)
+ {
+ _itemContainerGenerator.ItemContainerTheme = change.GetNewValue();
+ }
}
///
diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
index bd0339f525..6bb94c6070 100644
--- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
+++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
@@ -6,7 +6,6 @@ using Avalonia.Input.Raw;
using Avalonia.Layout;
using Avalonia.Metadata;
using Avalonia.Rendering;
-using JetBrains.Annotations;
namespace Avalonia.Platform
{
@@ -151,13 +150,7 @@ namespace Avalonia.Platform
/// Gets or sets a method called when the input focus is lost.
///
Action? LostFocus { get; set; }
-
- ///
- /// Gets a mouse device associated with toplevel
- ///
- [CanBeNull]
- IMouseDevice MouseDevice { get; }
-
+
IPopupImpl? CreatePopup();
///
diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs
index 92f6f1cb52..de7708e869 100644
--- a/src/Avalonia.Controls/Platform/PlatformManager.cs
+++ b/src/Avalonia.Controls/Platform/PlatformManager.cs
@@ -20,17 +20,8 @@ namespace Avalonia.Controls.Platform
{
}
- public static ITrayIconImpl? CreateTrayIcon()
- {
- var platform = AvaloniaLocator.Current.GetService();
-
- if (platform == null)
- {
- throw new Exception("Could not CreateTrayIcon(): IWindowingPlatform is not registered.");
- }
-
- return s_designerMode ? null : platform.CreateTrayIcon();
- }
+ public static ITrayIconImpl? CreateTrayIcon() =>
+ s_designerMode ? null : AvaloniaLocator.Current.GetService()?.CreateTrayIcon();
public static IWindowImpl CreateWindow()
diff --git a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
index 8d35a91e00..d8de813d47 100644
--- a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
+++ b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
@@ -45,6 +45,7 @@ Copyright © 2019 Nikita Tsukanov
*/
using System;
+using Avalonia.Input;
using Avalonia.Metadata;
using Avalonia.VisualTree;
using Avalonia.Media;
@@ -452,16 +453,14 @@ namespace Avalonia.Controls.Primitives.PopupPositioning
PopupPositionerConstraintAdjustment constraintAdjustment, Rect? rect,
FlowDirection flowDirection)
{
- // We need a better way for tracking the last pointer position
-#pragma warning disable CS0618 // Type or member is obsolete
- var pointer = topLevel.PointToClient(topLevel.PlatformImpl?.MouseDevice.Position ?? default);
-#pragma warning restore CS0618 // Type or member is obsolete
-
positionerParameters.Offset = offset;
positionerParameters.ConstraintAdjustment = constraintAdjustment;
if (placement == PlacementMode.Pointer)
{
- positionerParameters.AnchorRectangle = new Rect(pointer, new Size(1, 1));
+ // We need a better way for tracking the last pointer position
+ var position = topLevel.PointToClient(topLevel.LastPointerPosition ?? default);
+
+ positionerParameters.AnchorRectangle = new Rect(position, new Size(1, 1));
positionerParameters.Anchor = PopupAnchor.TopLeft;
positionerParameters.Gravity = PopupGravity.BottomRight;
}
diff --git a/src/Avalonia.Controls/Primitives/TemplatedControl.cs b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
index 35033c58f0..dc52cc3ae2 100644
--- a/src/Avalonia.Controls/Primitives/TemplatedControl.cs
+++ b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
@@ -367,6 +367,17 @@ namespace Avalonia.Controls.Primitives
{
}
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == ThemeProperty)
+ {
+ foreach (var child in this.GetTemplateChildren())
+ child.InvalidateStyles();
+ }
+ }
+
///
/// Called when the control's template is applied.
///
diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs
index d0e8e8f1a0..56b9caf085 100644
--- a/src/Avalonia.Controls/ProgressBar.cs
+++ b/src/Avalonia.Controls/ProgressBar.cs
@@ -100,6 +100,7 @@ namespace Avalonia.Controls
private double _indeterminateStartingOffset;
private double _indeterminateEndingOffset;
private Border? _indicator;
+ private IDisposable? _trackSizeChangedListener;
public static readonly StyledProperty IsIndeterminateProperty =
AvaloniaProperty.Register(nameof(IsIndeterminate));
@@ -195,8 +196,9 @@ namespace Avalonia.Controls
///
protected override Size ArrangeOverride(Size finalSize)
{
+ var result = base.ArrangeOverride(finalSize);
UpdateIndicator();
- return base.ArrangeOverride(finalSize);
+ return result;
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
@@ -216,8 +218,15 @@ namespace Avalonia.Controls
///
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
+ // dispose any previous track size listener
+ _trackSizeChangedListener?.Dispose();
+
_indicator = e.NameScope.Get("PART_Indicator");
+ // listen to size changes of the indicators track (parent) and update the indicator there.
+ _trackSizeChangedListener = _indicator.Parent?.GetPropertyChangedObservable(BoundsProperty)
+ .Subscribe(_ => UpdateIndicator());
+
UpdateIndicator();
}
diff --git a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
index e800f2f4b0..3bc0593813 100644
--- a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
+++ b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
@@ -12,7 +12,6 @@ using Avalonia.Remote.Protocol;
using Avalonia.Remote.Protocol.Input;
using Avalonia.Remote.Protocol.Viewport;
using Avalonia.Threading;
-using InputModifiers = Avalonia.Input.InputModifiers;
using Key = Avalonia.Input.Key;
using PixelFormat = Avalonia.Platform.PixelFormat;
using ProtocolPixelFormat = Avalonia.Remote.Protocol.Viewport.PixelFormat;
diff --git a/src/Avalonia.Controls/RichTextBlock.cs b/src/Avalonia.Controls/RichTextBlock.cs
index 2b84113497..0c8b1d125d 100644
--- a/src/Avalonia.Controls/RichTextBlock.cs
+++ b/src/Avalonia.Controls/RichTextBlock.cs
@@ -41,9 +41,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty SelectionBrushProperty =
AvaloniaProperty.Register(nameof(SelectionBrush), Brushes.Blue);
- public static readonly StyledProperty SelectionForegroundBrushProperty =
- AvaloniaProperty.Register(nameof(SelectionForegroundBrush));
-
///
/// Defines the property.
///
@@ -63,12 +60,13 @@ namespace Avalonia.Controls
private bool _canCopy;
private int _selectionStart;
private int _selectionEnd;
+ private int _wordSelectionStart = -1;
static RichTextBlock()
{
FocusableProperty.OverrideDefaultValue(typeof(RichTextBlock), true);
- AffectsRender(SelectionStartProperty, SelectionEndProperty, SelectionForegroundBrushProperty, SelectionBrushProperty);
+ AffectsRender(SelectionStartProperty, SelectionEndProperty, SelectionBrushProperty, IsTextSelectionEnabledProperty);
}
public RichTextBlock()
@@ -89,15 +87,6 @@ namespace Avalonia.Controls
set => SetValue(SelectionBrushProperty, value);
}
- ///
- /// Gets or sets a value that defines the brush used for selected text.
- ///
- public IBrush? SelectionForegroundBrush
- {
- get => GetValue(SelectionForegroundBrushProperty);
- set => SetValue(SelectionForegroundBrushProperty, value);
- }
-
///
/// Gets or sets a character index for the beginning of the current selection.
///
@@ -170,6 +159,8 @@ namespace Avalonia.Controls
remove => RemoveHandler(CopyingToClipboardEvent, value);
}
+ internal bool HasComplexContent => Inlines.Count > 0;
+
///
/// Copies the current selection to the Clipboard.
///
@@ -198,7 +189,7 @@ namespace Avalonia.Controls
}
}
- public override void Render(DrawingContext context)
+ protected override void RenderTextLayout(DrawingContext context, Point origin)
{
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
@@ -213,13 +204,16 @@ namespace Avalonia.Controls
var rects = TextLayout.HitTestTextRange(start, length);
- foreach (var rect in rects)
+ using (context.PushPostTransform(Matrix.CreateTranslation(origin)))
{
- context.FillRectangle(selectionBrush, PixelRect.FromRect(rect, 1).ToRect(1));
+ foreach (var rect in rects)
+ {
+ context.FillRectangle(selectionBrush, PixelRect.FromRect(rect, 1).ToRect(1));
+ }
}
}
- base.Render(context);
+ base.RenderTextLayout(context, origin);
}
///
@@ -251,6 +245,30 @@ namespace Avalonia.Controls
SelectionEnd = SelectionStart;
}
+ protected void AddText(string? text)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return;
+ }
+
+ if (!HasComplexContent && string.IsNullOrEmpty(_text))
+ {
+ _text = text;
+ }
+ else
+ {
+ if (!string.IsNullOrEmpty(_text))
+ {
+ Inlines.Add(_text);
+
+ _text = null;
+ }
+
+ Inlines.Add(text);
+ }
+ }
+
protected override string? GetText()
{
return _text ?? Inlines.Text;
@@ -259,17 +277,8 @@ namespace Avalonia.Controls
protected override void SetText(string? text)
{
var oldValue = _text ?? Inlines?.Text;
-
- if (Inlines is not null && Inlines.HasComplexContent)
- {
- Inlines.Text = text;
-
- _text = null;
- }
- else
- {
- _text = text;
- }
+
+ AddText(text);
RaisePropertyChanged(TextProperty, oldValue, text);
}
@@ -280,8 +289,9 @@ namespace Avalonia.Controls
/// A object.
protected override TextLayout CreateTextLayout(string? text)
{
+ var typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
var defaultProperties = new GenericTextRunProperties(
- new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
+ typeface,
FontSize,
TextDecorations,
Foreground);
@@ -293,7 +303,7 @@ namespace Avalonia.Controls
var inlines = Inlines;
- if (inlines is not null && inlines.HasComplexContent)
+ if (HasComplexContent)
{
var textRuns = new List();
@@ -328,6 +338,8 @@ namespace Avalonia.Controls
protected override void OnKeyDown(KeyEventArgs e)
{
+ base.OnKeyDown(e);
+
var handled = false;
var modifiers = e.KeyModifiers;
var keymap = AvaloniaLocator.Current.GetRequiredService();
@@ -346,6 +358,8 @@ namespace Avalonia.Controls
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
+ base.OnPointerPressed(e);
+
if (!IsTextSelectionEnabled)
{
return;
@@ -356,7 +370,9 @@ namespace Avalonia.Controls
if (text != null && clickInfo.Properties.IsLeftButtonPressed)
{
- var point = e.GetPosition(this);
+ var padding = Padding;
+
+ var point = e.GetPosition(this) - new Point(padding.Left, padding.Top);
var clickToSelect = e.KeyModifiers.HasFlag(KeyModifiers.Shift);
@@ -365,8 +381,6 @@ namespace Avalonia.Controls
var hit = TextLayout.HitTestPoint(point);
var index = hit.TextPosition;
- SelectionStart = SelectionEnd = index;
-
#pragma warning disable CS0618 // Type or member is obsolete
switch (e.ClickCount)
#pragma warning restore CS0618 // Type or member is obsolete
@@ -374,12 +388,34 @@ namespace Avalonia.Controls
case 1:
if (clickToSelect)
{
- SelectionStart = Math.Min(oldIndex, index);
- SelectionEnd = Math.Max(oldIndex, index);
+ if (_wordSelectionStart >= 0)
+ {
+ var previousWord = StringUtils.PreviousWord(text, index);
+
+ if (index > _wordSelectionStart)
+ {
+ SelectionEnd = StringUtils.NextWord(text, index);
+ }
+
+ if (index < _wordSelectionStart || previousWord == _wordSelectionStart)
+ {
+ SelectionStart = previousWord;
+ }
+ }
+ else
+ {
+ SelectionStart = Math.Min(oldIndex, index);
+ SelectionEnd = Math.Max(oldIndex, index);
+ }
}
else
{
- SelectionStart = SelectionEnd = index;
+ if (_wordSelectionStart == -1 || index < SelectionStart || index > SelectionEnd)
+ {
+ SelectionStart = SelectionEnd = index;
+
+ _wordSelectionStart = -1;
+ }
}
break;
@@ -389,9 +425,13 @@ namespace Avalonia.Controls
SelectionStart = StringUtils.PreviousWord(text, index);
}
+ _wordSelectionStart = SelectionStart;
+
SelectionEnd = StringUtils.NextWord(text, index);
break;
case 3:
+ _wordSelectionStart = -1;
+
SelectAll();
break;
}
@@ -403,6 +443,8 @@ namespace Avalonia.Controls
protected override void OnPointerMoved(PointerEventArgs e)
{
+ base.OnPointerMoved(e);
+
if (!IsTextSelectionEnabled)
{
return;
@@ -411,20 +453,49 @@ namespace Avalonia.Controls
// selection should not change during pointer move if the user right clicks
if (e.Pointer.Captured == this && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
- var point = e.GetPosition(this);
+ var text = Text;
+ var padding = Padding;
+
+ var point = e.GetPosition(this) - new Point(padding.Left, padding.Top);
point = new Point(
- MathUtilities.Clamp(point.X, 0, Math.Max(Bounds.Width - 1, 0)),
- MathUtilities.Clamp(point.Y, 0, Math.Max(Bounds.Height - 1, 0)));
+ MathUtilities.Clamp(point.X, 0, Math.Max(TextLayout.Bounds.Width, 0)),
+ MathUtilities.Clamp(point.Y, 0, Math.Max(TextLayout.Bounds.Width, 0)));
var hit = TextLayout.HitTestPoint(point);
+ var textPosition = hit.TextPosition;
+
+ if (text != null && _wordSelectionStart >= 0)
+ {
+ var distance = textPosition - _wordSelectionStart;
+
+ if (distance <= 0)
+ {
+ SelectionStart = StringUtils.PreviousWord(text, textPosition);
+ }
+
+ if (distance >= 0)
+ {
+ if (SelectionStart != _wordSelectionStart)
+ {
+ SelectionStart = _wordSelectionStart;
+ }
+
+ SelectionEnd = StringUtils.NextWord(text, textPosition);
+ }
+ }
+ else
+ {
+ SelectionEnd = textPosition;
+ }
- SelectionEnd = hit.TextPosition;
}
}
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
+ base.OnPointerReleased(e);
+
if (!IsTextSelectionEnabled)
{
return;
@@ -437,7 +508,9 @@ namespace Avalonia.Controls
if (e.InitialPressMouseButton == MouseButton.Right)
{
- var point = e.GetPosition(this);
+ var padding = Padding;
+
+ var point = e.GetPosition(this) - new Point(padding.Left, padding.Top);
var hit = TextLayout.HitTestPoint(point);
@@ -470,11 +543,6 @@ namespace Avalonia.Controls
InvalidateTextLayout();
break;
}
- case nameof(TextProperty):
- {
- InvalidateTextLayout();
- break;
- }
}
}
diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs
index 52261d1c76..99c8068b3d 100644
--- a/src/Avalonia.Controls/TextBlock.cs
+++ b/src/Avalonia.Controls/TextBlock.cs
@@ -4,6 +4,7 @@ using Avalonia.Controls.Documents;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
+using Avalonia.Metadata;
using Avalonia.Utilities;
namespace Avalonia.Controls
@@ -11,7 +12,7 @@ namespace Avalonia.Controls
///
/// A control that displays a block of text.
///
- public class TextBlock : Control
+ public class TextBlock : Control, IAddChild
{
///
/// Defines the property.
@@ -128,7 +129,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty TextDecorationsProperty =
AvaloniaProperty.Register(nameof(TextDecorations));
- protected string? _text;
+ internal string? _text;
protected TextLayout? _textLayout;
protected Size _constraint;
@@ -473,11 +474,6 @@ namespace Avalonia.Controls
control.SetValue(MaxLinesProperty, maxLines);
}
- public void Add(string text)
- {
- _text = text;
- }
-
///
/// Renders the to a drawing context.
///
@@ -509,7 +505,17 @@ namespace Avalonia.Controls
}
}
- TextLayout.Draw(context, new Point(padding.Left, top));
+ RenderTextLayout(context, new Point(padding.Left, top));
+ }
+
+ protected virtual void RenderTextLayout(DrawingContext context, Point origin)
+ {
+ TextLayout.Draw(context, origin);
+ }
+
+ void IAddChild.AddChild(string text)
+ {
+ _text = text;
}
protected virtual string? GetText()
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 9531f719b9..1b268db2f7 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -53,7 +53,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty PasswordCharProperty =
AvaloniaProperty.Register(nameof(PasswordChar));
-
+
public static readonly StyledProperty SelectionBrushProperty =
AvaloniaProperty.Register(nameof(SelectionBrush));
@@ -80,7 +80,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty MaxLinesProperty =
AvaloniaProperty.Register(nameof(MaxLines), defaultValue: 0);
-
+
public static readonly DirectProperty TextProperty =
TextBlock.TextProperty.AddOwnerWithDataValidation(
o => o.Text,
@@ -105,7 +105,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty TextWrappingProperty =
TextBlock.TextWrappingProperty.AddOwner();
-
+
///
/// Defines see property.
///
@@ -202,6 +202,7 @@ namespace Avalonia.Controls
private string _newLine = Environment.NewLine;
private static readonly string[] invalidCharacters = new String[1] { "\u007f" };
+ private int _wordSelectionStart = -1;
private int _selectedTextChangesMadeSinceLastUndoSnapshot;
private bool _hasDoneSnapshotOnce;
private const int _maxCharsBeforeUndoSnapshot = 7;
@@ -275,7 +276,7 @@ namespace Avalonia.Controls
get => GetValue(IsReadOnlyProperty);
set => SetValue(IsReadOnlyProperty, value);
}
-
+
public char PasswordChar
{
get => GetValue(PasswordCharProperty);
@@ -307,7 +308,7 @@ namespace Avalonia.Controls
{
value = CoerceCaretIndex(value);
var changed = SetAndRaise(SelectionStartProperty, ref _selectionStart, value);
-
+
if (changed)
{
UpdateCommandStates();
@@ -327,12 +328,12 @@ namespace Avalonia.Controls
{
value = CoerceCaretIndex(value);
var changed = SetAndRaise(SelectionEndProperty, ref _selectionEnd, value);
-
+
if (changed)
{
UpdateCommandStates();
}
-
+
if (SelectionStart == value && CaretIndex != value)
{
CaretIndex = value;
@@ -351,7 +352,7 @@ namespace Avalonia.Controls
get => GetValue(MaxLinesProperty);
set => SetValue(MaxLinesProperty, value);
}
-
+
///
/// Gets or sets the line height.
///
@@ -370,7 +371,7 @@ namespace Avalonia.Controls
var caretIndex = CaretIndex;
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
-
+
CaretIndex = CoerceCaretIndex(caretIndex, value);
SelectionStart = CoerceCaretIndex(selectionStart, value);
SelectionEnd = CoerceCaretIndex(selectionEnd, value);
@@ -567,7 +568,7 @@ namespace Avalonia.Controls
_presenter = e.NameScope.Get("PART_TextPresenter");
_imClient.SetPresenter(_presenter, this);
-
+
if (IsFocused)
{
_presenter?.ShowCaret();
@@ -577,7 +578,7 @@ namespace Avalonia.Controls
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
-
+
if (IsFocused)
{
_presenter?.ShowCaret();
@@ -587,7 +588,7 @@ namespace Avalonia.Controls
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
-
+
_imClient.SetPresenter(null, null);
}
@@ -637,7 +638,7 @@ namespace Avalonia.Controls
}
UpdateCommandStates();
-
+
_imClient.SetPresenter(_presenter, this);
_presenter?.ShowCaret();
@@ -657,7 +658,7 @@ namespace Avalonia.Controls
UpdateCommandStates();
_presenter?.HideCaret();
-
+
_imClient.SetPresenter(null, null);
}
@@ -700,14 +701,14 @@ namespace Avalonia.Controls
if (grapheme.FirstCodepoint.IsBreakChar)
{
- if(lineCount + 1 > MaxLines)
+ if (lineCount + 1 > MaxLines)
{
break;
}
else
{
lineCount++;
- }
+ }
}
length += grapheme.Text.Length;
@@ -736,7 +737,7 @@ namespace Avalonia.Controls
text = Text ?? string.Empty;
SetTextInternal(text.Substring(0, caretIndex) + input + text.Substring(caretIndex));
ClearSelection();
-
+
if (IsUndoEnabled)
{
_undoRedoHelper.DiscardRedo();
@@ -746,7 +747,7 @@ namespace Avalonia.Controls
{
RaisePropertyChanged(TextProperty, oldText, _text);
}
-
+
CaretIndex = caretIndex + input.Length;
}
}
@@ -828,7 +829,7 @@ namespace Avalonia.Controls
{
return;
}
-
+
var text = Text ?? string.Empty;
var caretIndex = CaretIndex;
var movement = false;
@@ -985,87 +986,87 @@ namespace Avalonia.Controls
break;
case Key.Up:
- {
- selection = DetectSelection();
-
- _presenter.MoveCaretVertical(LogicalDirection.Backward);
-
- if (caretIndex != _presenter.CaretIndex)
{
- movement = true;
- }
+ selection = DetectSelection();
- if (selection)
- {
- SelectionEnd = _presenter.CaretIndex;
- }
- else
- {
- CaretIndex = _presenter.CaretIndex;
+ _presenter.MoveCaretVertical(LogicalDirection.Backward);
+
+ if (caretIndex != _presenter.CaretIndex)
+ {
+ movement = true;
+ }
+
+ if (selection)
+ {
+ SelectionEnd = _presenter.CaretIndex;
+ }
+ else
+ {
+ CaretIndex = _presenter.CaretIndex;
+ }
+
+ break;
}
-
- break;
- }
case Key.Down:
- {
- selection = DetectSelection();
-
- _presenter.MoveCaretVertical();
-
- if (caretIndex != _presenter.CaretIndex)
- {
- movement = true;
- }
-
- if (selection)
- {
- SelectionEnd = _presenter.CaretIndex;
- }
- else
{
- CaretIndex = _presenter.CaretIndex;
+ selection = DetectSelection();
+
+ _presenter.MoveCaretVertical();
+
+ if (caretIndex != _presenter.CaretIndex)
+ {
+ movement = true;
+ }
+
+ if (selection)
+ {
+ SelectionEnd = _presenter.CaretIndex;
+ }
+ else
+ {
+ CaretIndex = _presenter.CaretIndex;
+ }
+
+ break;
}
-
- break;
- }
case Key.Back:
- {
- SnapshotUndoRedo();
-
- if (hasWholeWordModifiers && SelectionStart == SelectionEnd)
{
- SetSelectionForControlBackspace();
- }
-
- if (!DeleteSelection())
- {
- var characterHit = _presenter.GetNextCharacterHit(LogicalDirection.Backward);
+ SnapshotUndoRedo();
- var backspacePosition = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+ if (hasWholeWordModifiers && SelectionStart == SelectionEnd)
+ {
+ SetSelectionForControlBackspace();
+ }
- if (caretIndex != backspacePosition)
+ if (!DeleteSelection())
{
- var start = Math.Min(backspacePosition, caretIndex);
- var end = Math.Max(backspacePosition, caretIndex);
+ var characterHit = _presenter.GetNextCharacterHit(LogicalDirection.Backward);
- var length = end - start;
+ var backspacePosition = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
- var editedText = text.Substring(0, start) + text.Substring(Math.Min(end, text.Length));
+ if (caretIndex != backspacePosition)
+ {
+ var start = Math.Min(backspacePosition, caretIndex);
+ var end = Math.Max(backspacePosition, caretIndex);
- SetTextInternal(editedText);
+ var length = end - start;
- CaretIndex = start;
- }
- }
-
- SnapshotUndoRedo();
+ var editedText = text.Substring(0, start) + text.Substring(Math.Min(end, text.Length));
- handled = true;
- break;
- }
+ SetTextInternal(editedText);
+
+ CaretIndex = start;
+ }
+ }
+
+ SnapshotUndoRedo();
+
+ handled = true;
+ break;
+ }
case Key.Delete:
SnapshotUndoRedo();
-
+
if (hasWholeWordModifiers && SelectionStart == SelectionEnd)
{
SetSelectionForControlDelete();
@@ -1077,7 +1078,7 @@ namespace Avalonia.Controls
var nextPosition = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
- if(nextPosition != caretIndex)
+ if (nextPosition != caretIndex)
{
var start = Math.Min(nextPosition, caretIndex);
var end = Math.Max(nextPosition, caretIndex);
@@ -1144,7 +1145,7 @@ namespace Avalonia.Controls
{
return;
}
-
+
var text = Text;
var clickInfo = e.GetCurrentPoint(this);
@@ -1170,24 +1171,50 @@ namespace Avalonia.Controls
case 1:
if (clickToSelect)
{
- SelectionStart = Math.Min(oldIndex, index);
- SelectionEnd = Math.Max(oldIndex, index);
+ if (_wordSelectionStart >= 0)
+ {
+ var previousWord = StringUtils.PreviousWord(text, index);
+
+ if (index > _wordSelectionStart)
+ {
+ SelectionEnd = StringUtils.NextWord(text, index);
+ }
+
+ if (index < _wordSelectionStart || previousWord == _wordSelectionStart)
+ {
+ SelectionStart = previousWord;
+ }
+ }
+ else
+ {
+ SelectionStart = Math.Min(oldIndex, index);
+ SelectionEnd = Math.Max(oldIndex, index);
+ }
}
else
{
- SelectionStart = SelectionEnd = index;
+ if(_wordSelectionStart == -1 || index < SelectionStart || index > SelectionEnd)
+ {
+ SelectionStart = SelectionEnd = index;
+ _wordSelectionStart = -1;
+ }
}
break;
- case 2:
+ case 2:
+
if (!StringUtils.IsStartOfWord(text, index))
{
SelectionStart = StringUtils.PreviousWord(text, index);
}
+ _wordSelectionStart = SelectionStart;
+
SelectionEnd = StringUtils.NextWord(text, index);
break;
case 3:
+ _wordSelectionStart = -1;
+
SelectAll();
break;
}
@@ -1203,7 +1230,7 @@ namespace Avalonia.Controls
{
return;
}
-
+
// selection should not change during pointer move if the user right clicks
if (e.Pointer.Captured == _presenter && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
@@ -1215,7 +1242,32 @@ namespace Avalonia.Controls
_presenter.MoveCaretToPoint(point);
- SelectionEnd = _presenter.CaretIndex;
+ var caretIndex = _presenter.CaretIndex;
+ var text = Text;
+
+ if (text != null && _wordSelectionStart >= 0)
+ {
+ var distance = caretIndex - _wordSelectionStart;
+
+ if (distance <= 0)
+ {
+ SelectionStart = StringUtils.PreviousWord(text, caretIndex);
+ }
+
+ if (distance >= 0)
+ {
+ if(SelectionStart != _wordSelectionStart)
+ {
+ SelectionStart = _wordSelectionStart;
+ }
+
+ SelectionEnd = StringUtils.NextWord(text, caretIndex);
+ }
+ }
+ else
+ {
+ SelectionEnd = _presenter.CaretIndex;
+ }
}
}
@@ -1234,9 +1286,9 @@ namespace Avalonia.Controls
if (e.InitialPressMouseButton == MouseButton.Right)
{
var point = e.GetPosition(_presenter);
-
+
_presenter.MoveCaretToPoint(point);
-
+
var caretIndex = _presenter.CaretIndex;
// see if mouse clicked inside current selection
@@ -1250,7 +1302,7 @@ namespace Avalonia.Controls
CaretIndex = SelectionEnd = SelectionStart = caretIndex;
}
}
-
+
e.Pointer.Capture(null);
}
@@ -1309,7 +1361,7 @@ namespace Avalonia.Controls
{
return;
}
-
+
var text = Text ?? string.Empty;
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
@@ -1319,11 +1371,11 @@ namespace Avalonia.Controls
if (isSelecting)
{
_presenter.MoveCaretToTextPosition(selectionEnd);
-
+
_presenter.MoveCaretHorizontal(direction > 0 ?
LogicalDirection.Forward :
LogicalDirection.Backward);
-
+
SelectionEnd = _presenter.CaretIndex;
}
else
@@ -1347,7 +1399,7 @@ namespace Avalonia.Controls
else
{
int offset;
-
+
if (direction > 0)
{
offset = StringUtils.NextWord(text, selectionEnd) - selectionEnd;
@@ -1356,7 +1408,7 @@ namespace Avalonia.Controls
{
offset = StringUtils.PreviousWord(text, selectionEnd) - selectionEnd;
}
-
+
SelectionEnd += offset;
_presenter.MoveCaretToTextPosition(SelectionEnd);
@@ -1378,7 +1430,7 @@ namespace Avalonia.Controls
{
return;
}
-
+
var caretIndex = CaretIndex;
if (document)
@@ -1401,7 +1453,7 @@ namespace Avalonia.Controls
{
return;
}
-
+
var text = Text ?? string.Empty;
var caretIndex = CaretIndex;
@@ -1432,8 +1484,9 @@ namespace Avalonia.Controls
private bool DeleteSelection(bool raiseTextChanged = true)
{
- if (IsReadOnly) return true;
-
+ if (IsReadOnly)
+ return true;
+
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
@@ -1444,40 +1497,40 @@ namespace Avalonia.Controls
var text = Text!;
SetTextInternal(text.Substring(0, start) + text.Substring(end), raiseTextChanged);
-
+
_presenter?.MoveCaretToTextPosition(start);
-
- CaretIndex= start;
-
+
+ CaretIndex = start;
+
ClearSelection();
-
+
return true;
}
-
+
CaretIndex = SelectionStart;
-
+
return false;
}
private string GetSelection()
{
var text = Text;
-
+
if (string.IsNullOrEmpty(text))
{
return "";
}
-
+
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
var start = Math.Min(selectionStart, selectionEnd);
var end = Math.Max(selectionStart, selectionEnd);
-
+
if (start == end || (Text?.Length ?? 0) < end)
{
return "";
}
-
+
return text.Substring(start, end - start);
}
@@ -1496,7 +1549,7 @@ namespace Avalonia.Controls
private void SetSelectionForControlBackspace()
{
var selectionStart = CaretIndex;
-
+
MoveHorizontal(-1, true, false);
SelectionStart = selectionStart;
@@ -1508,9 +1561,9 @@ namespace Avalonia.Controls
{
return;
}
-
+
SelectionStart = CaretIndex;
-
+
MoveHorizontal(1, true, true);
if (SelectionEnd < _text.Length && _text[SelectionEnd] == ' ')
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index 5c5053b982..1c1df84431 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -285,6 +285,8 @@ namespace Avalonia.Controls
///
public IRenderer Renderer { get; private set; }
+ internal PixelPoint? LastPointerPosition => _pointerOverPreProcessor?.LastPosition;
+
///
/// Gets the access key handler for the window.
///
@@ -302,9 +304,6 @@ namespace Avalonia.Controls
set { SetValue(PointerOverElementProperty, value); }
}
- ///
- IMouseDevice? IInputRoot.MouseDevice => PlatformImpl?.MouseDevice;
-
///
/// Gets or sets a value indicating whether access keys are shown in the window.
///
diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs
index 490b0b3ce3..2e3aa037c2 100644
--- a/src/Avalonia.Controls/TreeViewItem.cs
+++ b/src/Avalonia.Controls/TreeViewItem.cs
@@ -121,6 +121,11 @@ namespace Avalonia.Controls
{
ItemTemplate = _treeView.ItemTemplate;
}
+
+ if (ItemContainerTheme == null && _treeView?.ItemContainerTheme != null)
+ {
+ ItemContainerTheme = _treeView.ItemContainerTheme;
+ }
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
diff --git a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs
index b009778f97..811f9c7baa 100644
--- a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs
+++ b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs
@@ -37,6 +37,7 @@ namespace Avalonia.DesignerSupport
var localAsm = assemblyPath != null ? Assembly.LoadFile(Path.GetFullPath(assemblyPath)) : null;
var loaded = loader.Load(stream, localAsm, null, baseUri, true);
var style = loaded as IStyle;
+ var resources = loaded as ResourceDictionary;
if (style != null)
{
var substitute = Design.GetPreviewWith((AvaloniaObject)style);
@@ -58,6 +59,27 @@ namespace Avalonia.DesignerSupport
}
};
}
+ else if (resources != null)
+ {
+ var substitute = Design.GetPreviewWith(resources);
+ if (substitute != null)
+ {
+ substitute.Resources.MergedDictionaries.Add(resources);
+ control = substitute;
+ }
+ else
+ control = new StackPanel
+ {
+ Children =
+ {
+ new TextBlock {Text = "ResourceDictionaries can't be previewed without Design.PreviewWith. Add"},
+ new TextBlock {Text = ""},
+ new TextBlock {Text = " "},
+ new TextBlock {Text = ""},
+ new TextBlock {Text = "in your resource dictionary"}
+ }
+ };
+ }
else if (loaded is Application)
control = new TextBlock {Text = "Application can't be previewed in design view"};
else
diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
index f8e2e0544f..631da80d8b 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
@@ -67,8 +67,15 @@ namespace Avalonia.Diagnostics.ViewModels
var setters = new List();
- if (styleSource is Style style)
+ if (styleSource is StyleBase style)
{
+ var selector = style switch
+ {
+ Style s => s.Selector?.ToString(),
+ ControlTheme t => t.TargetType?.Name.ToString(),
+ _ => null,
+ };
+
foreach (var setter in style.Setters)
{
if (setter is Setter regularSetter
@@ -105,7 +112,7 @@ namespace Avalonia.Diagnostics.ViewModels
}
}
- AppliedStyles.Add(new StyleViewModel(appliedStyle, style.Selector?.ToString() ?? "No selector", setters));
+ AppliedStyles.Add(new StyleViewModel(appliedStyle, selector ?? "No selector", setters));
}
}
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
index 3b143d3b58..96dc929434 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
@@ -19,8 +19,10 @@ namespace Avalonia.Diagnostics.Views
internal class MainWindow : Window, IStyleHost
{
private readonly IDisposable? _keySubscription;
+ private readonly IDisposable? _pointerSubscription;
private readonly Dictionary _frozenPopupStates;
private AvaloniaObject? _root;
+ private PixelPoint _lastPointerPosition;
public MainWindow()
{
@@ -30,6 +32,10 @@ namespace Avalonia.Diagnostics.Views
.OfType()
.Where(x => x.Type == RawKeyEventType.KeyDown)
.Subscribe(RawKeyDown);
+ _pointerSubscription = InputManager.Instance?.Process
+ .OfType()
+ .Subscribe(x => _lastPointerPosition = x.Root.PointToScreen(x.Position));
+
_frozenPopupStates = new Dictionary();
@@ -84,6 +90,7 @@ namespace Avalonia.Diagnostics.Views
{
base.OnClosed(e);
_keySubscription?.Dispose();
+ _pointerSubscription?.Dispose();
foreach (var state in _frozenPopupStates)
{
@@ -108,9 +115,7 @@ namespace Avalonia.Diagnostics.Views
private IControl? GetHoveredControl(TopLevel topLevel)
{
-#pragma warning disable CS0618 // Type or member is obsolete
- var point = (topLevel as IInputRoot)?.MouseDevice?.GetPosition(topLevel) ?? default;
-#pragma warning restore CS0618 // Type or member is obsolete
+ var point = topLevel.PointToClient(_lastPointerPosition);
return (IControl?)topLevel.GetVisualsAt(point, x =>
{
diff --git a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs
index 94e7728d68..3a8fdb8491 100644
--- a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs
+++ b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs
@@ -21,7 +21,7 @@ namespace Avalonia.OpenGL.Angle
var display = IntPtr.Zero;
AngleOptions.PlatformApi angleApi = default;
{
- if (_egl.GetPlatformDisplayEXT == null)
+ if (!_egl.IsGetPlatformDisplayExtAvailable)
throw new OpenGlException("eglGetPlatformDisplayEXT is not supported by libegl.dll");
var allowedApis = AvaloniaLocator.Current.GetService()?.AllowedPlatformApis
@@ -37,7 +37,7 @@ namespace Avalonia.OpenGL.Angle
else
continue;
- display = _egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero,
+ display = _egl.GetPlatformDisplayExt(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero,
new[] { EGL_PLATFORM_ANGLE_TYPE_ANGLE, dapi, EGL_NONE });
if (display != IntPtr.Zero)
{
diff --git a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
index 76924d060f..bacb10c792 100644
--- a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
+++ b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
@@ -11,4 +11,5 @@
+
diff --git a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs
index b3469c212b..68442c1fd3 100644
--- a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs
+++ b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs
@@ -66,11 +66,9 @@ namespace Avalonia.OpenGL.Controls
return;
gl.GetIntegerv(GL_RENDERBUFFER_BINDING, out var oldRenderBuffer);
- if (_depthBuffer != 0) gl.DeleteRenderbuffers(1, new[] { _depthBuffer });
+ if (_depthBuffer != 0) gl.DeleteRenderbuffer(_depthBuffer);
- var oneArr = new int[1];
- gl.GenRenderbuffers(1, oneArr);
- _depthBuffer = oneArr[0];
+ _depthBuffer = gl.GenRenderbuffer();
gl.BindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
gl.RenderbufferStorage(GL_RENDERBUFFER,
GlVersion.Type == GlProfileType.OpenGLES ? GL_DEPTH_COMPONENT16 : GL_DEPTH_COMPONENT,
@@ -88,9 +86,9 @@ namespace Avalonia.OpenGL.Controls
var gl = _context.GlInterface;
gl.BindTexture(GL_TEXTURE_2D, 0);
gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
- gl.DeleteFramebuffers(1, new[] { _fb });
+ gl.DeleteFramebuffer(_fb);
_fb = 0;
- gl.DeleteRenderbuffers(1, new[] { _depthBuffer });
+ gl.DeleteRenderbuffer(_depthBuffer);
_depthBuffer = 0;
_attachment?.Dispose();
_attachment = null;
@@ -174,9 +172,7 @@ namespace Avalonia.OpenGL.Controls
{
_depthBufferSize = GetPixelSize();
var gl = _context.GlInterface;
- var oneArr = new int[1];
- gl.GenFramebuffers(1, oneArr);
- _fb = oneArr[0];
+ _fb = gl.GenFramebuffer();
gl.BindFramebuffer(GL_FRAMEBUFFER, _fb);
EnsureDepthBufferAttachment(gl);
diff --git a/src/Avalonia.OpenGL/Egl/EglConsts.cs b/src/Avalonia.OpenGL/Egl/EglConsts.cs
index 530d3401f6..1268845f0f 100644
--- a/src/Avalonia.OpenGL/Egl/EglConsts.cs
+++ b/src/Avalonia.OpenGL/Egl/EglConsts.cs
@@ -4,212 +4,212 @@ namespace Avalonia.OpenGL.Egl
{
public static class EglConsts
{
- public const int EGL_ALPHA_SIZE = 0x3021;
- public const int EGL_BAD_ACCESS = 0x3002;
- public const int EGL_BAD_ALLOC = 0x3003;
- public const int EGL_BAD_ATTRIBUTE = 0x3004;
- public const int EGL_BAD_CONFIG = 0x3005;
- public const int EGL_BAD_CONTEXT = 0x3006;
- public const int EGL_BAD_CURRENT_SURFACE = 0x3007;
- public const int EGL_BAD_DISPLAY = 0x3008;
- public const int EGL_BAD_MATCH = 0x3009;
- public const int EGL_BAD_NATIVE_PIXMAP = 0x300A;
- public const int EGL_BAD_NATIVE_WINDOW = 0x300B;
- public const int EGL_BAD_PARAMETER = 0x300C;
- public const int EGL_BAD_SURFACE = 0x300D;
- public const int EGL_BLUE_SIZE = 0x3022;
- public const int EGL_BUFFER_SIZE = 0x3020;
- public const int EGL_CONFIG_CAVEAT = 0x3027;
- public const int EGL_CONFIG_ID = 0x3028;
- public const int EGL_CORE_NATIVE_ENGINE = 0x305B;
- public const int EGL_DEPTH_SIZE = 0x3025;
- public const int EGL_DONT_CARE = -1;
- public const int EGL_DRAW = 0x3059;
- public const int EGL_EXTENSIONS = 0x3055;
- public const int EGL_FALSE = 0;
- public const int EGL_GREEN_SIZE = 0x3023;
- public const int EGL_HEIGHT = 0x3056;
- public const int EGL_LARGEST_PBUFFER = 0x3058;
- public const int EGL_LEVEL = 0x3029;
- public const int EGL_MAX_PBUFFER_HEIGHT = 0x302A;
- public const int EGL_MAX_PBUFFER_PIXELS = 0x302B;
- public const int EGL_MAX_PBUFFER_WIDTH = 0x302C;
- public const int EGL_NATIVE_RENDERABLE = 0x302D;
- public const int EGL_NATIVE_VISUAL_ID = 0x302E;
- public const int EGL_NATIVE_VISUAL_TYPE = 0x302F;
- public const int EGL_NONE = 0x3038;
- public const int EGL_NON_CONFORMANT_CONFIG = 0x3051;
- public const int EGL_NOT_INITIALIZED = 0x3001;
- public const int EGL_NO_CONTEXT = 0;
- public const int EGL_NO_DISPLAY = 0;
- public const int EGL_NO_SURFACE = 0;
- public const int EGL_PBUFFER_BIT = 0x0001;
- public const int EGL_PIXMAP_BIT = 0x0002;
- public const int EGL_READ = 0x305A;
- public const int EGL_RED_SIZE = 0x3024;
- public const int EGL_SAMPLES = 0x3031;
- public const int EGL_SAMPLE_BUFFERS = 0x3032;
- public const int EGL_SLOW_CONFIG = 0x3050;
- public const int EGL_STENCIL_SIZE = 0x3026;
- public const int EGL_SUCCESS = 0x3000;
- public const int EGL_SURFACE_TYPE = 0x3033;
- public const int EGL_TRANSPARENT_BLUE_VALUE = 0x3035;
- public const int EGL_TRANSPARENT_GREEN_VALUE = 0x3036;
- public const int EGL_TRANSPARENT_RED_VALUE = 0x3037;
- public const int EGL_TRANSPARENT_RGB = 0x3052;
- public const int EGL_TRANSPARENT_TYPE = 0x3034;
- public const int EGL_TRUE = 1;
- public const int EGL_VENDOR = 0x3053;
- public const int EGL_VERSION = 0x3054;
- public const int EGL_WIDTH = 0x3057;
- public const int EGL_WINDOW_BIT = 0x0004;
+ public const int EGL_ALPHA_SIZE = 0x3021;
+ public const int EGL_BAD_ACCESS = 0x3002;
+ public const int EGL_BAD_ALLOC = 0x3003;
+ public const int EGL_BAD_ATTRIBUTE = 0x3004;
+ public const int EGL_BAD_CONFIG = 0x3005;
+ public const int EGL_BAD_CONTEXT = 0x3006;
+ public const int EGL_BAD_CURRENT_SURFACE = 0x3007;
+ public const int EGL_BAD_DISPLAY = 0x3008;
+ public const int EGL_BAD_MATCH = 0x3009;
+ public const int EGL_BAD_NATIVE_PIXMAP = 0x300A;
+ public const int EGL_BAD_NATIVE_WINDOW = 0x300B;
+ public const int EGL_BAD_PARAMETER = 0x300C;
+ public const int EGL_BAD_SURFACE = 0x300D;
+ public const int EGL_BLUE_SIZE = 0x3022;
+// public const int EGL_BUFFER_SIZE = 0x3020;
+// public const int EGL_CONFIG_CAVEAT = 0x3027;
+// public const int EGL_CONFIG_ID = 0x3028;
+ public const int EGL_CORE_NATIVE_ENGINE = 0x305B;
+ public const int EGL_DEPTH_SIZE = 0x3025;
+// public const int EGL_DONT_CARE = -1;
+ public const int EGL_DRAW = 0x3059;
+ public const int EGL_EXTENSIONS = 0x3055;
+ public const int EGL_FALSE = 0;
+ public const int EGL_GREEN_SIZE = 0x3023;
+ public const int EGL_HEIGHT = 0x3056;
+// public const int EGL_LARGEST_PBUFFER = 0x3058;
+// public const int EGL_LEVEL = 0x3029;
+// public const int EGL_MAX_PBUFFER_HEIGHT = 0x302A;
+// public const int EGL_MAX_PBUFFER_PIXELS = 0x302B;
+// public const int EGL_MAX_PBUFFER_WIDTH = 0x302C;
+// public const int EGL_NATIVE_RENDERABLE = 0x302D;
+// public const int EGL_NATIVE_VISUAL_ID = 0x302E;
+// public const int EGL_NATIVE_VISUAL_TYPE = 0x302F;
+ public const int EGL_NONE = 0x3038;
+// public const int EGL_NON_CONFORMANT_CONFIG = 0x3051;
+ public const int EGL_NOT_INITIALIZED = 0x3001;
+ public const int EGL_NO_CONTEXT = 0;
+ public const int EGL_NO_DISPLAY = 0;
+ public const int EGL_NO_SURFACE = 0;
+ public const int EGL_PBUFFER_BIT = 0x0001;
+// public const int EGL_PIXMAP_BIT = 0x0002;
+ public const int EGL_READ = 0x305A;
+ public const int EGL_RED_SIZE = 0x3024;
+ public const int EGL_SAMPLES = 0x3031;
+// public const int EGL_SAMPLE_BUFFERS = 0x3032;
+// public const int EGL_SLOW_CONFIG = 0x3050;
+ public const int EGL_STENCIL_SIZE = 0x3026;
+ public const int EGL_SUCCESS = 0x3000;
+ public const int EGL_SURFACE_TYPE = 0x3033;
+// public const int EGL_TRANSPARENT_BLUE_VALUE = 0x3035;
+// public const int EGL_TRANSPARENT_GREEN_VALUE = 0x3036;
+// public const int EGL_TRANSPARENT_RED_VALUE = 0x3037;
+// public const int EGL_TRANSPARENT_RGB = 0x3052;
+// public const int EGL_TRANSPARENT_TYPE = 0x3034;
+ public const int EGL_TRUE = 1;
+// public const int EGL_VENDOR = 0x3053;
+// public const int EGL_VERSION = 0x3054;
+ public const int EGL_WIDTH = 0x3057;
+ public const int EGL_WINDOW_BIT = 0x0004;
- public const int EGL_BACK_BUFFER = 0x3084;
- public const int EGL_BIND_TO_TEXTURE_RGB = 0x3039;
- public const int EGL_BIND_TO_TEXTURE_RGBA = 0x303A;
- public const int EGL_CONTEXT_LOST = 0x300E;
- public const int EGL_MIN_SWAP_INTERVAL = 0x303B;
- public const int EGL_MAX_SWAP_INTERVAL = 0x303C;
- public const int EGL_MIPMAP_TEXTURE = 0x3082;
- public const int EGL_MIPMAP_LEVEL = 0x3083;
- public const int EGL_NO_TEXTURE = 0x305C;
- public const int EGL_TEXTURE_2D = 0x305F;
- public const int EGL_TEXTURE_FORMAT = 0x3080;
- public const int EGL_TEXTURE_RGB = 0x305D;
- public const int EGL_TEXTURE_RGBA = 0x305E;
- public const int EGL_TEXTURE_TARGET = 0x3081;
+// public const int EGL_BACK_BUFFER = 0x3084;
+// public const int EGL_BIND_TO_TEXTURE_RGB = 0x3039;
+// public const int EGL_BIND_TO_TEXTURE_RGBA = 0x303A;
+ public const int EGL_CONTEXT_LOST = 0x300E;
+// public const int EGL_MIN_SWAP_INTERVAL = 0x303B;
+// public const int EGL_MAX_SWAP_INTERVAL = 0x303C;
+// public const int EGL_MIPMAP_TEXTURE = 0x3082;
+// public const int EGL_MIPMAP_LEVEL = 0x3083;
+// public const int EGL_NO_TEXTURE = 0x305C;
+// public const int EGL_TEXTURE_2D = 0x305F;
+// public const int EGL_TEXTURE_FORMAT = 0x3080;
+// public const int EGL_TEXTURE_RGB = 0x305D;
+// public const int EGL_TEXTURE_RGBA = 0x305E;
+// public const int EGL_TEXTURE_TARGET = 0x3081;
- public const int EGL_ALPHA_FORMAT = 0x3088;
- public const int EGL_ALPHA_FORMAT_NONPRE = 0x308B;
- public const int EGL_ALPHA_FORMAT_PRE = 0x308C;
- public const int EGL_ALPHA_MASK_SIZE = 0x303E;
- public const int EGL_BUFFER_PRESERVED = 0x3094;
- public const int EGL_BUFFER_DESTROYED = 0x3095;
- public const int EGL_CLIENT_APIS = 0x308D;
- public const int EGL_COLORSPACE = 0x3087;
- public const int EGL_COLORSPACE_sRGB = 0x3089;
- public const int EGL_COLORSPACE_LINEAR = 0x308A;
- public const int EGL_COLOR_BUFFER_TYPE = 0x303F;
- public const int EGL_CONTEXT_CLIENT_TYPE = 0x3097;
- public const int EGL_DISPLAY_SCALING = 10000;
- public const int EGL_HORIZONTAL_RESOLUTION = 0x3090;
- public const int EGL_LUMINANCE_BUFFER = 0x308F;
- public const int EGL_LUMINANCE_SIZE = 0x303D;
- public const int EGL_OPENGL_ES_BIT = 0x0001;
- public const int EGL_OPENVG_BIT = 0x0002;
- public const int EGL_OPENGL_ES_API = 0x30A0;
- public const int EGL_OPENVG_API = 0x30A1;
- public const int EGL_OPENVG_IMAGE = 0x3096;
- public const int EGL_PIXEL_ASPECT_RATIO = 0x3092;
- public const int EGL_RENDERABLE_TYPE = 0x3040;
- public const int EGL_RENDER_BUFFER = 0x3086;
- public const int EGL_RGB_BUFFER = 0x308E;
- public const int EGL_SINGLE_BUFFER = 0x3085;
- public const int EGL_SWAP_BEHAVIOR = 0x3093;
- public const int EGL_UNKNOWN = -1;
- public const int EGL_VERTICAL_RESOLUTION = 0x3091;
- public const int EGL_CONFORMANT = 0x3042;
- public const int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- public const int EGL_MATCH_NATIVE_PIXMAP = 0x3041;
- public const int EGL_OPENGL_ES2_BIT = 0x0004;
- public const int EGL_VG_ALPHA_FORMAT = 0x3088;
- public const int EGL_VG_ALPHA_FORMAT_NONPRE = 0x308B;
- public const int EGL_VG_ALPHA_FORMAT_PRE = 0x308C;
- public const int EGL_VG_ALPHA_FORMAT_PRE_BIT = 0x0040;
- public const int EGL_VG_COLORSPACE = 0x3087;
- public const int EGL_VG_COLORSPACE_sRGB = 0x3089;
- public const int EGL_VG_COLORSPACE_LINEAR = 0x308A;
- public const int EGL_VG_COLORSPACE_LINEAR_BIT = 0x0020;
- public const int EGL_DEFAULT_DISPLAY = 0;
- public const int EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 0x0200;
- public const int EGL_MULTISAMPLE_RESOLVE = 0x3099;
- public const int EGL_MULTISAMPLE_RESOLVE_DEFAULT = 0x309A;
- public const int EGL_MULTISAMPLE_RESOLVE_BOX = 0x309B;
- public const int EGL_OPENGL_API = 0x30A2;
- public const int EGL_OPENGL_BIT = 0x0008;
- public const int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
- public const int EGL_CONTEXT_MAJOR_VERSION = 0x3098;
- public const int EGL_CONTEXT_MINOR_VERSION = 0x30FB;
- public const int EGL_CONTEXT_OPENGL_PROFILE_MASK = 0x30FD;
- public const int EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY = 0x31BD;
- public const int EGL_NO_RESET_NOTIFICATION = 0x31BE;
- public const int EGL_LOSE_CONTEXT_ON_RESET = 0x31BF;
- public const int EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT = 0x00000001;
- public const int EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT = 0x00000002;
- public const int EGL_CONTEXT_OPENGL_DEBUG = 0x31B0;
- public const int EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE = 0x31B1;
- public const int EGL_CONTEXT_OPENGL_ROBUST_ACCESS = 0x31B2;
- public const int EGL_OPENGL_ES3_BIT = 0x00000040;
- public const int EGL_CL_EVENT_HANDLE = 0x309C;
- public const int EGL_SYNC_CL_EVENT = 0x30FE;
- public const int EGL_SYNC_CL_EVENT_COMPLETE = 0x30FF;
- public const int EGL_SYNC_PRIOR_COMMANDS_COMPLETE = 0x30F0;
- public const int EGL_SYNC_TYPE = 0x30F7;
- public const int EGL_SYNC_STATUS = 0x30F1;
- public const int EGL_SYNC_CONDITION = 0x30F8;
- public const int EGL_SIGNALED = 0x30F2;
- public const int EGL_UNSIGNALED = 0x30F3;
+// public const int EGL_ALPHA_FORMAT = 0x3088;
+// public const int EGL_ALPHA_FORMAT_NONPRE = 0x308B;
+// public const int EGL_ALPHA_FORMAT_PRE = 0x308C;
+// public const int EGL_ALPHA_MASK_SIZE = 0x303E;
+// public const int EGL_BUFFER_PRESERVED = 0x3094;
+// public const int EGL_BUFFER_DESTROYED = 0x3095;
+// public const int EGL_CLIENT_APIS = 0x308D;
+// public const int EGL_COLORSPACE = 0x3087;
+// public const int EGL_COLORSPACE_sRGB = 0x3089;
+// public const int EGL_COLORSPACE_LINEAR = 0x308A;
+// public const int EGL_COLOR_BUFFER_TYPE = 0x303F;
+// public const int EGL_CONTEXT_CLIENT_TYPE = 0x3097;
+// public const int EGL_DISPLAY_SCALING = 10000;
+// public const int EGL_HORIZONTAL_RESOLUTION = 0x3090;
+// public const int EGL_LUMINANCE_BUFFER = 0x308F;
+// public const int EGL_LUMINANCE_SIZE = 0x303D;
+ public const int EGL_OPENGL_ES_BIT = 0x0001;
+// public const int EGL_OPENVG_BIT = 0x0002;
+ public const int EGL_OPENGL_ES_API = 0x30A0;
+// public const int EGL_OPENVG_API = 0x30A1;
+// public const int EGL_OPENVG_IMAGE = 0x3096;
+// public const int EGL_PIXEL_ASPECT_RATIO = 0x3092;
+ public const int EGL_RENDERABLE_TYPE = 0x3040;
+// public const int EGL_RENDER_BUFFER = 0x3086;
+// public const int EGL_RGB_BUFFER = 0x308E;
+// public const int EGL_SINGLE_BUFFER = 0x3085;
+// public const int EGL_SWAP_BEHAVIOR = 0x3093;
+// public const int EGL_UNKNOWN = -1;
+// public const int EGL_VERTICAL_RESOLUTION = 0x3091;
+// public const int EGL_CONFORMANT = 0x3042;
+// public const int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+// public const int EGL_MATCH_NATIVE_PIXMAP = 0x3041;
+ public const int EGL_OPENGL_ES2_BIT = 0x0004;
+// public const int EGL_VG_ALPHA_FORMAT = 0x3088;
+// public const int EGL_VG_ALPHA_FORMAT_NONPRE = 0x308B;
+// public const int EGL_VG_ALPHA_FORMAT_PRE = 0x308C;
+// public const int EGL_VG_ALPHA_FORMAT_PRE_BIT = 0x0040;
+// public const int EGL_VG_COLORSPACE = 0x3087;
+// public const int EGL_VG_COLORSPACE_sRGB = 0x3089;
+// public const int EGL_VG_COLORSPACE_LINEAR = 0x308A;
+// public const int EGL_VG_COLORSPACE_LINEAR_BIT = 0x0020;
+// public const int EGL_DEFAULT_DISPLAY = 0;
+// public const int EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 0x0200;
+// public const int EGL_MULTISAMPLE_RESOLVE = 0x3099;
+// public const int EGL_MULTISAMPLE_RESOLVE_DEFAULT = 0x309A;
+// public const int EGL_MULTISAMPLE_RESOLVE_BOX = 0x309B;
+// public const int EGL_OPENGL_API = 0x30A2;
+// public const int EGL_OPENGL_BIT = 0x0008;
+// public const int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
+ public const int EGL_CONTEXT_MAJOR_VERSION = 0x3098;
+ public const int EGL_CONTEXT_MINOR_VERSION = 0x30FB;
+// public const int EGL_CONTEXT_OPENGL_PROFILE_MASK = 0x30FD;
+// public const int EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY = 0x31BD;
+// public const int EGL_NO_RESET_NOTIFICATION = 0x31BE;
+// public const int EGL_LOSE_CONTEXT_ON_RESET = 0x31BF;
+// public const int EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT = 0x00000001;
+// public const int EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT = 0x00000002;
+// public const int EGL_CONTEXT_OPENGL_DEBUG = 0x31B0;
+// public const int EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE = 0x31B1;
+// public const int EGL_CONTEXT_OPENGL_ROBUST_ACCESS = 0x31B2;
+ public const int EGL_OPENGL_ES3_BIT = 0x00000040;
+// public const int EGL_CL_EVENT_HANDLE = 0x309C;
+// public const int EGL_SYNC_CL_EVENT = 0x30FE;
+// public const int EGL_SYNC_CL_EVENT_COMPLETE = 0x30FF;
+// public const int EGL_SYNC_PRIOR_COMMANDS_COMPLETE = 0x30F0;
+// public const int EGL_SYNC_TYPE = 0x30F7;
+// public const int EGL_SYNC_STATUS = 0x30F1;
+// public const int EGL_SYNC_CONDITION = 0x30F8;
+// public const int EGL_SIGNALED = 0x30F2;
+// public const int EGL_UNSIGNALED = 0x30F3;
- public const int EGL_SYNC_FLUSH_COMMANDS_BIT = 0x0001;
+// public const int EGL_SYNC_FLUSH_COMMANDS_BIT = 0x0001;
- public const int EGL_TIMEOUT_EXPIRED = 0x30F5;
- public const int EGL_CONDITION_SATISFIED = 0x30F6;
- public const int EGL_NO_SYNC = 0;
- public const int EGL_SYNC_FENCE = 0x30F9;
- public const int EGL_GL_COLORSPACE = 0x309D;
- public const int EGL_GL_COLORSPACE_SRGB = 0x3089;
- public const int EGL_GL_COLORSPACE_LINEAR = 0x308A;
- public const int EGL_GL_RENDERBUFFER = 0x30B9;
- public const int EGL_GL_TEXTURE_2D = 0x30B1;
- public const int EGL_GL_TEXTURE_LEVEL = 0x30BC;
- public const int EGL_GL_TEXTURE_3D = 0x30B2;
- public const int EGL_GL_TEXTURE_ZOFFSET = 0x30BD;
- public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x30B3;
- public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x30B4;
- public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x30B5;
- public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x30B6;
- public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x30B7;
- public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x30B8;
- public const int EGL_IMAGE_PRESERVED = 0x30D2;
- public const int EGL_NO_IMAGE = 0;
+// public const int EGL_TIMEOUT_EXPIRED = 0x30F5;
+// public const int EGL_CONDITION_SATISFIED = 0x30F6;
+// public const int EGL_NO_SYNC = 0;
+// public const int EGL_SYNC_FENCE = 0x30F9;
+// public const int EGL_GL_COLORSPACE = 0x309D;
+// public const int EGL_GL_COLORSPACE_SRGB = 0x3089;
+// public const int EGL_GL_COLORSPACE_LINEAR = 0x308A;
+// public const int EGL_GL_RENDERBUFFER = 0x30B9;
+// public const int EGL_GL_TEXTURE_2D = 0x30B1;
+// public const int EGL_GL_TEXTURE_LEVEL = 0x30BC;
+// public const int EGL_GL_TEXTURE_3D = 0x30B2;
+// public const int EGL_GL_TEXTURE_ZOFFSET = 0x30BD;
+// public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x30B3;
+// public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x30B4;
+// public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x30B5;
+// public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x30B6;
+// public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x30B7;
+// public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x30B8;
+// public const int EGL_IMAGE_PRESERVED = 0x30D2;
+// public const int EGL_NO_IMAGE = 0;
- public const int EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207;
- public const int EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208;
+ public const int EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207;
+ public const int EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208;
//EGL_ANGLE_platform_angle
- public const int EGL_PLATFORM_ANGLE_ANGLE = 0x3202;
- public const int EGL_PLATFORM_ANGLE_TYPE_ANGLE = 0x3203;
- public const int EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204;
- public const int EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205;
- public const int EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED = 0x3451;
- public const int EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206;
- public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A;
- public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE = 0x345E;
+ public const int EGL_PLATFORM_ANGLE_ANGLE = 0x3202;
+ public const int EGL_PLATFORM_ANGLE_TYPE_ANGLE = 0x3203;
+// public const int EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204;
+// public const int EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205;
+// public const int EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED = 0x3451;
+// public const int EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206;
+// public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A;
+// public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE = 0x345E;
- public const int EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE = 0x320D;
- public const int EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE = 0x320E;
+// public const int EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE = 0x320D;
+// public const int EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE = 0x320E;
//EGL_ANGLE_platform_angle_d3d
- public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209;
- public const int EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE = 0x320F;
- public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE = 0x320B;
- public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE = 0x320C;
+// public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209;
+// public const int EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE = 0x320F;
+// public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE = 0x320B;
+// public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE = 0x320C;
//EXT_device_query
- public const int EGL_DEVICE_EXT = 0x322C;
+ public const int EGL_DEVICE_EXT = 0x322C;
//ANGLE_device_d3d
- public const int EGL_D3D9_DEVICE_ANGLE = 0x33A0;
- public const int EGL_D3D11_DEVICE_ANGLE = 0x33A1;
+ public const int EGL_D3D9_DEVICE_ANGLE = 0x33A0;
+ public const int EGL_D3D11_DEVICE_ANGLE = 0x33A1;
- public const int EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE = 0x3200;
- public const int EGL_D3D_TEXTURE_ANGLE = 0x33A3;
+ public const int EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE = 0x3200;
+ public const int EGL_D3D_TEXTURE_ANGLE = 0x33A3;
- public const int EGL_TEXTURE_OFFSET_X_ANGLE = 0x3490;
- public const int EGL_TEXTURE_OFFSET_Y_ANGLE = 0x3491;
+ public const int EGL_TEXTURE_OFFSET_X_ANGLE = 0x3490;
+ public const int EGL_TEXTURE_OFFSET_Y_ANGLE = 0x3491;
- public const int EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE = 0x33A6;
+ public const int EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE = 0x33A6;
}
}
diff --git a/src/Avalonia.OpenGL/Egl/EglContext.cs b/src/Avalonia.OpenGL/Egl/EglContext.cs
index bc517c3e27..e7b5dc7c83 100644
--- a/src/Avalonia.OpenGL/Egl/EglContext.cs
+++ b/src/Avalonia.OpenGL/Egl/EglContext.cs
@@ -24,7 +24,7 @@ namespace Avalonia.OpenGL.Egl
SampleCount = sampleCount;
StencilSize = stencilSize;
using (MakeCurrent())
- GlInterface = GlInterface.FromNativeUtf8GetProcAddress(version, b => _egl.GetProcAddress(b));
+ GlInterface = GlInterface.FromNativeUtf8GetProcAddress(version, _egl.GetProcAddress);
}
public IntPtr Context { get; }
diff --git a/src/Avalonia.OpenGL/Egl/EglDisplay.cs b/src/Avalonia.OpenGL/Egl/EglDisplay.cs
index 623364866b..d3d85e8c83 100644
--- a/src/Avalonia.OpenGL/Egl/EglDisplay.cs
+++ b/src/Avalonia.OpenGL/Egl/EglDisplay.cs
@@ -34,9 +34,9 @@ namespace Avalonia.OpenGL.Egl
}
else
{
- if (egl.GetPlatformDisplayEXT == null)
+ if (!egl.IsGetPlatformDisplayExtAvailable)
throw new OpenGlException("eglGetPlatformDisplayEXT is not supported by libegl");
- display = egl.GetPlatformDisplayEXT(platformType, platformDisplay, attrs);
+ display = egl.GetPlatformDisplayExt(platformType, platformDisplay, attrs);
}
if (display == IntPtr.Zero)
diff --git a/src/Avalonia.OpenGL/Egl/EglInterface.cs b/src/Avalonia.OpenGL/Egl/EglInterface.cs
index 6148e58440..4fec8e5356 100644
--- a/src/Avalonia.OpenGL/Egl/EglInterface.cs
+++ b/src/Avalonia.OpenGL/Egl/EglInterface.cs
@@ -2,31 +2,26 @@
using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
+using Avalonia.SourceGenerator;
namespace Avalonia.OpenGL.Egl
{
- public class EglInterface : GlInterfaceBase
+ public unsafe partial class EglInterface
{
- public EglInterface() : base(Load())
+ public EglInterface(Func getProcAddress)
{
-
- }
-
- public EglInterface(Func getProcAddress) : base(getProcAddress)
- {
-
+ Initialize(getProcAddress);
}
- public EglInterface(Func getProcAddress) : base(getProcAddress)
+ public EglInterface(string library) : this(Load(library))
{
-
}
-
- public EglInterface(string library) : base(Load(library))
+
+ public EglInterface() : this(Load())
{
+
}
-
static Func Load()
{
var os = AvaloniaLocator.Current.GetService().GetRuntimeInfo().OperatingSystem;
@@ -46,119 +41,75 @@ namespace Avalonia.OpenGL.Egl
}
// ReSharper disable UnassignedGetOnlyAutoProperty
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate int EglGetError();
- [GlEntryPoint("eglGetError")]
- public EglGetError GetError { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglGetDisplay(IntPtr nativeDisplay);
- [GlEntryPoint("eglGetDisplay")]
- public EglGetDisplay GetDisplay { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglGetPlatformDisplayEXT(int platform, IntPtr nativeDisplay, int[] attrs);
- [GlEntryPoint("eglGetPlatformDisplayEXT")]
- [GlOptionalEntryPoint]
- public EglGetPlatformDisplayEXT GetPlatformDisplayEXT { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglInitialize(IntPtr display, out int major, out int minor);
- [GlEntryPoint("eglInitialize")]
- public EglInitialize Initialize { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglGetProcAddress(Utf8Buffer proc);
- [GlEntryPoint("eglGetProcAddress")]
- public EglGetProcAddress GetProcAddress { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglBindApi(int api);
- [GlEntryPoint("eglBindAPI")]
- public EglBindApi BindApi { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglChooseConfig(IntPtr display, int[] attribs,
- out IntPtr surfaceConfig, int numConfigs, out int choosenConfig);
- [GlEntryPoint("eglChooseConfig")]
- public EglChooseConfig ChooseConfig { get; }
+
+ [GetProcAddress("eglGetError")]
+ public partial int GetError();
+
+ [GetProcAddress("eglGetDisplay")]
+ public partial IntPtr GetDisplay(IntPtr nativeDisplay);
+
+ [GetProcAddress("eglGetPlatformDisplayEXT", true)]
+ public partial IntPtr GetPlatformDisplayExt(int platform, IntPtr nativeDisplay, int[] attrs);
+
+ [GetProcAddress("eglInitialize")]
+ public partial bool Initialize(IntPtr display, out int major, out int minor);
+
+ [GetProcAddress("eglGetProcAddress")]
+ public partial IntPtr GetProcAddress(IntPtr proc);
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglCreateContext(IntPtr display, IntPtr config,
+ [GetProcAddress("eglBindAPI")]
+ public partial bool BindApi(int api);
+
+ [GetProcAddress("eglChooseConfig")]
+ public partial bool ChooseConfig(IntPtr display, int[] attribs,
+ out IntPtr surfaceConfig, int numConfigs, out int choosenConfig);
+
+ [GetProcAddress("eglCreateContext")]
+ public partial IntPtr CreateContext(IntPtr display, IntPtr config,
IntPtr share, int[] attrs);
- [GlEntryPoint("eglCreateContext")]
- public EglCreateContext CreateContext { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglDestroyContext(IntPtr display, IntPtr context);
- [GlEntryPoint("eglDestroyContext")]
- public EglDestroyContext DestroyContext { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglCreatePBufferSurface(IntPtr display, IntPtr config, int[] attrs);
- [GlEntryPoint("eglCreatePbufferSurface")]
- public EglCreatePBufferSurface CreatePBufferSurface { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglMakeCurrent(IntPtr display, IntPtr draw, IntPtr read, IntPtr context);
- [GlEntryPoint("eglMakeCurrent")]
- public EglMakeCurrent MakeCurrent { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglGetCurrentContext();
- [GlEntryPoint("eglGetCurrentContext")]
- public EglGetCurrentContext GetCurrentContext { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglGetCurrentDisplay();
- [GlEntryPoint("eglGetCurrentDisplay")]
- public EglGetCurrentContext GetCurrentDisplay { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglGetCurrentSurface(int readDraw);
- [GlEntryPoint("eglGetCurrentSurface")]
- public EglGetCurrentSurface GetCurrentSurface { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate void EglDisplaySurfaceVoidDelegate(IntPtr display, IntPtr surface);
- [GlEntryPoint("eglDestroySurface")]
- public EglDisplaySurfaceVoidDelegate DestroySurface { get; }
-
- [GlEntryPoint("eglSwapBuffers")]
- public EglDisplaySurfaceVoidDelegate SwapBuffers { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr
- EglCreateWindowSurface(IntPtr display, IntPtr config, IntPtr window, int[] attrs);
- [GlEntryPoint("eglCreateWindowSurface")]
- public EglCreateWindowSurface CreateWindowSurface { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglGetConfigAttrib(IntPtr display, IntPtr config, int attr, out int rv);
- [GlEntryPoint("eglGetConfigAttrib")]
- public EglGetConfigAttrib GetConfigAttrib { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglWaitGL();
- [GlEntryPoint("eglWaitGL")]
- public EglWaitGL WaitGL { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglWaitClient();
- [GlEntryPoint("eglWaitClient")]
- public EglWaitGL WaitClient { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglWaitNative(int engine);
- [GlEntryPoint("eglWaitNative")]
- public EglWaitNative WaitNative { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglQueryString(IntPtr display, int i);
-
- [GlEntryPoint("eglQueryString")]
- public EglQueryString QueryStringNative { get; }
+
+ [GetProcAddress("eglDestroyContext")]
+ public partial bool DestroyContext(IntPtr display, IntPtr context);
+
+ [GetProcAddress("eglCreatePbufferSurface")]
+ public partial IntPtr CreatePBufferSurface(IntPtr display, IntPtr config, int[] attrs);
+ [GetProcAddress("eglMakeCurrent")]
+ public partial bool MakeCurrent(IntPtr display, IntPtr draw, IntPtr read, IntPtr context);
+
+ [GetProcAddress("eglGetCurrentContext")]
+ public partial IntPtr GetCurrentContext();
+
+ [GetProcAddress("eglGetCurrentDisplay")]
+ public partial IntPtr GetCurrentDisplay();
+
+ [GetProcAddress("eglGetCurrentSurface")]
+ public partial IntPtr GetCurrentSurface(int readDraw);
+
+ [GetProcAddress("eglDestroySurface")]
+ public partial void DestroySurface(IntPtr display, IntPtr surface);
+
+ [GetProcAddress("eglSwapBuffers")]
+ public partial void SwapBuffers(IntPtr display, IntPtr surface);
+
+ [GetProcAddress("eglCreateWindowSurface")]
+ public partial IntPtr CreateWindowSurface(IntPtr display, IntPtr config, IntPtr window, int[] attrs);
+
+ [GetProcAddress("eglGetConfigAttrib")]
+ public partial bool GetConfigAttrib(IntPtr display, IntPtr config, int attr, out int rv);
+
+ [GetProcAddress("eglWaitGL")]
+ public partial bool WaitGL();
+
+ [GetProcAddress("eglWaitClient")]
+ public partial bool WaitClient();
+
+ [GetProcAddress("eglWaitNative")]
+ public partial bool WaitNative(int engine);
+
+ [GetProcAddress("eglQueryString")]
+ public partial IntPtr QueryStringNative(IntPtr display, int i);
+
public string QueryString(IntPtr display, int i)
{
var rv = QueryStringNative(display, i);
@@ -166,25 +117,15 @@ namespace Avalonia.OpenGL.Egl
return null;
return Marshal.PtrToStringAnsi(rv);
}
+
+ [GetProcAddress("eglCreatePbufferFromClientBuffer")]
+ public partial IntPtr CreatePbufferFromClientBuffer(IntPtr display, int buftype, IntPtr buffer, IntPtr config, int[] attrib_list);
+
+ [GetProcAddress("eglQueryDisplayAttribEXT", true)]
+ public partial bool QueryDisplayAttribExt(IntPtr display, int attr, out IntPtr res);
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate IntPtr EglCreatePbufferFromClientBuffer(IntPtr display, int buftype, IntPtr buffer, IntPtr config, int[] attrib_list);
- [GlEntryPoint("eglCreatePbufferFromClientBuffer")]
-
- public EglCreatePbufferFromClientBuffer CreatePbufferFromClientBuffer { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglQueryDisplayAttribEXT(IntPtr display, int attr, out IntPtr res);
-
- [GlEntryPoint("eglQueryDisplayAttribEXT"), GlOptionalEntryPoint]
- public EglQueryDisplayAttribEXT QueryDisplayAttribExt { get; }
-
- [UnmanagedFunctionPointer(CallingConvention.StdCall)]
- public delegate bool EglQueryDeviceAttribEXT(IntPtr display, int attr, out IntPtr res);
-
- [GlEntryPoint("eglQueryDeviceAttribEXT"), GlOptionalEntryPoint]
- public EglQueryDisplayAttribEXT QueryDeviceAttribExt { get; }
-
- // ReSharper restore UnassignedGetOnlyAutoProperty
+
+ [GetProcAddress("eglQueryDeviceAttribEXT", true)]
+ public partial bool QueryDeviceAttribExt(IntPtr display, int attr, out IntPtr res);
}
}
diff --git a/src/Avalonia.OpenGL/GlBasicInfoInterface.cs b/src/Avalonia.OpenGL/GlBasicInfoInterface.cs
index aaba2ec09c..7a7110f15b 100644
--- a/src/Avalonia.OpenGL/GlBasicInfoInterface.cs
+++ b/src/Avalonia.OpenGL/GlBasicInfoInterface.cs
@@ -3,46 +3,24 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.Platform.Interop;
+using Avalonia.SourceGenerator;
namespace Avalonia.OpenGL
{
- public class GlBasicInfoInterface : GlBasicInfoInterface