GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Fri Apr 18, 2014 1:07 pm

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: A custom spin button ?
PostPosted: Thu Sep 22, 2011 1:59 am 
Offline
GTK+ Guru

Joined: Fri Mar 25, 2011 5:16 pm
Posts: 176
Location: USA
I need a spin button button with much larger up/down buttons. It will be used for time input. It's to be displayed on a 7" resistive touch screen (800 x 480) so the tiny stock one's won't work. I thought about just using a label and two buttons but gtk_label_set_text() takes a const.
1) Can I modify the stock spin button to use larger up/down buttons or should I just create a custom widget?
If I go the custom widget route, does anyone have some links? I've done a ton of googling and I can't find any up to date tutorials covering custom widgets with C language.


Top
 Profile  
 
 Post subject: Re: A custom spin button ?
PostPosted: Fri Sep 23, 2011 3:55 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

I would take a middle approach: create composited custom widget (deriving from GtkTable or some other container) using a GtkLabel and two buttons. This would be really simple to hook up (I can give you some sample code if you wish).

As for the label taking constant string, you can always update it using gtk_label_set_label().

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: A custom spin button ?
PostPosted: Fri Sep 23, 2011 5:36 pm 
Offline
GTK+ Guru

Joined: Fri Mar 25, 2011 5:16 pm
Posts: 176
Location: USA
Yes, that would be great if you could show me a sample.


Top
 Profile  
 
 Post subject: Re: A custom spin button ?
PostPosted: Fri Sep 23, 2011 10:28 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
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


Top
 Profile  
 
 Post subject: Re: A custom spin button ?
PostPosted: Sat Sep 24, 2011 2:45 am 
Offline
GTK+ Guru

Joined: Fri Mar 25, 2011 5:16 pm
Posts: 176
Location: USA
It works great, thank you very much. It will take me some time for me to go through it. I'm not familiar with the GObject lib.


Top
 Profile  
 
 Post subject: Re: A custom spin button ?
PostPosted: Sun Sep 25, 2011 12:59 am 
Offline
GTK+ Guru

Joined: Fri Mar 25, 2011 5:16 pm
Posts: 176
Location: USA
I'm trying to get more information on GTK_TYPE_TABLE in this line of c-widget.c:
Code:
G_DEFINE_TYPE (CWidget, c_widget, GTK_TYPE_TABLE)

I did a grep search and came up with: gtktable.h line 40
Code:
#define   GTK_TYPE_TABLE      (gtk_table_get_type ())

gtktable.h line 103,
Code:
GType   gtk_table_get_type  (void) G_GNUC_CONST;

gtktypefuncs.c line 348,
Code:
*tp++ = gtk_table_get_type();

But I can't seam to find the definition of gtk_table_get_type ()
Where is it?


Top
 Profile  
 
 Post subject: Re: A custom spin button ?
PostPosted: Sun Sep 25, 2011 7:41 am 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

I would advice you to read GObject reference manual, since all of the stuff is explained there. There is even a tutorial on how to create new GObject-derived types.

As for you question here, *_get_type() functions are defined by G_DEFINE_TYPE() macro. This macro expands into quite a large piece of code that is listed in GObject manual here.

Cheers,
Tadej


Top
 Profile  
 
 Post subject: Re: A custom spin button ?
PostPosted: Sun Sep 25, 2011 5:08 pm 
Offline
GTK+ Guru

Joined: Fri Mar 25, 2011 5:16 pm
Posts: 176
Location: USA
Thank you for the function link. Now that you mention it, I just started reading the GObject manual and found it's tutorial section yesterday, thank you


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group