Merge pull request #151 from lytico/lytico_overridechain

Fix overide chain
This commit is contained in:
Harry 2020-04-16 21:49:54 +02:00 committed by GitHub
commit 7054da77af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 191 additions and 5 deletions

View File

@ -0,0 +1,28 @@
using System;
using System.Runtime.InteropServices;
namespace GLib
{
public static class AbiStructExtension
{
public static N BaseOverride<N>(this AbiStruct class_abi, GType gtype, string fieldname) where N : Delegate
{
N unmanaged = null;
unsafe {
IntPtr raw_ptr = IntPtr.Zero;
while (raw_ptr == IntPtr.Zero && GType.IsManaged(gtype)) {
gtype = gtype.GetThresholdType();
var abi_ptr = (IntPtr*) (((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset(fieldname));
raw_ptr = *abi_ptr;
}
if (raw_ptr != IntPtr.Zero) {
unmanaged = Marshal.GetDelegateForFunctionPointer<N>(raw_ptr);
}
}
return unmanaged;
}
}
}

View File

@ -10,6 +10,7 @@
<EmbeddedResource Include="**\*.glade">
<LogicalName>%(Filename)%(Extension)</LogicalName>
</EmbeddedResource>
<EmbeddedResource Include="Testpic.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Sections\**\*.cs" Visible="false">

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

BIN
Source/Samples/Testpic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -207,11 +207,7 @@ namespace GtkSharp.Generation {
this.GenerateMethodBody (sw, null);
// Find the first unmanaged ancestor
sw.WriteLine ("\t\t\t{0}NativeDelegate unmanaged = null;", Name);
sw.WriteLine ("\t\t\tunsafe {");
sw.WriteLine ("\t\t\t\tIntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset(\"{0}\"));", CName);
sw.WriteLine ("\t\t\t\tunmanaged = ({0}NativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof({0}NativeDelegate));", this.Name);
sw.WriteLine ("\t\t\t}");
sw.WriteLine ($"\t\t\t{Name}NativeDelegate unmanaged = class_abi.BaseOverride<{Name}NativeDelegate>(this.LookupGType(), \"{CName}\");");
sw.Write ("\t\t\tif (unmanaged == null) ");
if (parms.HasOutParam)
sw.WriteLine ("throw new InvalidOperationException (\"No base method to invoke\");");

View File

@ -147,6 +147,7 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\tusing System.Collections;");
sw.WriteLine ("\tusing System.Collections.Generic;");
sw.WriteLine ("\tusing System.Runtime.InteropServices;");
sw.WriteLine ("\tusing static GLib.AbiStructExtension;");
sw.WriteLine ();
SymbolTable table = SymbolTable.Table;