Browse Source

Merge branch 'master' into colorpicker2

pull/8215/head
robloo 4 years ago
committed by GitHub
parent
commit
bf17d13df6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  2. 16
      src/Avalonia.Base/Rendering/ImmediateRenderer.cs
  3. 16
      src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs
  4. 13
      src/Avalonia.Base/VisualExtensions.cs
  5. 2
      src/Avalonia.Controls/Viewbox.cs
  6. 5
      src/Avalonia.X11/NativeDialogs/Gtk.cs
  7. 66
      src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs
  8. 26
      tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

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

@ -41,13 +41,17 @@ namespace ControlCatalog.Pages
this.FindControl<Button>("OpenFile").Click += async delegate
{
// Almost guaranteed to exist
var fullPath = Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName;
var initialFileName = fullPath == null ? null : System.IO.Path.GetFileName(fullPath);
var initialDirectory = fullPath == null ? null : System.IO.Path.GetDirectoryName(fullPath);
var result = await new OpenFileDialog()
{
Title = "Open file",
Filters = GetFilters(),
Directory = lastSelectedDirectory,
// Almost guaranteed to exist
InitialFileName = Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName
Directory = initialDirectory,
InitialFileName = initialFileName
}.ShowAsync(GetWindow());
results.Items = result;
resultsVisible.IsVisible = result?.Any() == true;
@ -83,7 +87,12 @@ namespace ControlCatalog.Pages
Title = "Select folder",
Directory = lastSelectedDirectory,
}.ShowAsync(GetWindow());
lastSelectedDirectory = result;
if (!string.IsNullOrEmpty(result))
{
lastSelectedDirectory = result;
}
results.Items = new [] { result };
resultsVisible.IsVisible = result != null;
};

16
src/Avalonia.Base/Rendering/ImmediateRenderer.cs

@ -277,18 +277,20 @@ namespace Avalonia.Rendering
var m = Matrix.CreateTranslation(visual.Bounds.Position);
var renderTransform = Matrix.Identity;
// this should be calculated BEFORE renderTransform
if (visual.HasMirrorTransform)
{
var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, visual.Bounds.Width, 0);
renderTransform *= mirrorMatrix;
}
if (visual.RenderTransform != null)
{
var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
var offset = Matrix.CreateTranslation(origin);
renderTransform = (-offset) * visual.RenderTransform.Value * (offset);
}
if (visual.HasMirrorTransform)
{
var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, visual.Bounds.Width, 0);
renderTransform *= mirrorMatrix;
var finalTransform = (-offset) * visual.RenderTransform.Value * (offset);
renderTransform *= finalTransform;
}
m = renderTransform * m;

16
src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs

@ -188,19 +188,21 @@ namespace Avalonia.Rendering.SceneGraph
var renderTransform = Matrix.Identity;
if (visual.RenderTransform != null)
{
var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
var offset = Matrix.CreateTranslation(origin);
renderTransform = (-offset) * visual.RenderTransform.Value * (offset);
}
// this should be calculated BEFORE renderTransform
if (visual.HasMirrorTransform)
{
var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, visual.Bounds.Width, 0);
renderTransform *= mirrorMatrix;
}
if (visual.RenderTransform != null)
{
var origin = visual.RenderTransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
var offset = Matrix.CreateTranslation(origin);
var finalTransform = (-offset) * visual.RenderTransform.Value * (offset);
renderTransform *= finalTransform;
}
m = renderTransform * m;
using (contextImpl.BeginUpdate(node))

13
src/Avalonia.Base/VisualExtensions.cs

@ -101,6 +101,13 @@ namespace Avalonia
while (v != ancestor)
{
// this should be calculated BEFORE renderTransform
if (v.HasMirrorTransform)
{
var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, v.Bounds.Width, 0);
result *= mirrorMatrix;
}
if (v.RenderTransform?.Value != null)
{
var origin = v.RenderTransformOrigin.ToPixels(v.Bounds.Size);
@ -110,12 +117,6 @@ namespace Avalonia
result *= renderTransform;
}
if (v.HasMirrorTransform)
{
var mirrorMatrix = new Matrix(-1.0, 0.0, 0.0, 1.0, v.Bounds.Width, 0);
result *= mirrorMatrix;
}
var topLeft = v.Bounds.TopLeft;
if (topLeft != default)

2
src/Avalonia.Controls/Viewbox.cs

@ -168,6 +168,8 @@ namespace Avalonia.Controls
if (_child is not null)
VisualChildren.Add(_child);
InvalidateMeasure();
}
}
}

5
src/Avalonia.X11/NativeDialogs/Gtk.cs

@ -195,7 +195,10 @@ namespace Avalonia.X11.NativeDialogs
[DllImport(GtkName)]
public static extern void gtk_file_chooser_set_current_name(IntPtr chooser, Utf8Buffer file);
[DllImport(GtkName)]
public static extern void gtk_file_chooser_set_current_folder(IntPtr chooser, Utf8Buffer file);
[DllImport(GtkName)]
public static extern IntPtr gtk_file_filter_new();

66
src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs

@ -15,8 +15,9 @@ namespace Avalonia.X11.NativeDialogs
class GtkSystemDialog : ISystemDialogImpl
{
private Task<bool> _initialized;
private unsafe Task<string[]> ShowDialog(string title, IWindowImpl parent, GtkFileChooserAction action,
bool multiSelect, string initialFileName, IEnumerable<FileDialogFilter> filters, string defaultExtension, bool overwritePrompt)
private unsafe Task<string[]> ShowDialog(string title, IWindowImpl parent, GtkFileChooserAction action,
bool multiSelect, string initialDirectory, string initialFileName, IEnumerable<FileDialogFilter> filters, string defaultExtension, bool overwritePrompt)
{
IntPtr dlg;
using (var name = new Utf8Buffer(title))
@ -44,7 +45,7 @@ namespace Avalonia.X11.NativeDialogs
filtersDic[filter] = f;
using (var b = new Utf8Buffer(f.Name))
gtk_file_filter_set_name(filter, b);
foreach (var e in f.Extensions)
using (var b = new Utf8Buffer("*." + e))
gtk_file_filter_add_pattern(filter, b);
@ -100,17 +101,32 @@ namespace Avalonia.X11.NativeDialogs
gtk_dialog_add_button(dlg, open, GtkResponseType.Accept);
using (var open = new Utf8Buffer("Cancel"))
gtk_dialog_add_button(dlg, open, GtkResponseType.Cancel);
if (initialDirectory != null)
{
using var dir = new Utf8Buffer(initialDirectory);
gtk_file_chooser_set_current_folder(dlg, dir);
}
if (initialFileName != null)
using (var fn = new Utf8Buffer(initialFileName))
{
// gtk_file_chooser_set_filename() expects full path
using var fn = action == GtkFileChooserAction.Open
? new Utf8Buffer(Path.Combine(initialDirectory ?? "", initialFileName))
: new Utf8Buffer(initialFileName);
if (action == GtkFileChooserAction.Save)
{
if (action == GtkFileChooserAction.Save)
gtk_file_chooser_set_current_name(dlg, fn);
else
gtk_file_chooser_set_filename(dlg, fn);
gtk_file_chooser_set_current_name(dlg, fn);
}
else
{
gtk_file_chooser_set_filename(dlg, fn);
}
}
gtk_file_chooser_set_do_overwrite_confirmation(dlg, overwritePrompt);
gtk_window_present(dlg);
return tcs.Task;
}
@ -144,13 +160,15 @@ namespace Avalonia.X11.NativeDialogs
var platformImpl = parent?.PlatformImpl;
return await await RunOnGlibThread(
() => ShowDialog(dialog.Title, platformImpl,
dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save,
(dialog as OpenFileDialog)?.AllowMultiple ?? false,
Path.Combine(string.IsNullOrEmpty(dialog.Directory) ? "" : dialog.Directory,
string.IsNullOrEmpty(dialog.InitialFileName) ? "" : dialog.InitialFileName), dialog.Filters,
(dialog as SaveFileDialog)?.DefaultExtension, (dialog as SaveFileDialog)?.ShowOverwritePrompt ?? false));
return await await RunOnGlibThread(() => ShowDialog(
dialog.Title, platformImpl,
dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save,
(dialog as OpenFileDialog)?.AllowMultiple ?? false,
dialog.Directory,
dialog.InitialFileName,
dialog.Filters,
(dialog as SaveFileDialog)?.DefaultExtension,
(dialog as SaveFileDialog)?.ShowOverwritePrompt ?? false));
}
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, Window parent)
@ -161,12 +179,20 @@ namespace Avalonia.X11.NativeDialogs
return await await RunOnGlibThread(async () =>
{
var res = await ShowDialog(dialog.Title, platformImpl,
GtkFileChooserAction.SelectFolder, false, dialog.Directory, null, null, false);
var res = await ShowDialog(
dialog.Title,
platformImpl,GtkFileChooserAction.SelectFolder,
false,
dialog.Directory,
null,
null,
null,
false);
return res?.FirstOrDefault();
});
}
async Task EnsureInitialized()
{
if (_initialized == null) _initialized = StartGtk();
@ -174,7 +200,7 @@ namespace Avalonia.X11.NativeDialogs
if (!(await _initialized))
throw new Exception("Unable to initialize GTK on separate thread");
}
void UpdateParent(IntPtr chooser, IWindowImpl parentWindow)
{
var xid = parentWindow.Handle.Handle;

26
tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

@ -181,6 +181,32 @@ namespace Avalonia.Controls.UnitTests
Assert.Null(child.GetLogicalParent());
}
[Fact]
public void Changing_Child_Should_Invalidate_Layout()
{
var target = new Viewbox();
target.Child = new Canvas
{
Width = 100,
Height = 100,
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(100, 100), target.DesiredSize);
target.Child = new Canvas
{
Width = 200,
Height = 200,
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(200, 200), target.DesiredSize);
}
private bool TryGetScale(Viewbox viewbox, out Vector scale)
{
if (viewbox.InternalTransform is null)

Loading…
Cancel
Save