diff --git a/.gitignore b/.gitignore index 1d74816204..5fa78979c3 100644 --- a/.gitignore +++ b/.gitignore @@ -159,6 +159,12 @@ $RECYCLE.BIN/ *.userprefs *.nugetreferenceswitcher + +################# +## Rider +################# +.idea + ################# ## Cake ################# diff --git a/.travis.yml b/.travis.yml index a3c02eea58..52a400d19a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,13 +3,14 @@ os: - linux - osx dist: trusty +osx_image: xcode8.3 env: global: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 - DOTNET_CLI_TELEMETRY_OPTOUT=1 mono: - latest -dotnet: 1.0.1 +dotnet: 2.0.0 script: - ./build.sh --target "Travis" --platform "Mono" --configuration "Release" notifications: diff --git a/appveyor.yml b/appveyor.yml index 7457a1d5bb..ca548b6b0a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,9 +17,9 @@ init: - ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")} install: - if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi - - if not exist dotnet-1.0.1.exe appveyor DownloadFile https://go.microsoft.com/fwlink/?linkid=843448 -FileName "dotnet-1.0.1.exe" + - if not exist dotnet-2.0.0.exe appveyor DownloadFile https://download.microsoft.com/download/0/F/D/0FD852A4-7EA1-4E2A-983A-0484AC19B92C/dotnet-sdk-2.0.0-win-x64.exe -FileName "dotnet-2.0.0.exe" - ps: Start-Process -FilePath "msiexec" -ArgumentList "/i gtk-sharp-2.12.26.msi /quiet /qn /norestart" -Wait - - ps: Start-Process -FilePath "dotnet-1.0.1.exe" -ArgumentList "/quiet" -Wait + - ps: Start-Process -FilePath "dotnet-2.0.0.exe" -ArgumentList "/quiet" -Wait - cmd: set PATH=%programfiles(x86)%\GtkSharp\2.12\bin\;%PATH% before_build: - git submodule update --init diff --git a/build.cake b/build.cake index 4e18f23780..b7b349b12b 100644 --- a/build.cake +++ b/build.cake @@ -162,7 +162,7 @@ void RunCoreTest(string project, Parameters parameters, bool coreOnly = false) project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj"); Information("Running tests from " + project); DotNetCoreRestore(project); - var frameworks = new List(){"netcoreapp1.1"}; + var frameworks = new List(){"netcoreapp2.0"}; if(parameters.IsRunningOnWindows) frameworks.Add("net461"); foreach(var fw in frameworks) diff --git a/build/XUnit.props b/build/XUnit.props index d59cee6536..9d4d401743 100644 --- a/build/XUnit.props +++ b/build/XUnit.props @@ -9,7 +9,7 @@ - + diff --git a/docs/guidelines/build.md b/docs/guidelines/build.md index 822496814b..0cf91d913a 100644 --- a/docs/guidelines/build.md +++ b/docs/guidelines/build.md @@ -80,10 +80,11 @@ mono ./samples/ControlCatalog.Desktop/bin/Debug/ControlCatalog.Desktop.exe ### Building Avalonia in MonoDevelop -Unless you have a very current version of monodevelop (6.1.x or newer), it is necessary to manually -restore the Nuget depdendencies as [mentioned above](#restore-nuget-packages). You must then -disable MonoDevelop's inbuilt NuGet package manager add-in by going to `Tools -> Add-in Manager` or -it will complain that a newer version of NuGet is needed. +Flatpak version will *NOT* work. Version from https://github.com/cra0zy/monodevelop-run-installer/ might work if you are very lucky. Make sure that you have the latest version of Mono (from alpha update channel) and .NET Core SDK. Make sure to follow `FrameworkPathOverride` workaround from https://github.com/dotnet/sdk/issues/335 + +### Building and running Avalonia in Rider + +For Linux/OSX you'll probably need to apply workaround from https://github.com/dotnet/sdk/issues/335 + +Just add `export FrameworkPathOverride=/usr/lib/mono/4.6.1-api` (or `export FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api` for OSX) -Finally, select the `Debug | Mono` or `Release | Mono` build configuration and you should be good to -go! diff --git a/packages.cake b/packages.cake index 22a519802f..2c0298b669 100644 --- a/packages.cake +++ b/packages.cake @@ -43,7 +43,6 @@ public class Packages } } - //new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" }, public Packages(ICakeContext context, Parameters parameters) { // NUGET NUSPECS @@ -186,12 +185,12 @@ public class Packages }; var coreLibrariesFiles = coreLibraries.Select((lib) => { - return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/netstandard1.3/" + lib[1] + lib[2]); + return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/netstandard2.0/" + lib[1] + lib[2]); }).ToList(); var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => { return new NuSpecContent { - Source = file.FullPath, Target = "lib/netstandard1.3" + Source = file.FullPath, Target = "lib/netstandard2.0" }; }); @@ -203,14 +202,14 @@ public class Packages var netcoreappCoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => { return new NuSpecContent { - Source = file.FullPath, Target = "lib/netcoreapp1.0" + Source = file.FullPath, Target = "lib/netcoreapp2.0" }; }); var net45RuntimePlatformExtensions = new [] {".xml", ".dll"}; var net45RuntimePlatform = net45RuntimePlatformExtensions.Select(libSuffix => { return new NuSpecContent { - Source = ((FilePath)context.File("./src/Avalonia.DotNetFrameworkRuntime/bin/" + parameters.DirSuffix + "/Avalonia.DotNetFrameworkRuntime" + libSuffix)).FullPath, + Source = ((FilePath)context.File("./src/Avalonia.DotNetFrameworkRuntime/bin/" + parameters.DirSuffix + "/net461/Avalonia.DotNetFrameworkRuntime" + libSuffix)).FullPath, Target = "lib/net45" }; }); @@ -218,8 +217,8 @@ public class Packages var netCoreRuntimePlatformExtensions = new [] {".xml", ".dll"}; var netCoreRuntimePlatform = netCoreRuntimePlatformExtensions.Select(libSuffix => { return new NuSpecContent { - Source = ((FilePath)context.File("./src/Avalonia.DotNetCoreRuntime/bin/" + parameters.DirSuffix + "/netcoreapp1.0/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath, - Target = "lib/netcoreapp1.0" + Source = ((FilePath)context.File("./src/Avalonia.DotNetCoreRuntime/bin/" + parameters.DirSuffix + "/netcoreapp2.0/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath, + Target = "lib/netcoreapp2.0" }; }); @@ -238,15 +237,15 @@ public class Packages new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion }, new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion }, //.NET Core - new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" }, - new NuSpecDependency() { Id = "Microsoft.Extensions.DependencyModel", TargetFramework = "netcoreapp1.0", Version = "1.1.0" }, - new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" }, - new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = SplatVersion }, - new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = SerilogVersion }, - new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp1.0", Version = SpracheVersion }, - new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp1.0", Version = SystemReactiveVersion }, + new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp2.0", Version = "4.3.0" }, + new NuSpecDependency() { Id = "Microsoft.Extensions.DependencyModel", TargetFramework = "netcoreapp2.0", Version = "1.1.0" }, + new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp2.0", Version = "1.6.0" }, + new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp2.0", Version = SplatVersion }, + new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp2.0", Version = SerilogVersion }, + new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp2.0", Version = SpracheVersion }, + new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp2.0", Version = SystemReactiveVersion }, } - .Deps(new string[]{null, "netcoreapp1.0"}, + .Deps(new string[]{null, "netcoreapp2.0"}, "System.ValueTuple", "System.ComponentModel.TypeConverter", "System.ComponentModel.Primitives", "System.Runtime.Serialization.Primitives", "System.Xml.XmlDocument", "System.Xml.ReaderWriter") .ToArray(), @@ -269,9 +268,9 @@ public class Packages }, Files = new [] { - new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/netstandard1.3" } + new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/netstandard2.0" } }, - BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix + "/netstandard1.3"), + BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix + "/netstandard2.0"), OutputDirectory = parameters.NugetRoot } }; @@ -331,7 +330,7 @@ public class Packages Files = new [] { new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" }, - new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.Win32.dll", Target = "lib/netstandard1.3" } + new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.Win32.dll", Target = "lib/netstandard2.0" } }, BasePath = context.Directory("./src/Windows"), OutputDirectory = parameters.NugetRoot @@ -352,9 +351,9 @@ public class Packages }, Files = new [] { - new NuSpecContent { Source = "Avalonia.Direct2D1.dll", Target = "lib/netstandard1.3" } + new NuSpecContent { Source = "Avalonia.Direct2D1.dll", Target = "lib/netstandard2.0" } }, - BasePath = context.Directory("./src/Windows/Avalonia.Direct2D1/bin/" + parameters.DirSuffix + "/netstandard1.3"), + BasePath = context.Directory("./src/Windows/Avalonia.Direct2D1/bin/" + parameters.DirSuffix + "/netstandard2.0"), OutputDirectory = parameters.NugetRoot }, /////////////////////////////////////////////////////////////////////////////// @@ -386,9 +385,9 @@ public class Packages }, Files = new [] { - new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard1.3" } + new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard2.0" } }, - BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix + "/netstandard1.3"), + BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix + "/netstandard2.0"), OutputDirectory = parameters.NugetRoot }, /////////////////////////////////////////////////////////////////////////////// @@ -418,18 +417,18 @@ public class Packages { new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }, new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }, - new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version, TargetFramework="netcoreapp1.1" }, - new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion, TargetFramework="netcoreapp1.1" }, - new NuSpecDependency() { Id = "Avalonia.Skia.Linux.Natives", Version = SkiaSharpLinuxVersion, TargetFramework="netcoreapp1.1" }, + new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version, TargetFramework="netcoreapp2.0" }, + new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion, TargetFramework="netcoreapp2.0" }, + new NuSpecDependency() { Id = "Avalonia.Skia.Linux.Natives", Version = SkiaSharpLinuxVersion, TargetFramework="netcoreapp2.0" }, new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version, TargetFramework="net461" }, new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion, TargetFramework="net461" }, new NuSpecDependency() { Id = "Avalonia.Skia.Linux.Natives", Version = SkiaSharpLinuxVersion, TargetFramework="net461" } }, Files = new [] { - new NuSpecContent { Source = "Avalonia.Skia.dll", Target = "lib/netstandard1.3" } + new NuSpecContent { Source = "Avalonia.Skia.dll", Target = "lib/netstandard2.0" } }, - BasePath = context.Directory("./src/Skia/Avalonia.Skia/bin/" + parameters.DirSuffix + "/netstandard1.3"), + BasePath = context.Directory("./src/Skia/Avalonia.Skia/bin/" + parameters.DirSuffix + "/netstandard2.0"), OutputDirectory = parameters.NugetRoot }, /////////////////////////////////////////////////////////////////////////////// @@ -448,9 +447,9 @@ public class Packages new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="net45", Version = parameters.Version }, new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="net45", Version = parameters.Version }, //.NET Core - new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="netcoreapp1.0", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="netcoreapp1.0", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="netcoreapp1.0", Version = parameters.Version } + new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="netcoreapp2.0", Version = parameters.Version }, + new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="netcoreapp2.0", Version = parameters.Version }, + new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="netcoreapp2.0", Version = parameters.Version } }, Files = new NuSpecContent[] { @@ -488,7 +487,7 @@ public class Packages }, Files = new [] { - new NuSpecContent { Source = "Avalonia.LinuxFramebuffer/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.LinuxFramebuffer.dll", Target = "lib/netstandard1.3" } + new NuSpecContent { Source = "Avalonia.LinuxFramebuffer/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.LinuxFramebuffer.dll", Target = "lib/netstandard2.0" } }, BasePath = context.Directory("./src/Linux/"), OutputDirectory = parameters.NugetRoot diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj index e0e848b91b..b308c59789 100644 --- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp1.1 + netcoreapp2.0 diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index a75de098e8..99ddce0757 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 False false diff --git a/samples/ControlCatalog/Pages/ToolTipPage.xaml b/samples/ControlCatalog/Pages/ToolTipPage.xaml index 29df11510c..5cf7fee4d1 100644 --- a/samples/ControlCatalog/Pages/ToolTipPage.xaml +++ b/samples/ControlCatalog/Pages/ToolTipPage.xaml @@ -1,22 +1,41 @@ - - ToolTip - A control which pops up a hint when a control is hovered + + ToolTip + A control which pops up a hint when a control is hovered - - - - - ToolTip - A control which pops up a hint when a control is hovered - - - Hover Here - + HorizontalAlignment="Center"> + + Hover Here + + + + + + ToolTip + A control which pops up a hint when a control is hovered + + + ToolTip bottom placement + + - \ No newline at end of file diff --git a/src/Avalonia.Animation/Avalonia.Animation.csproj b/src/Avalonia.Animation/Avalonia.Animation.csproj index 8f832dabcf..bafac2b261 100644 --- a/src/Avalonia.Animation/Avalonia.Animation.csproj +++ b/src/Avalonia.Animation/Avalonia.Animation.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj index 6906aed42b..58c510f483 100644 --- a/src/Avalonia.Base/Avalonia.Base.csproj +++ b/src/Avalonia.Base/Avalonia.Base.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false Avalonia diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 037546b186..d999e3b74e 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.Controls/DropDown.cs b/src/Avalonia.Controls/DropDown.cs index 0b1371b10e..5349fb1ca7 100644 --- a/src/Avalonia.Controls/DropDown.cs +++ b/src/Avalonia.Controls/DropDown.cs @@ -120,7 +120,7 @@ namespace Avalonia.Controls /// protected override void OnPointerPressed(PointerPressedEventArgs e) { - if (!IsDropDownOpen && ((IVisual)e.Source).GetVisualRoot() != typeof(PopupRoot)) + if (!IsDropDownOpen && ((IVisual)e.Source).GetVisualRoot() is PopupRoot) { IsDropDownOpen = true; e.Handled = true; diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs index daea187a69..5cd3b22fc9 100644 --- a/src/Avalonia.Controls/Primitives/Popup.cs +++ b/src/Avalonia.Controls/Primitives/Popup.cs @@ -277,7 +277,7 @@ namespace Avalonia.Controls.Primitives { base.OnDetachedFromLogicalTree(e); _topLevel = null; - + if (_popupRoot != null) { ((ISetLogicalParent)_popupRoot).SetParent(null); @@ -327,34 +327,40 @@ namespace Avalonia.Controls.Primitives /// /// The popup's position in screen coordinates. protected virtual Point GetPosition() + { + return GetPosition(PlacementTarget ?? this.GetVisualParent(), PlacementMode, PopupRoot, + HorizontalOffset, VerticalOffset); + } + + internal static Point GetPosition(Control target, PlacementMode placement, PopupRoot popupRoot, double horizontalOffset, double verticalOffset) { var zero = default(Point); - var mode = PlacementMode; - var target = PlacementTarget ?? this.GetVisualParent(); + var mode = placement; if (target?.GetVisualRoot() == null) { mode = PlacementMode.Pointer; - } + } switch (mode) { case PlacementMode.Pointer: - if(PopupRoot != null) + if (popupRoot != null) { // Scales the Horizontal and Vertical offset to screen co-ordinates. - var screenOffset = new Point(HorizontalOffset * (PopupRoot as ILayoutRoot).LayoutScaling, VerticalOffset * (PopupRoot as ILayoutRoot).LayoutScaling); - return (((IInputRoot)PopupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset; + var screenOffset = new Point(horizontalOffset * (popupRoot as ILayoutRoot).LayoutScaling, + verticalOffset * (popupRoot as ILayoutRoot).LayoutScaling); + return (((IInputRoot)popupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset; } return default(Point); case PlacementMode.Bottom: - - return target?.PointToScreen(new Point(0 + HorizontalOffset, target.Bounds.Height + VerticalOffset)) ?? zero; + return target?.PointToScreen(new Point(0 + horizontalOffset, target.Bounds.Height + verticalOffset)) ?? + zero; case PlacementMode.Right: - return target?.PointToScreen(new Point(target.Bounds.Width + HorizontalOffset, 0 + VerticalOffset)) ?? zero; + return target?.PointToScreen(new Point(target.Bounds.Width + horizontalOffset, 0 + verticalOffset)) ?? zero; default: throw new InvalidOperationException("Invalid value for Popup.PlacementMode"); diff --git a/src/Avalonia.Controls/ToolTip.cs b/src/Avalonia.Controls/ToolTip.cs index e1b69637af..e45f30f818 100644 --- a/src/Avalonia.Controls/ToolTip.cs +++ b/src/Avalonia.Controls/ToolTip.cs @@ -3,11 +3,7 @@ using System; using System.Reactive.Linq; -using System.Reactive.Subjects; using Avalonia.Controls.Primitives; -using Avalonia.Input; -using Avalonia.Threading; -using Avalonia.VisualTree; namespace Avalonia.Controls { @@ -29,29 +25,50 @@ namespace Avalonia.Controls AvaloniaProperty.RegisterAttached("Tip"); /// - /// The popup window used to display the active tooltip. + /// Defines the ToolTip.IsOpen attached property. /// - private static PopupRoot s_popup; + public static readonly AttachedProperty IsOpenProperty = + AvaloniaProperty.RegisterAttached("IsOpen"); /// - /// The control that the currently visible tooltip is attached to. + /// Defines the ToolTip.Placement property. /// - private static Control s_current; + public static readonly AttachedProperty PlacementProperty = + AvaloniaProperty.RegisterAttached("Placement", defaultValue: PlacementMode.Pointer); /// - /// Observable fired when a tooltip should be displayed for a control. The output from this - /// observable is throttled and calls when the time - /// period expires. + /// Defines the ToolTip.HorizontalOffset property. /// - private static readonly Subject s_show = new Subject(); + public static readonly AttachedProperty HorizontalOffsetProperty = + AvaloniaProperty.RegisterAttached("HorizontalOffset"); + + /// + /// Defines the ToolTip.VerticalOffset property. + /// + public static readonly AttachedProperty VerticalOffsetProperty = + AvaloniaProperty.RegisterAttached("VerticalOffset", 20); + + /// + /// Defines the ToolTip.ShowDelay property. + /// + public static readonly AttachedProperty ShowDelayProperty = + AvaloniaProperty.RegisterAttached("ShowDelay", 400); + + /// + /// Stores the curernt instance in the control. + /// + private static readonly AttachedProperty ToolTipProperty = + AvaloniaProperty.RegisterAttached("ToolTip"); + + private PopupRoot _popup; /// /// Initializes static members of the class. /// static ToolTip() { - TipProperty.Changed.Subscribe(TipChanged); - s_show.Throttle(TimeSpan.FromSeconds(0.5), AvaloniaScheduler.Instance).Subscribe(ShowToolTip); + TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged); + IsOpenProperty.Changed.Subscribe(IsOpenChanged); } /// @@ -77,101 +94,160 @@ namespace Avalonia.Controls } /// - /// called when the property changes on a control. + /// Gets the value of the ToolTip.IsOpen attached property. /// - /// The event args. - private static void TipChanged(AvaloniaPropertyChangedEventArgs e) + /// The control to get the property from. + /// + /// A value indicating whether the tool tip is visible. + /// + public static bool GetIsOpen(Control element) { - var control = (Control)e.Sender; + return element.GetValue(IsOpenProperty); + } - if (e.OldValue != null) - { - control.PointerEnter -= ControlPointerEnter; - control.PointerLeave -= ControlPointerLeave; - } + /// + /// Sets the value of the ToolTip.IsOpen attached property. + /// + /// The control to get the property from. + /// A value indicating whether the tool tip is visible. + public static void SetIsOpen(Control element, bool value) + { + element.SetValue(IsOpenProperty, value); + } - if (e.NewValue != null) - { - control.PointerEnter += ControlPointerEnter; - control.PointerLeave += ControlPointerLeave; - } + /// + /// Gets the value of the ToolTip.Placement attached property. + /// + /// The control to get the property from. + /// + /// A value indicating how the tool tip is positioned. + /// + public static PlacementMode GetPlacement(Control element) + { + return element.GetValue(PlacementProperty); } /// - /// Shows a tooltip for the specified control. + /// Sets the value of the ToolTip.Placement attached property. /// - /// The control. - private static void ShowToolTip(Control control) + /// The control to get the property from. + /// A value indicating how the tool tip is positioned. + public static void SetPlacement(Control element, PlacementMode value) { - if (control != null && control.IsVisible && control.GetVisualRoot() != null) - { - var cp = (control.GetVisualRoot() as IInputRoot)?.MouseDevice?.GetPosition(control); + element.SetValue(PlacementProperty, value); + } - if (cp.HasValue && control.IsVisible && new Rect(control.Bounds.Size).Contains(cp.Value)) - { - var position = control.PointToScreen(cp.Value) + new Vector(0, 22); - - if (s_popup == null) - { - s_popup = new PopupRoot(); - s_popup.Content = new ToolTip(); - } - else - { - ((ISetLogicalParent)s_popup).SetParent(null); - } - - ((ISetLogicalParent)s_popup).SetParent(control); - ((ToolTip)s_popup.Content).Content = GetTip(control); - s_popup.Position = position; - s_popup.Show(); - - s_current = control; - } - } + /// + /// Gets the value of the ToolTip.HorizontalOffset attached property. + /// + /// The control to get the property from. + /// + /// A value indicating how the tool tip is positioned. + /// + public static double GetHorizontalOffset(Control element) + { + return element.GetValue(HorizontalOffsetProperty); + } + + /// + /// Sets the value of the ToolTip.HorizontalOffset attached property. + /// + /// The control to get the property from. + /// A value indicating how the tool tip is positioned. + public static void SetHorizontalOffset(Control element, double value) + { + element.SetValue(HorizontalOffsetProperty, value); + } + + /// + /// Gets the value of the ToolTip.VerticalOffset attached property. + /// + /// The control to get the property from. + /// + /// A value indicating how the tool tip is positioned. + /// + public static double GetVerticalOffset(Control element) + { + return element.GetValue(VerticalOffsetProperty); + } + + /// + /// Sets the value of the ToolTip.VerticalOffset attached property. + /// + /// The control to get the property from. + /// A value indicating how the tool tip is positioned. + public static void SetVerticalOffset(Control element, double value) + { + element.SetValue(VerticalOffsetProperty, value); } /// - /// Called when the pointer enters a control with an attached tooltip. + /// Gets the value of the ToolTip.ShowDelay attached property. /// - /// The event sender. - /// The event args. - private static void ControlPointerEnter(object sender, PointerEventArgs e) + /// The control to get the property from. + /// + /// A value indicating the time, in milliseconds, before a tool tip opens. + /// + public static int GetShowDelay(Control element) { - s_current = (Control)sender; - s_show.OnNext(s_current); + return element.GetValue(ShowDelayProperty); } /// - /// Called when the pointer leaves a control with an attached tooltip. + /// Sets the value of the ToolTip.ShowDelay attached property. /// - /// The event sender. - /// The event args. - private static void ControlPointerLeave(object sender, PointerEventArgs e) + /// The control to get the property from. + /// A value indicating the time, in milliseconds, before a tool tip opens. + public static void SetShowDelay(Control element, int value) { - var control = (Control)sender; + element.SetValue(ShowDelayProperty, value); + } + + private static void IsOpenChanged(AvaloniaPropertyChangedEventArgs e) + { + var control = (Control)e.Sender; - if (control == s_current) + if ((bool)e.NewValue) { - if (s_popup != null) + var tip = GetTip(control); + if (tip == null) return; + + var toolTip = control.GetValue(ToolTipProperty); + if (toolTip == null || (tip != toolTip && tip != toolTip.Content)) { - DisposeTooltip(); - s_show.OnNext(null); + toolTip?.Close(); + + toolTip = tip as ToolTip ?? new ToolTip { Content = tip }; + control.SetValue(ToolTipProperty, toolTip); } + + toolTip.Open(control); + } + else + { + var toolTip = control.GetValue(ToolTipProperty); + toolTip?.Close(); } } - private static void DisposeTooltip() + private void Open(Control control) { - if (s_popup != null) - { - // Clear the ToolTip's Content in case it has control content: this will - // reset its visual parent allowing it to be used again. - ((ToolTip)s_popup.Content).Content = null; + Close(); + + _popup = new PopupRoot { Content = this }; + ((ISetLogicalParent)_popup).SetParent(control); + _popup.Position = Popup.GetPosition(control, GetPlacement(control), _popup, + GetHorizontalOffset(control), GetVerticalOffset(control)); + _popup.Show(); + } - // Dispose of the popup. - s_popup.Dispose(); - s_popup = null; + private void Close() + { + if (_popup != null) + { + _popup.Content = null; + _popup.Hide(); + _popup = null; } } } diff --git a/src/Avalonia.Controls/ToolTipService.cs b/src/Avalonia.Controls/ToolTipService.cs new file mode 100644 index 0000000000..bfd7ef0f33 --- /dev/null +++ b/src/Avalonia.Controls/ToolTipService.cs @@ -0,0 +1,98 @@ +using System; +using Avalonia.Input; +using Avalonia.Threading; + +namespace Avalonia.Controls +{ + /// + /// Handeles interaction with controls. + /// + internal sealed class ToolTipService + { + public static ToolTipService Instance { get; } = new ToolTipService(); + + private DispatcherTimer _timer; + + private ToolTipService() { } + + /// + /// called when the property changes on a control. + /// + /// The event args. + internal void TipChanged(AvaloniaPropertyChangedEventArgs e) + { + var control = (Control)e.Sender; + + if (e.OldValue != null) + { + control.PointerEnter -= ControlPointerEnter; + control.PointerLeave -= ControlPointerLeave; + } + + if (e.NewValue != null) + { + control.PointerEnter += ControlPointerEnter; + control.PointerLeave += ControlPointerLeave; + } + } + + /// + /// Called when the pointer enters a control with an attached tooltip. + /// + /// The event sender. + /// The event args. + private void ControlPointerEnter(object sender, PointerEventArgs e) + { + StopTimer(); + + var control = (Control)sender; + var showDelay = ToolTip.GetShowDelay(control); + if (showDelay == 0) + { + Open(control); + } + else + { + StartShowTimer(showDelay, control); + } + } + + /// + /// Called when the pointer leaves a control with an attached tooltip. + /// + /// The event sender. + /// The event args. + private void ControlPointerLeave(object sender, PointerEventArgs e) + { + var control = (Control)sender; + Close(control); + } + + private void StartShowTimer(int showDelay, Control control) + { + _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(showDelay) }; + _timer.Tick += (o, e) => Open(control); + _timer.Start(); + } + + private void Open(Control control) + { + StopTimer(); + + ToolTip.SetIsOpen(control, true); + } + + private void Close(Control control) + { + StopTimer(); + + ToolTip.SetIsOpen(control, false); + } + + private void StopTimer() + { + _timer?.Stop(); + _timer = null; + } + } +} \ No newline at end of file diff --git a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj index a68e8760f2..63cb8132a9 100644 --- a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj +++ b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj index be3f397283..5cb56e0be1 100644 --- a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj +++ b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj index 36443ce6f3..5c72d433ce 100644 --- a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj +++ b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj @@ -1,6 +1,6 @@  - netcoreapp1.0 + netcoreapp2.0 false diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj index e2c866fe3d..181f5e3a1e 100644 --- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj +++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj @@ -1,75 +1,21 @@ - - - - - Debug - AnyCPU - {4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0} - Library - Properties - Avalonia.DotNetFrameworkRuntime - Avalonia.DotNetFrameworkRuntime - v4.6.1 - 512 - - - - true - full - false - bin\Debug\ - TRACE;DEBUG;FULLDOTNET - prompt - 4 - bin\Debug\Avalonia.DotNetFrameworkRuntime.xml - - - pdbonly - true - bin\Release\ - TRACE;FULLDOTNET - prompt - 4 - bin\Release\Avalonia.DotNetFrameworkRuntime.xml - true - - - - - - - - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {eb582467-6abb-43a1-b052-e981ba910e3a} - Avalonia.Visuals - - - {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} - Avalonia.Styling - - - - - + + + net461 + false + bin\$(Configuration)\Avalonia.DotNetFrameworkRuntime.xml + $(DefineConstants);FULLDOTNET + true + + + + Properties\SharedAssemblyInfo.cs + + + + + + + + + \ No newline at end of file diff --git a/src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs b/src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs deleted file mode 100644 index 3a91d50a24..0000000000 --- a/src/Avalonia.DotNetFrameworkRuntime/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Avalonia.DotNetFrameworkRuntime")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4a1abb09-9047-4bd5-a4ad-a055e52c5ee0")] diff --git a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj index e7822324a9..fde486fa12 100644 --- a/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj +++ b/src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 False False false diff --git a/src/Avalonia.HtmlRenderer/Compat/Api.cs b/src/Avalonia.HtmlRenderer/Compat/Api.cs index 798b697277..d4f4c6abbe 100644 --- a/src/Avalonia.HtmlRenderer/Compat/Api.cs +++ b/src/Avalonia.HtmlRenderer/Compat/Api.cs @@ -4,18 +4,6 @@ using System.Text; namespace System.Net { - internal class AsyncCompletedEventArgs - { - public object UserState { get; set; } - public Exception Error { get; set; } - public bool Cancelled { get; set; } - - public AsyncCompletedEventArgs(Exception error, bool cancelled, object userState) - { - - } - } - class WebException : Exception { public object Response { get; set; } diff --git a/src/Avalonia.Input/Avalonia.Input.csproj b/src/Avalonia.Input/Avalonia.Input.csproj index b5482ebce1..901f7b5675 100644 --- a/src/Avalonia.Input/Avalonia.Input.csproj +++ b/src/Avalonia.Input/Avalonia.Input.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj index 9d22de86b3..d683c77468 100644 --- a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj +++ b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.Layout/Avalonia.Layout.csproj b/src/Avalonia.Layout/Avalonia.Layout.csproj index d0260391d8..810a985e36 100644 --- a/src/Avalonia.Layout/Avalonia.Layout.csproj +++ b/src/Avalonia.Layout/Avalonia.Layout.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj index 9ac40cba07..b9fa2f208b 100644 --- a/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj +++ b/src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj index 22d815d786..835e2295e3 100644 --- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj +++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 False false diff --git a/src/Avalonia.Styling/Avalonia.Styling.csproj b/src/Avalonia.Styling/Avalonia.Styling.csproj index 6b606616bb..6c0b957bf4 100644 --- a/src/Avalonia.Styling/Avalonia.Styling.csproj +++ b/src/Avalonia.Styling/Avalonia.Styling.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false Avalonia diff --git a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj index 4e980680d9..b4b200834b 100644 --- a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj +++ b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Avalonia.Visuals/Avalonia.Visuals.csproj b/src/Avalonia.Visuals/Avalonia.Visuals.csproj index 127760d8ac..fe18b0e446 100644 --- a/src/Avalonia.Visuals/Avalonia.Visuals.csproj +++ b/src/Avalonia.Visuals/Avalonia.Visuals.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false Avalonia diff --git a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj index 0f4b8c2e1b..b58a83b3d2 100644 --- a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj +++ b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 False false diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs index cf065b86dc..764cbfd6b6 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs @@ -104,14 +104,16 @@ namespace Avalonia.Gtk3.Interop var path = Custom?.Lookup(dll); if (path == null && Custom?.BasePath != null) path = Path.Combine(Custom.BasePath, name); - - try - { - return loader.LoadLibrary(path); - } - catch (Exception e) + if (path != null) { - exceptions.Add(e); + try + { + return loader.LoadLibrary(path); + } + catch (Exception e) + { + exceptions.Add(e); + } } throw new AggregateException("Unable to load " + dll, exceptions); } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj b/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj index 82da3ec090..c38cb0f114 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj +++ b/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 true diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index f04f148c5b..de015fc947 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 False false false @@ -97,6 +97,7 @@ + diff --git a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github index dfc5affa5d..eebf9dbb92 160000 --- a/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github +++ b/src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github @@ -1 +1 @@ -Subproject commit dfc5affa5d8f4ddf5a7707e3202d5593519de640 +Subproject commit eebf9dbb9275ecc48c18ec24f6fbad8cb494857f diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj index 3d16196b70..57552f852c 100644 --- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj +++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs index e7402fb23c..092910a08f 100644 --- a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs +++ b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs @@ -12,7 +12,7 @@ namespace Avalonia.Shared.PlatformSupport internal partial class StandardRuntimePlatform : IRuntimePlatform { -#if NETCOREAPP1_0 +#if NETCOREAPP2_0 public void PostThreadPoolItem(Action cb) => ThreadPool.QueueUserWorkItem(_ => cb(), null); #else public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies(); diff --git a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj index bae10e4d97..f5ed89d154 100644 --- a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj +++ b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false Avalonia.Skia Avalonia.Skia diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index 4d656680b1..a84c373886 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 false diff --git a/src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj b/src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj index cedf3c4213..bae634b030 100644 --- a/src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj +++ b/src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj @@ -1,6 +1,6 @@  - netstandard1.3 + netstandard2.0 False false Avalonia.Win32 diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 5473ef9bea..4fed7a34f4 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -699,10 +699,40 @@ namespace Avalonia.Win32.Interop public static extern int GetSystemMetrics(SystemMetric smIndex); [DllImport("user32.dll", SetLastError = true)] - public static extern uint GetWindowLong(IntPtr hWnd, int nIndex); + public static extern uint GetWindowLongPtr(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll", SetLastError = true, EntryPoint = "GetWindowLong")] + public static extern uint GetWindowLong32b(IntPtr hWnd, int nIndex); + + public static uint GetWindowLong(IntPtr hWnd, int nIndex) + { + if(IntPtr.Size == 4) + { + return GetWindowLong32b(hWnd, nIndex); + } + else + { + return GetWindowLongPtr(hWnd, nIndex); + } + } + + [DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLong")] + private static extern uint SetWindowLong32b(IntPtr hWnd, int nIndex, uint value); [DllImport("user32.dll", SetLastError = true)] - public static extern uint SetWindowLong(IntPtr hWnd, int nIndex, uint value); + private static extern uint SetWindowLongPtr(IntPtr hWnd, int nIndex, uint value); + + public static uint SetWindowLong(IntPtr hWnd, int nIndex, uint value) + { + if (IntPtr.Size == 4) + { + return SetWindowLong32b(hWnd, nIndex, value); + } + else + { + return SetWindowLongPtr(hWnd, nIndex, value); + } + } [DllImport("user32.dll", SetLastError = true)] public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl); @@ -811,14 +841,14 @@ namespace Avalonia.Win32.Interop return SetClassLong64(hWnd, nIndex, dwNewLong); } -#if !NETSTANDARD && !NETSTANDARD1_3 - [ComImport, ClassInterface(ClassInterfaceType.None), TypeLibType(TypeLibTypeFlags.FCanCreate), Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")] - internal class FileOpenDialogRCW { } + + [DllImport("ole32.dll", PreserveSig = true)] + internal static extern int CoCreateInstance(ref Guid clsid, + IntPtr ignore1, int ignore2, ref Guid iid, [MarshalAs(UnmanagedType.IUnknown), Out] out object pUnkOuter); [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv); -#endif [DllImport("user32.dll", SetLastError = true)] public static extern bool OpenClipboard(IntPtr hWndOwner); @@ -1153,7 +1183,7 @@ namespace Avalonia.Win32.Interop public int flagsEx; } } -#if !NETSTANDARD && !NETSTANDARD1_3 + [ComImport(), Guid("42F85136-DB7E-439C-85F1-E4075D135FC8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IFileDialog { @@ -1253,5 +1283,4 @@ namespace Avalonia.Win32.Interop uint Compare([In, MarshalAs(UnmanagedType.Interface)] IShellItem psi, [In] uint hint, out int piOrder); } -#endif } diff --git a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs index 4d8c375aaf..e08fecbbd9 100644 --- a/src/Windows/Avalonia.Win32/SystemDialogImpl.cs +++ b/src/Windows/Avalonia.Win32/SystemDialogImpl.cs @@ -100,17 +100,14 @@ namespace Avalonia.Win32 var pofn = &ofn; // We should save the current directory to restore it later. -#if !NETSTANDARD var currentDirectory = Environment.CurrentDirectory; -#endif + var res = dialog is OpenFileDialog ? UnmanagedMethods.GetOpenFileName(new IntPtr(pofn)) : UnmanagedMethods.GetSaveFileName(new IntPtr(pofn)); // Restore the old current directory, since GetOpenFileName and GetSaveFileName change it after they're called -#if !NETSTANDARD Environment.CurrentDirectory = currentDirectory; -#endif if (!res) return null; @@ -155,15 +152,16 @@ namespace Avalonia.Win32 public Task ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) { -#if NETSTANDARD - throw new NotImplementedException(); -#else return Task.Factory.StartNew(() => { string result = string.Empty; var hWnd = parent?.Handle?.Handle ?? IntPtr.Zero; - var frm = (IFileDialog)(new UnmanagedMethods.FileOpenDialogRCW()); + var clsid = Guid.Parse("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7"); + var iid = Guid.Parse("42F85136-DB7E-439C-85F1-E4075D135FC8"); + + UnmanagedMethods.CoCreateInstance(ref clsid, IntPtr.Zero, 1, ref iid, out var unk); + var frm = (IFileDialog)unk; uint options; frm.GetOptions(out options); options |= (uint)(UnmanagedMethods.FOS.FOS_PICKFOLDERS | UnmanagedMethods.FOS.FOS_FORCEFILESYSTEM | UnmanagedMethods.FOS.FOS_NOVALIDATE | UnmanagedMethods.FOS.FOS_NOTESTFILECREATE | UnmanagedMethods.FOS.FOS_DONTADDTORECENT); @@ -214,7 +212,6 @@ namespace Avalonia.Win32 return result; }); -#endif } } } diff --git a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj index c656801d90..8692cdef42 100644 --- a/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj +++ b/tests/Avalonia.Base.UnitTests/Avalonia.Base.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library diff --git a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj index 957cdd7036..8b2f5093cf 100644 --- a/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj +++ b/tests/Avalonia.Controls.UnitTests/Avalonia.Controls.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library diff --git a/tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj b/tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj index 99cf4e98d2..98a1312782 100644 --- a/tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj +++ b/tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library diff --git a/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj b/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj index 86c9cf0617..78d2128478 100644 --- a/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj +++ b/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library diff --git a/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj b/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj index 0950856dca..0020ff46d9 100644 --- a/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj +++ b/tests/Avalonia.Layout.UnitTests/Avalonia.Layout.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library diff --git a/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj b/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj index 3ccd3da044..5d3b04e24b 100644 --- a/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj +++ b/tests/Avalonia.Markup.UnitTests/Avalonia.Markup.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj index f6f8f6bcb0..a1f66d0c72 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library diff --git a/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj b/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj index 134e89f2e5..370cfac6dd 100644 --- a/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj +++ b/tests/Avalonia.RenderTests/Avalonia.Skia.RenderTests.csproj @@ -6,7 +6,7 @@ - netcoreapp1.1 + netcoreapp2.0 bin\Skia\$(Configuration) false False diff --git a/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj b/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj index 3f9213b91f..ae12269e18 100644 --- a/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj +++ b/tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 Library CS0067 diff --git a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj index 40023134fd..b04fd5d2bc 100644 --- a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj +++ b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0 false Library @@ -33,7 +33,7 @@ - + @@ -52,7 +52,7 @@ - + \ No newline at end of file diff --git a/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj b/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj index d35542b51f..6dc9e3324d 100644 --- a/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj +++ b/tests/Avalonia.Visuals.UnitTests/Avalonia.Visuals.UnitTests.csproj @@ -1,6 +1,6 @@  - net461;netcoreapp1.1 + net461;netcoreapp2.0