Merge pull request #151 from lytico/lytico_overridechain
Fix overide chain
This commit is contained in:
commit
7054da77af
7 changed files with 191 additions and 5 deletions
28
Source/Libs/GLibSharp/AbiStructExtensions.cs
Normal file
28
Source/Libs/GLibSharp/AbiStructExtensions.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
<EmbeddedResource Include="**\*.glade">
|
<EmbeddedResource Include="**\*.glade">
|
||||||
<LogicalName>%(Filename)%(Extension)</LogicalName>
|
<LogicalName>%(Filename)%(Extension)</LogicalName>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Testpic.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Sections\**\*.cs" Visible="false">
|
<EmbeddedResource Include="Sections\**\*.cs" Visible="false">
|
||||||
|
|
110
Source/Samples/Sections/Widgets/CustomWidgets/ImageDrawn.cs
Normal file
110
Source/Samples/Sections/Widgets/CustomWidgets/ImageDrawn.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
Source/Samples/Sections/Widgets/ImageSection.cs
Normal file
50
Source/Samples/Sections/Widgets/ImageSection.cs
Normal 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
BIN
Source/Samples/Testpic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
|
@ -207,11 +207,7 @@ namespace GtkSharp.Generation {
|
||||||
|
|
||||||
this.GenerateMethodBody (sw, null);
|
this.GenerateMethodBody (sw, null);
|
||||||
// Find the first unmanaged ancestor
|
// Find the first unmanaged ancestor
|
||||||
sw.WriteLine ("\t\t\t{0}NativeDelegate unmanaged = null;", Name);
|
sw.WriteLine ($"\t\t\t{Name}NativeDelegate unmanaged = class_abi.BaseOverride<{Name}NativeDelegate>(this.LookupGType(), \"{CName}\");");
|
||||||
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.Write ("\t\t\tif (unmanaged == null) ");
|
sw.Write ("\t\t\tif (unmanaged == null) ");
|
||||||
if (parms.HasOutParam)
|
if (parms.HasOutParam)
|
||||||
sw.WriteLine ("throw new InvalidOperationException (\"No base method to invoke\");");
|
sw.WriteLine ("throw new InvalidOperationException (\"No base method to invoke\");");
|
||||||
|
|
|
@ -147,6 +147,7 @@ namespace GtkSharp.Generation {
|
||||||
sw.WriteLine ("\tusing System.Collections;");
|
sw.WriteLine ("\tusing System.Collections;");
|
||||||
sw.WriteLine ("\tusing System.Collections.Generic;");
|
sw.WriteLine ("\tusing System.Collections.Generic;");
|
||||||
sw.WriteLine ("\tusing System.Runtime.InteropServices;");
|
sw.WriteLine ("\tusing System.Runtime.InteropServices;");
|
||||||
|
sw.WriteLine ("\tusing static GLib.AbiStructExtension;");
|
||||||
sw.WriteLine ();
|
sw.WriteLine ();
|
||||||
|
|
||||||
SymbolTable table = SymbolTable.Table;
|
SymbolTable table = SymbolTable.Table;
|
||||||
|
|
Loading…
Reference in a new issue