7

do you know how do you create a custom widget in GTK 3 ? I tried to subclass GtkDrawingArea in C for hours. Gnome.org only provides a succinct tutorial on how to subclass G_OBJECT. My issue is that G_Object/GTK fails to view my custom StrokerNodalContainer as a subclass of GtkWidget when casting with GTK_WIDGET, even tough my definition struct contains a line like this :

GtkDrawingArea parent_instance;

It says :

invalid cast from 'StrokerNodalContainer' to 'GtkWidget'

Here is the full code if you suspect something else might be wrong. It's minimal so I don't see any reason for external code to mess up.

stroker-nodalcontainer.h

#ifndef __STROKER_NODALCONTAINER_H__
#define __STROKER_NODALCONTAINER_H__

#ifndef NO_INCLUDE_WITHIN_HEADERS
#include <gtk/gtk.h>
#endif

#define STROKER_TYPE_NODAL_CONTAINER                  (stroker_nodal_container_get_type ())
#define STROKER_NODAL_CONTAINER(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), STROKER_TYPE_NODAL_CONTAINER, StrokerNodalContainer))
#define STROKER_NODAL_CONTAINER_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST  ((klass), STROKER_TYPE_NODAL_CONTAINER, StrokerNodalContainerClass))
#define STROKER_IS_NODAL_CONTAINER(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STROKER_TYPE_NODAL_CONTAINER))
#define STROKER_IS_NODAL_CONTAINER_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE  ((klass), STROKER_TYPE_NODAL_CONTAINER))
#define STROKER_NODAL_CONTAINER_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS  ((obj), STROKER_TYPE_NODAL_CONTAINER, StrokerNodalContainerClass))

typedef struct _StrokerNodalContainer      StrokerNodalContainer;
typedef struct _StrokerNodalContainerClass StrokerNodalContainerClass;

struct _StrokerNodalContainer
{
    GtkDrawingArea parent_instance;
};

struct _StrokerNodalContainerClass
{
    GtkDrawingAreaClass parent_class;
};

GType stroker_nodal_container_get_type(void);

//StrokerNodalContainer* stroker_nodalcontainer_new(void);

#endif /* __STROKER_NODALCONTAINER_H__ */

stroker-nodalcontainer.c

#include <gtk/gtk.h>
#include "stroker-nodalcontainer.h"

G_DEFINE_TYPE( StrokerNodalContainer, stroker_nodal_container, G_TYPE_OBJECT )

static void stroker_nodal_container_class_init( StrokerNodalContainerClass* klass )
    {}

static void stroker_nodal_container_init( StrokerNodalContainer* self )
{
    GdkRGBA c;
    GtkWidget *widget;

    gdk_rgba_parse(&c, "blue");
    widget = GTK_WIDGET(self);

    gtk_widget_override_background_color( widget, GTK_STATE_FLAG_NORMAL, &c );
}

main.c

#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <cairo/cairo.h>

#include "stroker-nodalcontainer.h"

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *nodalWidget;

    gtk_init( &argc, &argv );

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "Stroker");
    g_signal_connect( window, "destroy", G_CALLBACK (gtk_main_quit), NULL );
    gtk_container_set_border_width( GTK_CONTAINER(window), 10 );
    gtk_widget_show (window);

    nodalWidget = g_object_new(STROKER_TYPE_NODAL_CONTAINER,NULL);
    gtk_container_add( GTK_CONTAINER(window), nodalWidget );
    gtk_widget_show (nodalWidget);

    gtk_main();


    return EXIT_SUCCESS;
}

Thank you for any help !

Lærne
  • 3,010
  • 1
  • 22
  • 33
  • there is an example on the official wiki but it's using Vala, not C, https://wiki.gnome.org/Projects/Vala/CustomWidgetSamples – user2485710 Sep 13 '14 at 15:10
  • Yeah, but Vala or C++ or java or python are so easy : the class inheritance feature is within the core of the language, so they just use that. I'm failing to have my `GObject` inheritance recognised. – Lærne Sep 13 '14 at 16:09
  • Vala compiles down to C89 + Glib + Gobject, I suggest the following: code something basic in Vala, compile Vala to C, inspect the generated C code . – user2485710 Sep 13 '14 at 16:13
  • 2
    I wrote a tutorial on this once: http://ptomato.name/advanced-gtk-techniques/html/custom-container.html – ptomato Sep 14 '14 at 06:29
  • Maybe you could edit the title so it states your actual problem? – DarkTrick May 14 '20 at 05:46

1 Answers1

7

The error message is probably because of this:

G_DEFINE_TYPE( StrokerNodalContainer, stroker_nodal_container, G_TYPE_OBJECT )

If you look at the documentation for G_DEFINE_TYPE() you'll see the third argument should be the parent type: you probably want GTK_TYPE_DRAWING_AREA here.

Jussi Kukkonen
  • 13,857
  • 1
  • 37
  • 54