Sign up

Downcasting

Say I have:

class PresentationTreeView: TreeView { … }

and am using Glade which declares a TreeView instance. Clearly one can:

TreeView tv = cast(TreeView)builder.getObject("presentationList");

but I need tv to be a PresentationTreeView. If I just cast I end up with a run time error 139. So the question is what is the correct way to downcast in this situation?

gtkmm uses the get_widget_derived approach. Is something similar not possible in D?

(Turns out I can use the same approach in D as is needed in Python if not.)

Re: Downcasting

On 9/6/18 8:29 PM, Russel Winder wrote:

Say I have:

class PresentationTreeView: TreeView { … }

and am using Glade which declares a TreeView instance. Clearly one can:

TreeView tv = cast(TreeView)builder.getObject("presentationList");

but I need tv to be a PresentationTreeView. If I just cast I end up with a run time error 139. So the question is what is the correct way to downcast in this situation?

gtkmm uses the get_widget_derived approach. Is something similar not possible in D?

(Turns out I can use the same approach in D as is needed in Python if not.)

The problem is that GtkBuilder doesn't instantiate a new
PresentationTreeView but only a TreeView.

One way around this is to make the PresentationTreeView a proper Gtk
class by using gtkd.Implement.ImplementClass, and then use
PresentationTreeView in the builder file.

The type name would be the fully qualified name in pascal case, and you
would need to call PresentationTreeView.getType() atleast once before
using GtkBuilder.

As for workarounds you could add a constructor to PresentationTreeView
that passes the gtk handle from the treeview to super.

Or add this to PresentationTreeView:

//Should be the first field in the class.
protected GtkTreeView* handle;

public static GType getType()
{
	return TreeView.getType();
}

public this (GtkTreeView* gtkTreeView, bool ownedRef = false)
{
	this.gtkTreeView = gtkTreeView;
	super(cast(GtkContainer*)gtkTreeView, ownedRef);
}

With that in place the opCast defined for ObjectG should recognize you
class as one that is part of GtkD/Gtk and allow you to cast the TreeView
to it.

Re: Downcasting

On Thu, 6 Sep 2018 23:10:24 +0200, Mike Wey wrote:

On 9/6/18 8:29 PM, Russel Winder wrote:

[…]

The problem is that GtkBuilder doesn't instantiate a new
PresentationTreeView but only a TreeView.

And as it should really, that is what is in the Glade file. :-)

One way around this is to make the PresentationTreeView a proper Gtk
class by using gtkd.Implement.ImplementClass, and then use
PresentationTreeView in the builder file.

The type name would be the fully qualified name in pascal case, and you
would need to call PresentationTreeView.getType() atleast once before
using GtkBuilder.

Whilst this has a great appeal, I suspect Glade itself would have problems with this, it would require using TreeView in Glade and then editing after the fact. Feasible certainly, but annoying.

As for workarounds you could add a constructor to PresentationTreeView
that passes the gtk handle from the treeview to super.

I initially started down this road but wasn't sure what to actually put in the constructor to avoid having an extra field.

Or add this to PresentationTreeView:

//Should be the first field in the class.
protected GtkTreeView* handle;

public static GType getType()
{
	return TreeView.getType();
}

public this (GtkTreeView* gtkTreeView, bool ownedRef = false)
{
	this.gtkTreeView = gtkTreeView;
	super(cast(GtkContainer*)gtkTreeView, ownedRef);
}

With that in place the opCast defined for ObjectG should recognize you
class as one that is part of GtkD/Gtk and allow you to cast the TreeView
to it.

So this makes the PresentationTreeView masquerade as a TreeView as far as GtkD is concerned?

I guess having the explicit extra field is something I am not immediately comfortable with, but mostly as I am a beginner at this.

I do have a need to instantiate PresentationTreeView explicitly as well as having this one Gtk.Builder instantiated one. This leads me back to the simpler form of constructor workaround which I think avoids having the getType() and the extra field.

Thanks for taking the time to answer this so fully, it really is very much appreciated.

Re: Downcasting

On Fri, 07 Sep 2018 08:09:40 GMT, Russel Winder wrote:
[…]

I initially started down this road but wasn't sure what to actually put in the constructor to avoid having an extra field.

public this(TreeView tv) {
	super(tv.getTreeViewStruct);
…

Seems to just do the trick.

Simple when you know how. :-)

Re: Downcasting

On 9/7/18 10:09 AM, Russel Winder wrote:

On Thu, 6 Sep 2018 23:10:24 +0200, Mike Wey wrote:

On 9/6/18 8:29 PM, Russel Winder wrote:
[…]

The problem is that GtkBuilder doesn't instantiate a new
PresentationTreeView but only a TreeView.

And as it should really, that is what is in the Glade file. :-)

You can add your custom widget to Glade if you really want to :D

https://developer.gnome.org/gladeui/unstable/widgetclasses.html

Re: Downcasting

I'll pass on that one I think, it's a class just for this one situation.

The special constructor seems to work a treat – though it is good to know about the other two options.