diff --git a/Source/Samples/Samples.csproj b/Source/Samples/Samples.csproj index 6d8640523..026a3ff24 100644 --- a/Source/Samples/Samples.csproj +++ b/Source/Samples/Samples.csproj @@ -10,6 +10,7 @@ %(Filename)%(Extension) + diff --git a/Source/Samples/Sections/Widgets/CustomWidgets/ImageDrawn.cs b/Source/Samples/Sections/Widgets/CustomWidgets/ImageDrawn.cs new file mode 100644 index 000000000..97470ca8b --- /dev/null +++ b/Source/Samples/Sections/Widgets/CustomWidgets/ImageDrawn.cs @@ -0,0 +1,110 @@ +// adopted from: https://github.com/mono/xwt/blob/master/Xwt.XamMac/Xwt.Mac/ImageHandler.cs + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Gtk; +using Gdk; +using System.Runtime.InteropServices; +using Cairo; +using Rectangle = Gdk.Rectangle; + +namespace Samples +{ + // This is a completely pointless widget, but its for testing subclassing Widget.OnDrawn + public class GtkDrawingArea : Gtk.DrawingArea { } + + public class ImageBox : GtkDrawingArea + { + Pixbuf image; + float yalign = 0.5f, xalign = 0.5f; + + public ImageBox(Pixbuf img) : this() + { + Image = img; + } + + public ImageBox() + { + this.HasWindow = false; + this.AppPaintable = true; + } + + public Pixbuf Image { + get { return image; } + set { + image = value; + SetSizeRequest((int) image.Width, (int) image.Height); + //QueueDraw(); + } + } + + private Size SizeRequestet { get; set; } + + public float Yalign { + get { return yalign; } + set { + yalign = value; + QueueDraw(); + } + } + + public float Xalign { + get { return xalign; } + set { + xalign = value; + QueueDraw(); + } + } + + void DrawPixbuf(Cairo.Context ctx, Gdk.Pixbuf img, double x, double y, Size idesc) + { + ctx.Save(); + ctx.Translate(x, y); + + ctx.Scale(idesc.Width / (double) img.Width, idesc.Height / (double) img.Height); + Gdk.CairoHelper.SetSourcePixbuf(ctx, img, 0, 0); + +#pragma warning disable 618 + using (var p = ctx.Source) { + if (p is SurfacePattern pattern) { + if (idesc.Width > img.Width || idesc.Height > img.Height) { + // Fixes blur issue when rendering on an image surface + pattern.Filter = Cairo.Filter.Fast; + } else + pattern.Filter = Cairo.Filter.Good; + } + } +#pragma warning restore 618 + + + ctx.Paint(); + + ctx.Restore(); + } + + protected override bool OnDrawn(Cairo.Context cr) + { + if (image == default) + return true; + var a = Allocation; + var size = Allocation.Size; + Pixbuf pixbuff = image; + // HACK: Gtk sends sometimes an expose/draw event while the widget reallocates. + // In that case we would draw in the wrong area, which may lead to artifacts + // if no other widget updates it. Alternative: we could clip the + // allocation bounds, but this may have other issues. + if (a.Width == 1 && a.Height == 1 && a.X == -1 && a.Y == -1) // the allocation coordinates on reallocation + return base.OnDrawn(cr); + + var x = (int) ((a.Width - (float) pixbuff.Width) * xalign); + var y = (int) ((a.Height - (float) pixbuff.Height) * yalign); + if (x < 0) x = 0; + if (y < 0) y = 0; + DrawPixbuf(cr, pixbuff, x, y, size); + return base.OnDrawn(cr); + } + } +} \ No newline at end of file diff --git a/Source/Samples/Sections/Widgets/ImageSection.cs b/Source/Samples/Sections/Widgets/ImageSection.cs new file mode 100644 index 000000000..8cb2d01c7 --- /dev/null +++ b/Source/Samples/Sections/Widgets/ImageSection.cs @@ -0,0 +1,50 @@ +// This is free and unencumbered software released into the public domain. +// Happy coding!!! - GtkSharp Team + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Atk; +using Gdk; +using Gtk; + +namespace Samples +{ + [Section(ContentType = typeof(ImageBox), Category = Category.Widgets)] + class ImageSection : ListSection + { + public ImageSection() + { + AddItem(CreateContainer()); + } + + public (string, Widget) CreateContainer() + { + Stream GetResourceStream(Assembly assembly, string name) + { + var resources = assembly.GetManifestResourceNames(); + var resourceName = resources.SingleOrDefault(str => str == name); + + // try harder: + if (resourceName == default) { + resourceName = resources.SingleOrDefault(str => str.EndsWith(name)); + } + + if (resourceName == default) + return default; + var stream = assembly.GetManifestResourceStream(resourceName); + return stream; + } + Pixbuf image = default; + using (var stream = GetResourceStream(typeof(ImageSection).Assembly, "Testpic.png")) { + image = new Pixbuf(stream); + } + + var container = new ImageBox(image); + + + return ($"{nameof(ImageBox)}:", container); + } + } +} \ No newline at end of file diff --git a/Source/Samples/Testpic.png b/Source/Samples/Testpic.png new file mode 100644 index 000000000..6aea67172 Binary files /dev/null and b/Source/Samples/Testpic.png differ