Hi.
This is a simple example that demonstrates how to create composited widgets (widget that is created from other stock widgets). Feel free to ask if something isn't clear.
Cheers,
Tadej
c-widget.h
Code:
#ifndef C_WIDGET_H
#define C_WIDGET_H
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define C_TYPE_WIDGET (c_widget_get_type())
#define C_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), C_TYPE_WIDGET, CWidget))
#define C_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), C_TYPE_WIDGET, CWidgetClass))
#define C_IS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), C_TYPE_WIDGET))
#define C_IS_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), C_TYPE_WIDGET))
#define C_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), C_TYPE_WIDGET, CWidgetClass))
typedef struct _CWidget CWidget;
typedef struct _CWidgetClass CWidgetClass;
typedef struct _CWidgetPrivate CWidgetPrivate;
struct _CWidget
{
GtkTable parent;
/*< Private >*/
CWidgetPrivate *priv;
};
struct _CWidgetClass
{
GtkTableClass parent_class;
};
/* Public interface */
GType c_widget_get_type (void) G_GNUC_CONST;
int c_widget_get_value (CWidget *widget);
void c_widget_set_value (CWidget *widget,
int value);
GtkWidget * c_widget_new (void);
G_END_DECLS
#endif /* C_WIDGET_H */
c-widget.c
Code:
#include "c-widget.h"
struct _CWidgetPrivate
{
int value;
GtkWidget *label,
*up,
*down;
};
enum
{
PROP_0,
PROP_VALUE,
LAST_PROP
};
static GObject *c_widget_constructor (GType type,
guint n_constr_props,
GObjectConstructParam *constr_params);
static void c_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void c_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
/* Callbacks */
static void cb_up (GtkButton *button,
CWidget *widget);
static void cb_down (GtkButton *button,
CWidget *widget);
G_DEFINE_TYPE (CWidget, c_widget, GTK_TYPE_TABLE)
static void
c_widget_class_init (CWidgetClass *klass)
{
GObjectClass *g_class;
GParamSpec *pspec;
g_class = G_OBJECT_CLASS (klass);
g_class->constructor = c_widget_constructor;
g_class->set_property = c_widget_set_property;
g_class->get_property = c_widget_get_property;
pspec = g_param_spec_int ("value", "Value of widget", "Displayed value",
G_MININT, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (g_class, PROP_VALUE, pspec);
g_type_class_add_private (klass, sizeof (CWidgetPrivate));
}
static GObject *
c_widget_constructor (GType type,
guint n_constr_props,
GObjectConstructParam *constr_params)
{
CWidgetPrivate *priv;
GObject *object;
GtkTable *table;
object = G_OBJECT_CLASS (c_widget_parent_class)->constructor (type,
n_constr_props,
constr_params);
priv = C_WIDGET (object)->priv;
table = GTK_TABLE (object);
gtk_widget_push_composite_child ();
gtk_table_resize (table, 2, 2);
gtk_table_set_homogeneous (table, FALSE);
priv->label = gtk_label_new ("0");
gtk_table_attach_defaults (table, priv->label, 0, 1, 0, 2);
gtk_widget_show (priv->label);
priv->up = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
g_signal_connect (priv->up, "clicked",
G_CALLBACK (cb_up), object);
gtk_table_attach_defaults (table, priv->up, 1, 2, 0, 1);
gtk_widget_show (priv->up);
priv->down = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
g_signal_connect (priv->down, "clicked",
G_CALLBACK (cb_down), object);
gtk_table_attach_defaults (table, priv->down, 1, 2, 1, 2);
gtk_widget_show (priv->down);
gtk_widget_pop_composite_child ();
return object;
}
static void
c_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
CWidget *widget = C_WIDGET (object);
switch (prop_id)
{
case PROP_VALUE:
c_widget_set_value (widget, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
c_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CWidgetPrivate *priv = C_WIDGET (object)->priv;
switch (prop_id)
{
case PROP_VALUE:
g_value_set_int (value, priv->value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
c_widget_init (CWidget *widget)
{
CWidgetPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (widget,
C_TYPE_WIDGET,
CWidgetPrivate);
widget->priv = priv;
priv->value = 0;
}
static void
cb_up (GtkButton *button,
CWidget *widget)
{
c_widget_set_value (widget, widget->priv->value + 1);
}
static void
cb_down (GtkButton *button,
CWidget *widget)
{
c_widget_set_value (widget, widget->priv->value - 1);
}
/* Public interface */
int
c_widget_get_value (CWidget *widget)
{
g_return_val_if_fail (C_IS_WIDGET (widget), 0);
return widget->priv->value;
}
void
c_widget_set_value (CWidget *widget,
int value)
{
char *text;
CWidgetPrivate *priv;
g_return_if_fail (C_IS_WIDGET (widget));
if (widget->priv->value == value)
return;
priv = widget->priv;
priv->value = value;
/* Update label */
text = g_strdup_printf ("%d", priv->value);
gtk_label_set_label (GTK_LABEL (priv->label), text);
g_free (text);
}
GtkWidget *
c_widget_new (void)
{
return g_object_new (C_TYPE_WIDGET, NULL);
}
test.c
Code:
#include "c-widget.h"
int
main (int argc,
char **argv)
{
GtkWidget *window,
*tester;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", gtk_main_quit, NULL);
tester = c_widget_new ();
gtk_container_add (GTK_CONTAINER (window), tester);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
Makefile
Code:
CC = gcc
CFLAGS = `pkg-config --cflags gtk+-2.0`
LDFLAGS = `pkg-config --libs gtk+-2.0`
test: test.o c-widget.o
c-widget.o: c-widget.c c-widget.h
test.o: test.c c-widget.h