Browse Source

Merge branch 'master' into box-shadow

pull/3871/head
danwalmsley 6 years ago
committed by GitHub
parent
commit
5e7a827d11
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      samples/ControlCatalog/Pages/DialogsPage.xaml
  2. 14
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  3. 12
      src/Avalonia.Dialogs/ManagedFileChooserViewModel.cs
  4. 20
      src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
  5. 7
      src/Avalonia.Dialogs/ManagedFileDialogOptions.cs
  6. 18
      src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
  7. 20
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs
  8. 25
      src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs
  9. 4
      src/Avalonia.X11/X11Window.cs
  10. 2
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  11. 2
      src/Skia/Avalonia.Skia/SkiaOptions.cs

1
samples/ControlCatalog/Pages/DialogsPage.xaml

@ -6,6 +6,7 @@
<Button Name="OpenFile">Open File</Button> <Button Name="OpenFile">Open File</Button>
<Button Name="SaveFile">Save File</Button> <Button Name="SaveFile">Save File</Button>
<Button Name="SelectFolder">Select Folder</Button> <Button Name="SelectFolder">Select Folder</Button>
<Button Name="OpenBoth">Select Both</Button>
<Button Name="DecoratedWindow">Decorated window</Button> <Button Name="DecoratedWindow">Decorated window</Button>
<Button Name="DecoratedWindowDialog">Decorated window (dialog)</Button> <Button Name="DecoratedWindowDialog">Decorated window (dialog)</Button>
<Button Name="Dialog">Dialog</Button> <Button Name="Dialog">Dialog</Button>

14
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Dialogs;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
#pragma warning disable 4014 #pragma warning disable 4014
@ -58,6 +59,19 @@ namespace ControlCatalog.Pages
Title = "Select folder", Title = "Select folder",
}.ShowAsync(GetWindow()); }.ShowAsync(GetWindow());
}; };
this.FindControl<Button>("OpenBoth").Click += async delegate
{
var res = await new OpenFileDialog()
{
Title = "Select both",
AllowMultiple = true
}.ShowManagedAsync(GetWindow(), new ManagedFileDialogOptions
{
AllowDirectorySelection = true
});
if (res != null)
Console.WriteLine("Selected: \n" + string.Join("\n", res));
};
this.FindControl<Button>("DecoratedWindow").Click += delegate this.FindControl<Button>("DecoratedWindow").Click += delegate
{ {
new DecoratedWindow().Show(); new DecoratedWindow().Show();

12
src/Avalonia.Dialogs/ManagedFileChooserViewModel.cs

@ -14,6 +14,7 @@ namespace Avalonia.Dialogs
{ {
internal class ManagedFileChooserViewModel : InternalViewModelBase internal class ManagedFileChooserViewModel : InternalViewModelBase
{ {
private readonly ManagedFileDialogOptions _options;
public event Action CancelRequested; public event Action CancelRequested;
public event Action<string[]> CompleteRequested; public event Action<string[]> CompleteRequested;
@ -103,8 +104,9 @@ namespace Avalonia.Dialogs
QuickLinks.AddRange(quickSources.GetAllItems().Select(i => new ManagedFileChooserItemViewModel(i))); QuickLinks.AddRange(quickSources.GetAllItems().Select(i => new ManagedFileChooserItemViewModel(i)));
} }
public ManagedFileChooserViewModel(FileSystemDialog dialog) public ManagedFileChooserViewModel(FileSystemDialog dialog, ManagedFileDialogOptions options)
{ {
_options = options;
_disposables = new CompositeDisposable(); _disposables = new CompositeDisposable();
var quickSources = AvaloniaLocator.Current var quickSources = AvaloniaLocator.Current
@ -202,10 +204,12 @@ namespace Avalonia.Dialogs
} }
else else
{ {
var invalidItems = SelectedItems.Where(i => i.ItemType == ManagedFileChooserItemType.Folder).ToList(); if (!_options.AllowDirectorySelection)
foreach (var item in invalidItems)
{ {
SelectedItems.Remove(item); var invalidItems = SelectedItems.Where(i => i.ItemType == ManagedFileChooserItemType.Folder)
.ToList();
foreach (var item in invalidItems)
SelectedItems.Remove(item);
} }
if (!_selectingDirectory) if (!_selectingDirectory)

20
src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs

@ -9,13 +9,15 @@ namespace Avalonia.Dialogs
{ {
private class ManagedSystemDialogImpl<T> : ISystemDialogImpl where T : Window, new() private class ManagedSystemDialogImpl<T> : ISystemDialogImpl where T : Window, new()
{ {
async Task<string[]> Show(SystemDialog d, Window parent) async Task<string[]> Show(SystemDialog d, Window parent, ManagedFileDialogOptions options = null)
{ {
var model = new ManagedFileChooserViewModel((FileSystemDialog)d); var model = new ManagedFileChooserViewModel((FileSystemDialog)d,
options ?? new ManagedFileDialogOptions());
var dialog = new T var dialog = new T
{ {
Content = new ManagedFileChooser(), Content = new ManagedFileChooser(),
Title = d.Title,
DataContext = model DataContext = model
}; };
@ -44,6 +46,11 @@ namespace Avalonia.Dialogs
{ {
return (await Show(dialog, parent))?.FirstOrDefault(); return (await Show(dialog, parent))?.FirstOrDefault();
} }
public async Task<string[]> ShowFileDialogAsync(FileDialog dialog, Window parent, ManagedFileDialogOptions options)
{
return await Show(dialog, parent, options);
}
} }
public static TAppBuilder UseManagedSystemDialogs<TAppBuilder>(this TAppBuilder builder) public static TAppBuilder UseManagedSystemDialogs<TAppBuilder>(this TAppBuilder builder)
@ -61,5 +68,14 @@ namespace Avalonia.Dialogs
AvaloniaLocator.CurrentMutable.Bind<ISystemDialogImpl>().ToSingleton<ManagedSystemDialogImpl<TWindow>>()); AvaloniaLocator.CurrentMutable.Bind<ISystemDialogImpl>().ToSingleton<ManagedSystemDialogImpl<TWindow>>());
return builder; return builder;
} }
public static Task<string[]> ShowManagedAsync(this OpenFileDialog dialog, Window parent,
ManagedFileDialogOptions options = null) => ShowManagedAsync<Window>(dialog, parent, options);
public static Task<string[]> ShowManagedAsync<TWindow>(this OpenFileDialog dialog, Window parent,
ManagedFileDialogOptions options = null) where TWindow : Window, new()
{
return new ManagedSystemDialogImpl<TWindow>().ShowFileDialogAsync(dialog, parent, options);
}
} }
} }

7
src/Avalonia.Dialogs/ManagedFileDialogOptions.cs

@ -0,0 +1,7 @@
namespace Avalonia.Dialogs
{
public class ManagedFileDialogOptions
{
public bool AllowDirectorySelection { get; set; }
}
}

18
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@ -12,7 +12,7 @@ namespace Avalonia.Rendering.SceneGraph
/// </summary> /// </summary>
public class Scene : IDisposable public class Scene : IDisposable
{ {
private Dictionary<IVisual, IVisualNode> _index; private readonly Dictionary<IVisual, IVisualNode> _index;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Scene"/> class. /// Initializes a new instance of the <see cref="Scene"/> class.
@ -83,7 +83,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <returns>The cloned scene.</returns> /// <returns>The cloned scene.</returns>
public Scene CloneScene() public Scene CloneScene()
{ {
var index = new Dictionary<IVisual, IVisualNode>(); var index = new Dictionary<IVisual, IVisualNode>(_index.Count);
var root = Clone((VisualNode)Root, null, index); var root = Clone((VisualNode)Root, null, index);
var result = new Scene(root, index, Layers.Clone(), Generation + 1) var result = new Scene(root, index, Layers.Clone(), Generation + 1)
@ -162,9 +162,19 @@ namespace Avalonia.Rendering.SceneGraph
index.Add(result.Visual, result); index.Add(result.Visual, result);
foreach (var child in source.Children) var children = source.Children;
var childrenCount = children.Count;
if (childrenCount > 0)
{ {
result.AddChild(Clone((VisualNode)child, result, index)); result.TryPreallocateChildren(childrenCount);
for (var i = 0; i < childrenCount; i++)
{
var child = children[i];
result.AddChild(Clone((VisualNode)child, result, index));
}
} }
return result; return result;

20
src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs

@ -11,16 +11,28 @@ namespace Avalonia.Rendering.SceneGraph
public class SceneLayers : IEnumerable<SceneLayer> public class SceneLayers : IEnumerable<SceneLayer>
{ {
private readonly IVisual _root; private readonly IVisual _root;
private readonly List<SceneLayer> _inner = new List<SceneLayer>(); private readonly List<SceneLayer> _inner;
private readonly Dictionary<IVisual, SceneLayer> _index = new Dictionary<IVisual, SceneLayer>(); private readonly Dictionary<IVisual, SceneLayer> _index;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SceneLayers"/> class. /// Initializes a new instance of the <see cref="SceneLayers"/> class.
/// </summary> /// </summary>
/// <param name="root">The scene's root visual.</param> /// <param name="root">The scene's root visual.</param>
public SceneLayers(IVisual root) public SceneLayers(IVisual root) : this(root, 0)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SceneLayers"/> class.
/// </summary>
/// <param name="root">The scene's root visual.</param>
/// <param name="capacity">Initial layer capacity.</param>
public SceneLayers(IVisual root, int capacity)
{ {
_root = root; _root = root;
_inner = new List<SceneLayer>(capacity);
_index = new Dictionary<IVisual, SceneLayer>(capacity);
} }
/// <summary> /// <summary>
@ -84,7 +96,7 @@ namespace Avalonia.Rendering.SceneGraph
/// <returns>The cloned layers.</returns> /// <returns>The cloned layers.</returns>
public SceneLayers Clone() public SceneLayers Clone()
{ {
var result = new SceneLayers(_root); var result = new SceneLayers(_root, Count);
foreach (var src in _inner) foreach (var src in _inner)
{ {

25
src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables; using System.Reactive.Disposables;
using Avalonia.Collections;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Utilities; using Avalonia.Utilities;
@ -349,6 +349,11 @@ namespace Avalonia.Rendering.SceneGraph
context.Transform = transformRestore; context.Transform = transformRestore;
} }
internal void TryPreallocateChildren(int count)
{
EnsureChildrenCreated(count);
}
private Rect CalculateBounds() private Rect CalculateBounds()
{ {
var result = new Rect(); var result = new Rect();
@ -362,11 +367,11 @@ namespace Avalonia.Rendering.SceneGraph
return result; return result;
} }
private void EnsureChildrenCreated() private void EnsureChildrenCreated(int capacity = 0)
{ {
if (_children == null) if (_children == null)
{ {
_children = new List<IVisualNode>(); _children = new List<IVisualNode>(capacity);
} }
} }
@ -383,7 +388,15 @@ namespace Avalonia.Rendering.SceneGraph
} }
else if (_drawOperationsCloned) else if (_drawOperationsCloned)
{ {
_drawOperations = new List<IRef<IDrawOperation>>(_drawOperations.Select(op => op.Clone())); var oldDrawOperations = _drawOperations;
_drawOperations = new List<IRef<IDrawOperation>>(oldDrawOperations.Count);
foreach (var drawOperation in oldDrawOperations)
{
_drawOperations.Add(drawOperation.Clone());
}
_drawOperationsRefCounter.Dispose(); _drawOperationsRefCounter.Dispose();
_drawOperationsRefCounter = RefCountable.Create(CreateDisposeDrawOperations(_drawOperations)); _drawOperationsRefCounter = RefCountable.Create(CreateDisposeDrawOperations(_drawOperations));
_drawOperationsCloned = false; _drawOperationsCloned = false;
@ -399,9 +412,9 @@ namespace Avalonia.Rendering.SceneGraph
/// <returns>Disposable for given draw operations.</returns> /// <returns>Disposable for given draw operations.</returns>
private static IDisposable CreateDisposeDrawOperations(List<IRef<IDrawOperation>> drawOperations) private static IDisposable CreateDisposeDrawOperations(List<IRef<IDrawOperation>> drawOperations)
{ {
return Disposable.Create(() => return Disposable.Create(drawOperations, operations =>
{ {
foreach (var operation in drawOperations) foreach (var operation in operations)
{ {
operation.Dispose(); operation.Dispose();
} }

4
src/Avalonia.X11/X11Window.cs

@ -328,7 +328,9 @@ namespace Avalonia.X11
} }
else if (ev.type == XEventName.UnmapNotify) else if (ev.type == XEventName.UnmapNotify)
_mapped = false; _mapped = false;
else if (ev.type == XEventName.Expose) else if (ev.type == XEventName.Expose ||
(ev.type == XEventName.VisibilityNotify &&
ev.VisibilityEvent.state < 2))
{ {
if (!_triggeredExpose) if (!_triggeredExpose)
{ {

2
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -18,7 +18,7 @@ namespace Avalonia.Skia
private GRContext GrContext { get; } private GRContext GrContext { get; }
public PlatformRenderInterface(ICustomSkiaGpu customSkiaGpu, long maxResourceBytes = 100000000) public PlatformRenderInterface(ICustomSkiaGpu customSkiaGpu, long maxResourceBytes = 100663296)
{ {
if (customSkiaGpu != null) if (customSkiaGpu != null)
{ {

2
src/Skia/Avalonia.Skia/SkiaOptions.cs

@ -10,7 +10,7 @@ namespace Avalonia
{ {
public SkiaOptions() public SkiaOptions()
{ {
MaxGpuResourceSizeBytes = 512000000; MaxGpuResourceSizeBytes = 100663296; // Value taken from skia.
} }
/// <summary> /// <summary>
/// Custom gpu factory to use. Can be used to customize behavior of Skia renderer. /// Custom gpu factory to use. Can be used to customize behavior of Skia renderer.

Loading…
Cancel
Save