Browse Source

Merge branch 'pr/575'

pull/618/head
Steven Kirk 10 years ago
parent
commit
b565443881
  1. BIN
      samples/ControlCatalog/Assets/test_icon.ico
  2. 5
      samples/ControlCatalog/ControlCatalog.csproj
  3. 3
      samples/ControlCatalog/MainWindow.xaml
  4. 18
      src/Android/Avalonia.Android/AndroidPlatform.cs
  5. 5
      src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs
  6. 3
      src/Avalonia.Controls/Avalonia.Controls.csproj
  7. 17
      src/Avalonia.Controls/Platform/IPlatformIconLoader.cs
  8. 9
      src/Avalonia.Controls/Platform/IWindowIconImpl.cs
  9. 5
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  10. 16
      src/Avalonia.Controls/Window.cs
  11. 34
      src/Avalonia.Controls/WindowIcon.cs
  12. 6
      src/Avalonia.SceneGraph/Media/Imaging/Bitmap.cs
  13. 7
      src/Avalonia.SceneGraph/Media/Imaging/IBitmap.cs
  14. 8
      src/Avalonia.SceneGraph/Platform/IBitmapImpl.cs
  15. 38
      src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs
  16. 20
      src/Gtk/Avalonia.Cairo/Media/Imaging/BitmapImpl.cs
  17. 11
      src/Gtk/Avalonia.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs
  18. 1
      src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
  19. 32
      src/Gtk/Avalonia.Gtk/GtkPlatform.cs
  20. 20
      src/Gtk/Avalonia.Gtk/IconImpl.cs
  21. 15
      src/Gtk/Avalonia.Gtk/WindowImpl.cs
  22. 1
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  23. 1
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeFeatureProvider.cs
  24. 70
      src/Markup/Avalonia.Markup.Xaml/Converters/IconTypeConverter.cs
  25. 9
      src/Skia/Avalonia.Skia/BitmapImpl.cs
  26. 21
      src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs
  27. 10
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  28. 19
      src/Windows/Avalonia.Win32/IconImpl.cs
  29. 147
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  30. 27
      src/Windows/Avalonia.Win32/Win32Platform.cs
  31. 9
      src/Windows/Avalonia.Win32/WindowImpl.cs
  32. 1
      src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
  33. 4
      src/iOS/Avalonia.iOS/AvaloniaView.cs
  34. 26
      src/iOS/Avalonia.iOS/PlatformIconLoader.cs
  35. 3
      src/iOS/Avalonia.iOS/iOSPlatform.cs
  36. 12
      tests/Avalonia.DesignerSupport.Tests/Checker.cs
  37. 4
      tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs

BIN
samples/ControlCatalog/Assets/test_icon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

5
samples/ControlCatalog/ControlCatalog.csproj

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
@ -204,6 +204,9 @@
<Name>Avalonia.Themes.Default</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Assets\test_icon.ico" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

3
samples/ControlCatalog/MainWindow.xaml

@ -1,6 +1,7 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:pages="clr-namespace:ControlCatalog.Pages;assembly=ControlCatalog"
Title="Avalonia Control Gallery">
Title="Avalonia Control Gallery"
Icon="resm:ControlCatalog.Assets.test_icon.ico">
<TabControl Classes="sidebar">
<TabControl.Transition>
<CrossFade Duration="0.25"/>

18
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -11,10 +11,11 @@ using Avalonia.Skia;
using System;
using System.Collections.Generic;
using Avalonia.Android.Platform.SkiaPlatform;
using System.IO;
namespace Avalonia.Android
{
public class AndroidPlatform : IPlatformSettings, IWindowingPlatform
public class AndroidPlatform : IPlatformSettings, IWindowingPlatform, IPlatformIconLoader
{
public static readonly AndroidPlatform Instance = new AndroidPlatform();
public Size DoubleClickSize => new Size(4, 4);
@ -65,5 +66,20 @@ namespace Avalonia.Android
{
throw new NotImplementedException();
}
public IWindowIconImpl LoadIcon(string fileName)
{
return null;
}
public IWindowIconImpl LoadIcon(Stream stream)
{
return null;
}
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
return null;
}
}
}

5
src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs

@ -180,5 +180,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
Paint?.Invoke(new Rect(new Point(0, 0), ClientSize));
}
public void SetIcon(IWindowIconImpl icon)
{
// No window icons for mobile platforms
}
}
}

3
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -56,6 +56,7 @@
<Compile Include="HotkeyManager.cs" />
<Compile Include="IApplicationLifecycle.cs" />
<Compile Include="IScrollable.cs" />
<Compile Include="WindowIcon.cs" />
<Compile Include="IPseudoClasses.cs" />
<Compile Include="DropDownItem.cs" />
<Compile Include="ISetInheritanceParent.cs" />
@ -64,6 +65,8 @@
<Compile Include="IVirtualizingPanel.cs" />
<Compile Include="LayoutTransformControl.cs" />
<Compile Include="Mixins\ContentControlMixin.cs" />
<Compile Include="Platform\IWindowIconImpl.cs" />
<Compile Include="Platform\IPlatformIconLoader.cs" />
<Compile Include="Platform\ITopLevelRenderer.cs" />
<Compile Include="Platform\IWindowingPlatform.cs" />
<Compile Include="Platform\PlatformManager.cs" />

17
src/Avalonia.Controls/Platform/IPlatformIconLoader.cs

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Media.Imaging;
namespace Avalonia.Platform
{
public interface IPlatformIconLoader
{
IWindowIconImpl LoadIcon(string fileName);
IWindowIconImpl LoadIcon(Stream stream);
IWindowIconImpl LoadIcon(IBitmapImpl bitmap);
}
}

9
src/Avalonia.Controls/Platform/IWindowIconImpl.cs

@ -0,0 +1,9 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Platform
{
public interface IWindowIconImpl
{
}
}

5
src/Avalonia.Controls/Platform/IWindowImpl.cs

@ -39,5 +39,10 @@ namespace Avalonia.Platform
/// Enables of disables system window decorations (title bar, buttons, etc)
/// </summary>
void SetSystemDecorations(bool enabled);
/// <summary>
/// Sets the icon of this window.
/// </summary>
void SetIcon(IWindowIconImpl icon);
}
}

16
src/Avalonia.Controls/Window.cs

@ -70,6 +70,12 @@ namespace Avalonia.Controls
public static readonly StyledProperty<string> TitleProperty =
AvaloniaProperty.Register<Window, string>(nameof(Title), "Window");
/// <summary>
/// Defines the <see cref="Icon"/> property.
/// </summary>
public static readonly StyledProperty<WindowIcon> IconProperty =
AvaloniaProperty.Register<Window, WindowIcon>(nameof(Icon));
private readonly NameScope _nameScope = new NameScope();
private object _dialogResult;
private readonly Size _maxPlatformClientSize;
@ -83,6 +89,7 @@ namespace Avalonia.Controls
TitleProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetTitle((string)e.NewValue));
HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
(s, e) => s.PlatformImpl.SetSystemDecorations((bool) e.NewValue));
IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
}
/// <summary>
@ -159,6 +166,15 @@ namespace Avalonia.Controls
set { this.PlatformImpl.WindowState = value; }
}
/// <summary>
/// Gets or sets the icon of the window.
/// </summary>
public WindowIcon Icon
{
get { return GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
/// <inheritdoc/>
Size ILayoutRoot.MaxClientSize => _maxPlatformClientSize;

34
src/Avalonia.Controls/WindowIcon.cs

@ -0,0 +1,34 @@
using Avalonia.Platform;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Media.Imaging;
namespace Avalonia.Controls
{
/// <summary>
/// Represents an icon for a window.
/// </summary>
public class WindowIcon
{
public WindowIcon(IBitmap bitmap)
{
PlatformImpl = AvaloniaLocator.Current.GetService<IPlatformIconLoader>().LoadIcon(bitmap.PlatformImpl);
}
public WindowIcon(string fileName)
{
PlatformImpl = AvaloniaLocator.Current.GetService<IPlatformIconLoader>().LoadIcon(fileName);
}
public WindowIcon(Stream stream)
{
PlatformImpl = AvaloniaLocator.Current.GetService<IPlatformIconLoader>().LoadIcon(stream);
}
public IWindowIconImpl PlatformImpl { get; }
}
}

6
src/Avalonia.SceneGraph/Media/Imaging/Bitmap.cs

@ -1,6 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.IO;
using Avalonia.Platform;
@ -66,5 +67,10 @@ namespace Avalonia.Media.Imaging
{
PlatformImpl.Save(fileName);
}
public void Save(Stream stream)
{
PlatformImpl.Save(stream);
}
}
}

7
src/Avalonia.SceneGraph/Media/Imaging/IBitmap.cs

@ -1,6 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.IO;
using Avalonia.Platform;
namespace Avalonia.Media.Imaging
@ -30,5 +31,11 @@ namespace Avalonia.Media.Imaging
/// </summary>
/// <param name="fileName">The filename.</param>
void Save(string fileName);
/// <summary>
/// Saves the bitmap to a stream in png format.
/// </summary>
/// <param name="stream">The stream.</param>
void Save(Stream stream);
}
}

8
src/Avalonia.SceneGraph/Platform/IBitmapImpl.cs

@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.IO;
namespace Avalonia.Platform
{
/// <summary>
@ -23,5 +25,11 @@ namespace Avalonia.Platform
/// </summary>
/// <param name="fileName">The filename.</param>
void Save(string fileName);
/// <summary>
/// Saves the bitmap to a stream in png format.
/// </summary>
/// <param name="stream">The stream.</param>
void Save(Stream stream);
}
}

38
src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs

@ -85,25 +85,25 @@ namespace Avalonia.Cairo.Media
_context.Scale(scale.X, scale.Y);
destRect /= scale;
if (opacityOverride < 1.0f) {
_context.PushGroup ();
Gdk.CairoHelper.SetSourcePixbuf (
_context,
impl.Surface,
-sourceRect.X + destRect.X,
-sourceRect.Y + destRect.Y);
_context.Rectangle (destRect.ToCairo ());
_context.Fill ();
_context.PopGroupToSource ();
_context.PaintWithAlpha (opacityOverride);
} else {
_context.PushGroup ();
Gdk.CairoHelper.SetSourcePixbuf (
_context,
impl.Surface,
-sourceRect.X + destRect.X,
-sourceRect.Y + destRect.Y);
if (opacityOverride < 1.0f) {
_context.PushGroup ();
Gdk.CairoHelper.SetSourcePixbuf (
_context,
impl,
-sourceRect.X + destRect.X,
-sourceRect.Y + destRect.Y);
_context.Rectangle (destRect.ToCairo ());
_context.Fill ();
_context.PopGroupToSource ();
_context.PaintWithAlpha (opacityOverride);
} else {
_context.PushGroup ();
Gdk.CairoHelper.SetSourcePixbuf (
_context,
impl,
-sourceRect.X + destRect.X,
-sourceRect.Y + destRect.Y);
_context.Rectangle (destRect.ToCairo ());
_context.Fill ();

20
src/Gtk/Avalonia.Cairo/Media/Imaging/BitmapImpl.cs

@ -6,28 +6,30 @@ using Avalonia.Platform;
namespace Avalonia.Cairo.Media.Imaging
{
using System.IO;
using Cairo = global::Cairo;
public class BitmapImpl : IBitmapImpl
public class BitmapImpl : Gdk.Pixbuf, IBitmapImpl
{
public BitmapImpl(Gdk.Pixbuf pixbuf)
:base(pixbuf.SaveToBuffer("png"))
{
Surface = pixbuf;
}
public int PixelWidth => Surface.Width;
public int PixelWidth => Width;
public int PixelHeight => Surface.Height;
public int PixelHeight => Height;
public Gdk.Pixbuf Surface
public void Save(string fileName)
{
get;
// TODO: Test
Save(fileName, "png");
}
public void Save(string fileName)
public void Save(Stream stream)
{
// TODO: Test
Surface.Save(fileName, "png");
var buffer = SaveToBuffer("png");
stream.Write(buffer, 0, buffer.Length);
}
}
}

11
src/Gtk/Avalonia.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs

@ -8,6 +8,7 @@ using Avalonia.Rendering;
namespace Avalonia.Cairo.Media.Imaging
{
using System.IO;
using Cairo = global::Cairo;
public class RenderTargetBitmapImpl : IRenderTargetBitmapImpl
@ -43,5 +44,15 @@ namespace Avalonia.Cairo.Media.Imaging
{
return _renderTarget.CreateDrawingContext();
}
public void Save(Stream stream)
{
var tempFileName = Path.GetTempFileName();
Surface.WriteToPng(tempFileName);
using (var tempFile = new FileStream(tempFileName, FileMode.Create))
{
tempFile.CopyTo(stream);
}
}
}
}

1
src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj

@ -46,6 +46,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="ClipboardImpl.cs" />
<Compile Include="IconImpl.cs" />
<Compile Include="SystemDialogImpl.cs" />
<Compile Include="CursorFactory.cs" />
<Compile Include="GtkExtensions.cs" />

32
src/Gtk/Avalonia.Gtk/GtkPlatform.cs

@ -25,9 +25,10 @@ namespace Avalonia
namespace Avalonia.Gtk
{
using System.IO;
using Gtk = global::Gtk;
public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform
public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader
{
private static readonly GtkPlatform s_instance = new GtkPlatform();
private static Thread _uiThread;
@ -53,7 +54,8 @@ namespace Avalonia.Gtk
.Bind<IMouseDevice>().ToConstant(GtkMouseDevice.Instance)
.Bind<IPlatformSettings>().ToConstant(s_instance)
.Bind<IPlatformThreadingInterface>().ToConstant(s_instance)
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogImpl>();
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogImpl>()
.Bind<IPlatformIconLoader>().ToConstant(s_instance);
SharedPlatform.Register();
_uiThread = Thread.CurrentThread;
}
@ -112,5 +114,31 @@ namespace Avalonia.Gtk
{
return new PopupImpl();
}
public IWindowIconImpl LoadIcon(string fileName)
{
return new IconImpl(new Gdk.Pixbuf(fileName));
}
public IWindowIconImpl LoadIcon(Stream stream)
{
return new IconImpl(new Gdk.Pixbuf(stream));
}
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
if (bitmap is Gdk.Pixbuf)
{
return new IconImpl((Gdk.Pixbuf)bitmap);
}
else
{
using (var memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream);
return new IconImpl(new Gdk.Pixbuf(memoryStream));
}
}
}
}
}

20
src/Gtk/Avalonia.Gtk/IconImpl.cs

@ -0,0 +1,20 @@
using Avalonia.Platform;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Gdk;
namespace Avalonia.Gtk
{
class IconImpl : IWindowIconImpl
{
public IconImpl(Pixbuf pixbuf)
{
Pixbuf = pixbuf;
}
public Pixbuf Pixbuf { get; }
}
}

15
src/Gtk/Avalonia.Gtk/WindowImpl.cs

@ -53,11 +53,11 @@ namespace Avalonia.Gtk
Realize();
}
protected override void OnRealized ()
{
base.OnRealized ();
_imContext.ClientWindow = this.GdkWindow;
}
protected override void OnRealized ()
{
base.OnRealized ();
_imContext.ClientWindow = this.GdkWindow;
}
public Size ClientSize
{
@ -383,5 +383,10 @@ namespace Avalonia.Gtk
Input(e);
return true;
}
public void SetIcon(IWindowIconImpl icon)
{
Icon = ((IconImpl)icon).Pixbuf;
}
}
}

1
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -62,6 +62,7 @@
<Compile Include="Converters\DateTimeTypeConverter.cs" />
<Compile Include="Converters\GeometryTypeConverter.cs" />
<Compile Include="Converters\GridLengthTypeConverter.cs" />
<Compile Include="Converters\IconTypeConverter.cs" />
<Compile Include="Converters\KeyGestureConverter.cs" />
<Compile Include="Converters\MemberSelectorTypeConverter.cs" />
<Compile Include="Converters\AvaloniaListTypeConverter.cs" />

1
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeFeatureProvider.cs

@ -173,6 +173,7 @@ namespace Avalonia.Markup.Xaml.Context
RegisterTypeConverter(typeof(TimeSpan), new TimeSpanTypeConverter());
RegisterTypeConverter(typeof(Uri), new UriTypeConverter());
RegisterTypeConverter(typeof(Cursor), new CursorTypeConverter());
RegisterTypeConverter(typeof(WindowIcon), new IconTypeConverter());
}
}
}

70
src/Markup/Avalonia.Markup.Xaml/Converters/IconTypeConverter.cs

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using OmniXaml.TypeConversion;
namespace Avalonia.Markup.Xaml.Converters
{
class IconTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string) || typeof(IBitmap).GetTypeInfo().IsAssignableFrom(sourceType.GetTypeInfo());
}
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
var path = value as string;
if (path != null)
{
return CreateIconFromPath(context, path);
}
var bitmap = value as IBitmap;
if (bitmap != null)
{
return new WindowIcon(bitmap);
}
throw new NotSupportedException();
}
private WindowIcon CreateIconFromPath(IValueContext context, string path)
{
var uri = new Uri(path, UriKind.RelativeOrAbsolute);
var baseUri = GetBaseUri(context);
var scheme = uri.IsAbsoluteUri ? uri.Scheme : "file";
switch (scheme)
{
case "file":
return new WindowIcon(path);
default:
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
return new WindowIcon(assets.Open(uri, baseUri));
}
}
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
private Uri GetBaseUri(IValueContext context)
{
object result;
context.ParsingDictionary.TryGetValue("Uri", out result);
return result as Uri;
}
}
}

9
src/Skia/Avalonia.Skia/BitmapImpl.cs

@ -80,5 +80,14 @@ namespace Avalonia.Skia
return new DrawingContext(new BitmapDrawingContext(Bitmap));
}
public void Save(Stream stream)
{
IntPtr length;
using (var image = SKImage.FromPixels(Bitmap.Info, Bitmap.GetPixels(out length), Bitmap.RowBytes))
using (var data = image.Encode())
{
data.SaveTo(stream);
}
}
}
}

21
src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs

@ -117,15 +117,20 @@ namespace Avalonia.Direct2D1.Media
using (FileStream s = new FileStream(fileName, FileMode.Create))
{
PngBitmapEncoder encoder = new PngBitmapEncoder(_factory);
encoder.Initialize(s);
BitmapFrameEncode frame = new BitmapFrameEncode(encoder);
frame.Initialize();
frame.WriteSource(WicImpl);
frame.Commit();
encoder.Commit();
Save(s);
}
}
public void Save(Stream stream)
{
PngBitmapEncoder encoder = new PngBitmapEncoder(_factory);
encoder.Initialize(stream);
BitmapFrameEncode frame = new BitmapFrameEncode(encoder);
frame.Initialize();
frame.WriteSource(WicImpl);
frame.Commit();
encoder.Commit();
}
}
}

10
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -44,6 +44,15 @@
<HintPath>..\..\..\packages\System.Reactive.Core.3.0.0\lib\net45\System.Reactive.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Reactive.Core">
<HintPath>..\..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces">
<HintPath>..\..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
<HintPath>..\..\..\packages\System.Reactive.Interfaces.3.0.0\lib\net45\System.Reactive.Interfaces.dll</HintPath>
<Private>True</Private>
@ -56,6 +65,7 @@
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="ClipboardImpl.cs" />
<Compile Include="IconImpl.cs" />
<Compile Include="SystemDialogImpl.cs" />
<Compile Include="CursorFactory.cs" />
<Compile Include="Input\KeyInterop.cs" />

19
src/Windows/Avalonia.Win32/IconImpl.cs

@ -0,0 +1,19 @@
using Avalonia.Platform;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Win32
{
class IconImpl : IWindowIconImpl
{
public IconImpl(System.Drawing.Bitmap iconBitmap)
{
IconBitmap = iconBitmap;
}
public System.Drawing.Bitmap IconBitmap { get; }
}
}

147
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -541,72 +541,72 @@ namespace Avalonia.Win32.Interop
WM_DISPATCH_WORK_ITEM = WM_USER,
}
public enum BitmapCompressionMode : uint
{
BI_RGB = 0,
BI_RLE8 = 1,
BI_RLE4 = 2,
BI_BITFIELDS = 3,
BI_JPEG = 4,
BI_PNG = 5
}
public enum DIBColorTable
{
DIB_RGB_COLORS = 0, /* color table in RGBs */
DIB_PAL_COLORS /* color table in palette indices */
};
[StructLayout(LayoutKind.Sequential)]
public struct RGBQUAD
{
public byte rgbBlue;
public byte rgbGreen;
public byte rgbRed;
public byte rgbReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
// C# cannot inlay structs in structs so must expand directly here
//
//[StructLayout(LayoutKind.Sequential)]
//public struct BITMAPINFOHEADER
//{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public BitmapCompressionMode biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
//}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public uint[] cols;
}
public const int SizeOf_BITMAPINFOHEADER = 40;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll")]
public static extern int SetDIBitsToDevice(IntPtr hdc, int XDest, int YDest,
uint dwWidth, uint dwHeight,
int XSrc, int YSrc,
uint uStartScan, uint cScanLines,
IntPtr lpvBits, [In] ref BITMAPINFO lpbmi, uint fuColorUse);
[DllImport("user32.dll")]
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll", SetLastError = true)]
public enum BitmapCompressionMode : uint
{
BI_RGB = 0,
BI_RLE8 = 1,
BI_RLE4 = 2,
BI_BITFIELDS = 3,
BI_JPEG = 4,
BI_PNG = 5
}
public enum DIBColorTable
{
DIB_RGB_COLORS = 0, /* color table in RGBs */
DIB_PAL_COLORS /* color table in palette indices */
};
[StructLayout(LayoutKind.Sequential)]
public struct RGBQUAD
{
public byte rgbBlue;
public byte rgbGreen;
public byte rgbRed;
public byte rgbReserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFO
{
// C# cannot inlay structs in structs so must expand directly here
//
//[StructLayout(LayoutKind.Sequential)]
//public struct BITMAPINFOHEADER
//{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public BitmapCompressionMode biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
//}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public uint[] cols;
}
public const int SizeOf_BITMAPINFOHEADER = 40;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll")]
public static extern int SetDIBitsToDevice(IntPtr hdc, int XDest, int YDest,
uint dwWidth, uint dwHeight,
int XSrc, int YSrc,
uint uStartScan, uint cScanLines,
IntPtr lpvBits, [In] ref BITMAPINFO lpbmi, uint fuColorUse);
[DllImport("user32.dll")]
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool AdjustWindowRectEx(ref RECT lpRect, uint dwStyle, bool bMenu, uint dwExStyle);
[DllImport("user32.dll")]
@ -709,10 +709,7 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "RegisterClassExW")]
public static extern ushort RegisterClassEx(ref WNDCLASSEX lpwcx);
@ -845,6 +842,10 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, MONITOR dwFlags);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public enum MONITOR
{
MONITOR_DEFAULTTONULL = 0x00000000,
@ -1008,6 +1009,12 @@ namespace Avalonia.Win32.Interop
E_OUTOFMEMORY = 0x8007000E
}
public enum Icons
{
ICON_SMALL = 0,
ICON_BIG = 1
}
public const uint SIGDN_FILESYSPATH = 0x80058000;
[Flags]

27
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -16,6 +16,7 @@ using Avalonia.Shared.PlatformSupport;
using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
using Avalonia.Controls;
using System.IO;
namespace Avalonia
{
@ -31,7 +32,7 @@ namespace Avalonia
namespace Avalonia.Win32
{
public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform
public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader
{
private static readonly Win32Platform s_instance = new Win32Platform();
private static Thread _uiThread;
@ -66,7 +67,8 @@ namespace Avalonia.Win32
.Bind<IPlatformSettings>().ToConstant(s_instance)
.Bind<IPlatformThreadingInterface>().ToConstant(s_instance)
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogImpl>()
.Bind<IWindowingPlatform>().ToConstant(s_instance);
.Bind<IWindowingPlatform>().ToConstant(s_instance)
.Bind<IPlatformIconLoader>().ToConstant(s_instance);
SharedPlatform.Register();
_uiThread = Thread.CurrentThread;
@ -186,5 +188,26 @@ namespace Avalonia.Win32
{
return new PopupImpl();
}
public IWindowIconImpl LoadIcon(string fileName)
{
var icon = new System.Drawing.Bitmap(fileName);
return new IconImpl(icon);
}
public IWindowIconImpl LoadIcon(Stream stream)
{
var icon = new System.Drawing.Bitmap(stream);
return new IconImpl(icon);
}
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
using (var memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream);
return new IconImpl(new System.Drawing.Bitmap(memoryStream));
}
}
}
}

9
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -604,7 +604,7 @@ namespace Avalonia.Win32
hInstance = Marshal.GetHINSTANCE(GetType().Module),
hCursor = DefaultCursor,
hbrBackground = IntPtr.Zero,
lpszClassName = _className,
lpszClassName = _className
};
ushort atom = UnmanagedMethods.RegisterClassEx(ref wndClassEx);
@ -681,5 +681,12 @@ namespace Avalonia.Win32
UnmanagedMethods.ShowWindow(_hwnd, command);
}
public void SetIcon(IWindowIconImpl icon)
{
var impl = (IconImpl)icon;
var nativeIcon = impl.IconBitmap;
UnmanagedMethods.PostMessage(_hwnd, (int)UnmanagedMethods.WindowsMessage.WM_SETICON,
new IntPtr((int)UnmanagedMethods.Icons.ICON_BIG), nativeIcon.GetHicon());
}
}
}

1
src/iOS/Avalonia.iOS/Avalonia.iOS.csproj

@ -39,6 +39,7 @@
<Compile Include="Extensions.cs" />
<Compile Include="iOSPlatform.cs" />
<Compile Include="AvaloniaView.cs" />
<Compile Include="PlatformIconLoader.cs" />
<Compile Include="PlatformSettings.cs" />
<Compile Include="PlatformThreadingInterface.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

4
src/iOS/Avalonia.iOS/AvaloniaView.cs

@ -214,7 +214,9 @@ namespace Avalonia.iOS
}
}
public void SetIcon(IWindowIconImpl icon)
{
}
}
class AvaloniaViewController : UIViewController

26
src/iOS/Avalonia.iOS/PlatformIconLoader.cs

@ -0,0 +1,26 @@
using Avalonia.Platform;
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Avalonia.iOS
{
class PlatformIconLoader : IPlatformIconLoader
{
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
return null;
}
public IWindowIconImpl LoadIcon(Stream stream)
{
return null;
}
public IWindowIconImpl LoadIcon(string fileName)
{
return null;
}
}
}

3
src/iOS/Avalonia.iOS/iOSPlatform.cs

@ -61,7 +61,8 @@ namespace Avalonia.iOS
.Bind<IKeyboardDevice>().ToConstant(KeyboardDevice)
.Bind<IMouseDevice>().ToConstant(MouseDevice)
.Bind<IPlatformSettings>().ToSingleton<PlatformSettings>()
.Bind<IPlatformThreadingInterface>().ToConstant(PlatformThreadingInterface.Instance);
.Bind<IPlatformThreadingInterface>().ToConstant(PlatformThreadingInterface.Instance)
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoader>();
}
}
}

12
tests/Avalonia.DesignerSupport.Tests/Checker.cs

@ -14,9 +14,9 @@ namespace Avalonia.DesignerSupport.Tests
private string _appDir;
private IntPtr _window;
public void DoCheck(string outputDir, string xamlText)
public void DoCheck(string baseAsset, string xamlText)
{
_appDir = Path.GetFullPath(outputDir);
_appDir = new FileInfo(baseAsset).Directory.FullName;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
foreach (var asm in Directory.GetFiles(_appDir).Where(f => f.ToLower().EndsWith(".dll") || f.ToLower().EndsWith(".exe")))
try
@ -29,8 +29,12 @@ namespace Avalonia.DesignerSupport.Tests
var dic = new Dictionary<string, object>();
var api = new DesignerApi(dic) { OnResize = OnResize, OnWindowCreated = OnWindowCreated };
LookupStaticMethod("Avalonia.DesignerSupport.DesignerAssist", "Init").Invoke(null, new object[] { dic });
api.UpdateXaml(xamlText);
api.UpdateXaml2(new DesignerApiXamlFileInfo
{
Xaml = xamlText,
AssemblyPath = baseAsset
}.Dictionary);
if (_window == IntPtr.Zero)
throw new Exception("Something went wrong");

4
tests/Avalonia.DesignerSupport.Tests/DesignerSupportTests.cs

@ -12,8 +12,8 @@ namespace Avalonia.DesignerSupport.Tests
public class DesignerSupportTests
{
[Theory,
InlineData(@"..\..\..\Avalonia.DesignerSupport.TestApp\bin\$BUILD", @"..\..\..\Avalonia.DesignerSupport.TestApp\MainWindow.xaml"),
InlineData(@"..\..\..\..\samples\ControlCatalog.Desktop\bin\$BUILD", @"..\..\..\..\samples\ControlCatalog\MainWindow.xaml")]
InlineData(@"..\..\..\Avalonia.DesignerSupport.TestApp\bin\$BUILD\Avalonia.DesignerSupport.TestApp.exe", @"..\..\..\Avalonia.DesignerSupport.TestApp\MainWindow.xaml"),
InlineData(@"..\..\..\..\samples\ControlCatalog.Desktop\bin\$BUILD\ControlCatalog.dll", @"..\..\..\..\samples\ControlCatalog\MainWindow.xaml")]
public void DesgignerApiShoudBeOperational(string outputDir, string xamlFile)
{
var xaml = File.ReadAllText(xamlFile);

Loading…
Cancel
Save