Bug 319607 – Add a throbber (activity widget) to GTK+

Add GtkSpinner activity throbber, as well as a cell renderer.
This commit is contained in:
Bastien Nocera 2009-07-21 02:16:56 +01:00
parent df53e6ad8b
commit d21700f510
13 changed files with 1403 additions and 39 deletions

View File

@ -37,6 +37,7 @@ demos = \
rotated_text.c \
search_entry.c \
sizegroup.c \
spinner.c \
stock_browser.c \
textview.c \
textscroll.c \

View File

@ -10,6 +10,8 @@
#include <gtk/gtk.h>
static GtkWidget *window = NULL;
static GtkTreeModel *model = NULL;
static guint timeout = 0;
typedef struct
{
@ -26,6 +28,8 @@ enum
COLUMN_NUMBER,
COLUMN_SEVERITY,
COLUMN_DESCRIPTION,
COLUMN_PULSE,
COLUMN_ACTIVE,
NUM_COLUMNS
};
@ -47,6 +51,33 @@ static Bug data[] =
{ FALSE, 1, "Normal", "First bug :=)" },
};
static gboolean
spinner_timeout (gpointer data)
{
GtkTreeIter iter;
guint pulse;
if (model == NULL)
return FALSE;
gtk_tree_model_get_iter_first (model, &iter);
gtk_tree_model_get (model, &iter,
COLUMN_PULSE, &pulse,
-1);
if (pulse == G_MAXUINT)
pulse = 0;
else
pulse++;
gtk_list_store_set (GTK_LIST_STORE (model),
&iter,
COLUMN_PULSE, pulse,
COLUMN_ACTIVE, TRUE,
-1);
return TRUE;
}
static GtkTreeModel *
create_model (void)
{
@ -56,21 +87,25 @@ create_model (void)
/* create list store */
store = gtk_list_store_new (NUM_COLUMNS,
G_TYPE_BOOLEAN,
G_TYPE_UINT,
G_TYPE_STRING,
G_TYPE_STRING);
G_TYPE_BOOLEAN,
G_TYPE_UINT,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_UINT,
G_TYPE_BOOLEAN);
/* add data to the list store */
for (i = 0; i < G_N_ELEMENTS (data); i++)
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_FIXED, data[i].fixed,
COLUMN_NUMBER, data[i].number,
COLUMN_SEVERITY, data[i].severity,
COLUMN_DESCRIPTION, data[i].description,
-1);
COLUMN_FIXED, data[i].fixed,
COLUMN_NUMBER, data[i].number,
COLUMN_SEVERITY, data[i].severity,
COLUMN_DESCRIPTION, data[i].description,
COLUMN_PULSE, 0,
COLUMN_ACTIVE, FALSE,
-1);
}
return GTK_TREE_MODEL (store);
@ -78,8 +113,8 @@ create_model (void)
static void
fixed_toggled (GtkCellRendererToggle *cell,
gchar *path_str,
gpointer data)
gchar *path_str,
gpointer data)
{
GtkTreeModel *model = (GtkTreeModel *)data;
GtkTreeIter iter;
@ -110,48 +145,75 @@ add_columns (GtkTreeView *treeview)
/* column for fixed toggles */
renderer = gtk_cell_renderer_toggle_new ();
g_signal_connect (renderer, "toggled",
G_CALLBACK (fixed_toggled), model);
G_CALLBACK (fixed_toggled), model);
column = gtk_tree_view_column_new_with_attributes ("Fixed?",
renderer,
"active", COLUMN_FIXED,
NULL);
renderer,
"active", COLUMN_FIXED,
NULL);
/* set this column to a fixed sizing (of 50 pixels) */
gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
GTK_TREE_VIEW_COLUMN_FIXED);
GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
gtk_tree_view_append_column (treeview, column);
/* column for bug numbers */
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Bug number",
renderer,
"text",
COLUMN_NUMBER,
NULL);
renderer,
"text",
COLUMN_NUMBER,
NULL);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NUMBER);
gtk_tree_view_append_column (treeview, column);
/* column for severities */
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Severity",
renderer,
"text",
COLUMN_SEVERITY,
NULL);
renderer,
"text",
COLUMN_SEVERITY,
NULL);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_SEVERITY);
gtk_tree_view_append_column (treeview, column);
/* column for description */
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Description",
renderer,
"text",
COLUMN_DESCRIPTION,
NULL);
renderer,
"text",
COLUMN_DESCRIPTION,
NULL);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_DESCRIPTION);
gtk_tree_view_append_column (treeview, column);
/* column for spinner */
renderer = gtk_cell_renderer_spinner_new ();
column = gtk_tree_view_column_new_with_attributes ("Spinning",
renderer,
"pulse",
COLUMN_PULSE,
"active",
COLUMN_ACTIVE,
NULL);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_PULSE);
gtk_tree_view_append_column (treeview, column);
}
static gboolean
window_closed (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
model = NULL;
window = NULL;
if (timeout != 0)
{
g_source_remove (timeout);
timeout = 0;
}
return FALSE;
}
GtkWidget *
@ -162,17 +224,16 @@ do_list_store (GtkWidget *do_widget)
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *sw;
GtkTreeModel *model;
GtkWidget *treeview;
/* create window, etc */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_screen (GTK_WINDOW (window),
gtk_widget_get_screen (do_widget));
gtk_widget_get_screen (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "GtkListStore demo");
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_container_set_border_width (GTK_CONTAINER (window), 8);
vbox = gtk_vbox_new (FALSE, 8);
@ -183,10 +244,10 @@ do_list_store (GtkWidget *do_widget)
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_ETCHED_IN);
GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
/* create tree model */
@ -196,7 +257,7 @@ do_list_store (GtkWidget *do_widget)
treeview = gtk_tree_view_new_with_model (model);
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview),
COLUMN_DESCRIPTION);
COLUMN_DESCRIPTION);
g_object_unref (model);
@ -207,14 +268,25 @@ do_list_store (GtkWidget *do_widget)
/* finish & show */
gtk_window_set_default_size (GTK_WINDOW (window), 280, 250);
g_signal_connect (window, "delete-event",
G_CALLBACK (window_closed), NULL);
}
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show_all (window);
{
gtk_widget_show_all (window);
if (timeout == 0)
timeout = g_timeout_add (80, spinner_timeout, NULL);
}
else
{
gtk_widget_destroy (window);
window = NULL;
if (timeout != 0)
{
g_source_remove (timeout);
timeout = 0;
}
}
return window;

90
demos/gtk-demo/spinner.c Normal file
View File

@ -0,0 +1,90 @@
/* Spinner
*
* GtkSpinner allows to show that background activity is on-going.
*
*/
#include <gtk/gtk.h>
static GtkWidget *window = NULL;
static GtkWidget *spinner_sensitive = NULL;
static GtkWidget *spinner_unsensitive = NULL;
static void
on_play_clicked (GtkButton *button, gpointer user_data)
{
gtk_spinner_start (GTK_SPINNER (spinner_sensitive));
gtk_spinner_start (GTK_SPINNER (spinner_unsensitive));
}
static void
on_stop_clicked (GtkButton *button, gpointer user_data)
{
gtk_spinner_stop (GTK_SPINNER (spinner_sensitive));
gtk_spinner_stop (GTK_SPINNER (spinner_unsensitive));
}
GtkWidget *
do_spinner (GtkWidget *do_widget)
{
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *spinner;
if (!window)
{
window = gtk_dialog_new_with_buttons ("GtkSpinner",
GTK_WINDOW (do_widget),
0,
GTK_STOCK_CLOSE,
GTK_RESPONSE_NONE,
NULL);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_signal_connect (window, "response",
G_CALLBACK (gtk_widget_destroy), NULL);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
/* Sensitive */
hbox = gtk_hbox_new (FALSE, 5);
spinner = gtk_spinner_new ();
gtk_container_add (GTK_CONTAINER (hbox), spinner);
gtk_container_add (GTK_CONTAINER (hbox), gtk_entry_new ());
gtk_container_add (GTK_CONTAINER (vbox), hbox);
spinner_sensitive = spinner;
/* Disabled */
hbox = gtk_hbox_new (FALSE, 5);
spinner = gtk_spinner_new ();
gtk_container_add (GTK_CONTAINER (hbox), spinner);
gtk_container_add (GTK_CONTAINER (hbox), gtk_entry_new ());
gtk_container_add (GTK_CONTAINER (vbox), hbox);
spinner_unsensitive = spinner;
gtk_widget_set_sensitive (hbox, FALSE);
button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PLAY);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (on_play_clicked), spinner);
gtk_container_add (GTK_CONTAINER (vbox), button);
button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_STOP);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (on_stop_clicked), spinner);
gtk_container_add (GTK_CONTAINER (vbox), button);
}
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show_all (window);
else
gtk_widget_destroy (window);
return window;
}

View File

@ -3584,6 +3584,24 @@ GTK_SPIN_BUTTON_GET_CLASS
gtk_spin_button_get_type
</SECTION>
<SECTION>
<FILE>gtkspinner</FILE>
<TITLE>GtkSpinner</TITLE>
GtkSpinner
gtk_spinner_new
gtk_spinner_start
gtk_spinner_stop
<SUBSECTION Standard>
GTK_SPINNER
GTK_IS_SPINNER
GTK_TYPE_SPINNER
GTK_SPINNER_CLASS
GTK_IS_SPINER_CLASS
GTK_SPINNER_GET_CLASS
<SUBSECTION Private>
gtk_spinner_get_type
</SECTION>
<SECTION>
<FILE>gtkstatusbar</FILE>
<TITLE>GtkStatusbar</TITLE>
@ -5106,6 +5124,23 @@ GtkCellRendererSpinPrivate
gtk_cell_renderer_spin_get_type
</SECTION>
<SECTION>
<FILE>gtkcellrendererspinner</FILE>
<TITLE>GtkCellRendererSpinner</TITLE>
GtkCellRendererSpinner
gtk_cell_renderer_spinner_new
<SUBSECTION Standard>
GTK_TYPE_CELL_RENDERER_SPINNER
GTK_CELL_RENDERER_SPINNER
GTK_CELL_RENDERER_SPINNER_CLASS
GTK_IS_CELL_RENDERER_SPINNER
GTK_IS_CELL_RENDERER_SPINNER_CLASS
GTK_CELL_RENDERER_SPINNER_GET_CLASS
<SUBSECTION Private>
GtkCellRendererSpinnerPrivate
gtk_cell_renderer_spinner_get_type
</SECTION>
<SECTION>
<FILE>gtkcellrendererpixbuf</FILE>
<TITLE>GtkCellRendererPixbuf</TITLE>
@ -5929,6 +5964,7 @@ gtk_paint_polygon
gtk_paint_shadow
gtk_paint_shadow_gap
gtk_paint_slider
gtk_paint_spinner
gtk_paint_string
gtk_paint_tab
gtk_paint_vline

View File

@ -178,6 +178,7 @@ gtk_public_h_sources = \
gtkcellrendererpixbuf.h \
gtkcellrendererprogress.h \
gtkcellrendererspin.h \
gtkcellrendererspinner.h\
gtkcellrenderertext.h \
gtkcellrenderertoggle.h \
gtkcellview.h \
@ -289,6 +290,7 @@ gtk_public_h_sources = \
gtksizegroup.h \
gtksocket.h \
gtkspinbutton.h \
gtkspinner.h \
gtkstatusbar.h \
gtkstatusicon.h \
gtkstock.h \
@ -433,6 +435,7 @@ gtk_base_c_sources = \
gtkcellrendererpixbuf.c \
gtkcellrendererprogress.c \
gtkcellrendererspin.c \
gtkcellrendererspinner.c\
gtkcellrenderertext.c \
gtkcellrenderertoggle.c \
gtkcellview.c \
@ -557,6 +560,7 @@ gtk_base_c_sources = \
gtkshow.c \
gtksocket.c \
gtkspinbutton.c \
gtkspinner.c \
gtkstatusbar.c \
gtkstatusicon.c \
gtkstock.c \

View File

@ -59,6 +59,7 @@
#include <gtk/gtkcellrendererpixbuf.h>
#include <gtk/gtkcellrendererprogress.h>
#include <gtk/gtkcellrendererspin.h>
#include <gtk/gtkcellrendererspinner.h>
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtkcellrenderertoggle.h>
#include <gtk/gtkcellview.h>
@ -168,6 +169,7 @@
#include <gtk/gtksizegroup.h>
#include <gtk/gtksocket.h>
#include <gtk/gtkspinbutton.h>
#include <gtk/gtkspinner.h>
#include <gtk/gtkstatusbar.h>
#include <gtk/gtkstatusicon.h>
#include <gtk/gtkstock.h>

View File

@ -670,6 +670,13 @@ gtk_cell_renderer_spin_new
#endif
#endif
#if IN_HEADER(__GTK_CELL_RENDERER_SPINNER_H__)
#if IN_FILE(__GTK_CELL_RENDERER_SPINNER_C__)
gtk_cell_renderer_spinner_get_type G_GNUC_CONST
gtk_cell_renderer_spinner_new
#endif
#endif
#if IN_HEADER(__GTK_CELL_RENDERER_PROGRESS_H__)
#if IN_FILE(__GTK_CELL_RENDERER_PROGRESS_C__)
gtk_cell_renderer_progress_get_type G_GNUC_CONST
@ -1277,6 +1284,7 @@ gtk_paint_resize_grip
gtk_paint_shadow
gtk_paint_shadow_gap
gtk_paint_slider
gtk_paint_spinner
gtk_paint_tab
gtk_paint_vline
gtk_border_new G_GNUC_MALLOC
@ -3802,6 +3810,15 @@ gtk_spin_button_update
#endif
#endif
#if IN_HEADER(__GTK_SPINNER_H__)
#if IN_FILE(__GTK_SPINNER_C__)
gtk_spinner_get_type G_GNUC_CONST
gtk_spinner_new
gtk_spinner_start
gtk_spinner_stop
#endif
#endif
#if IN_HEADER(__GTK_STATUSBAR_H__)
#if IN_FILE(__GTK_STATUSBAR_C__)
gtk_statusbar_get_context_id

View File

@ -0,0 +1,362 @@
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2009 Matthias Clasen <mclasen@redhat.com>
* Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2009 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 2007. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gtkintl.h"
#include <gtk/gtk.h>
#include "gtkcellrendererspinner.h"
#include "gtkalias.h"
enum {
PROP_0,
PROP_ACTIVE,
PROP_PULSE,
PROP_SIZE
};
struct _GtkCellRendererSpinnerPrivate
{
gboolean active;
guint pulse;
GtkIconSize icon_size, old_icon_size;
gint size;
};
#define GTK_CELL_RENDERER_SPINNER_GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
GTK_TYPE_CELL_RENDERER_SPINNER, \
GtkCellRendererSpinnerPrivate))
static void gtk_cell_renderer_spinner_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec);
static void gtk_cell_renderer_spinner_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_cell_renderer_spinner_get_size (GtkCellRenderer *cell,
GtkWidget *widget,
GdkRectangle *cell_area,
gint *x_offset,
gint *y_offset,
gint *width,
gint *height);
static void gtk_cell_renderer_spinner_render (GtkCellRenderer *cell,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags);
G_DEFINE_TYPE (GtkCellRendererSpinner, gtk_cell_renderer_spinner, GTK_TYPE_CELL_RENDERER)
static void
gtk_cell_renderer_spinner_class_init (GtkCellRendererSpinnerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
object_class->get_property = gtk_cell_renderer_spinner_get_property;
object_class->set_property = gtk_cell_renderer_spinner_set_property;
cell_class->get_size = gtk_cell_renderer_spinner_get_size;
cell_class->render = gtk_cell_renderer_spinner_render;
/* GtkCellRendererSpinner::active:
*
* Whether the spinner is active (ie. shown) in the cell
*
* Since 2.20
*/
g_object_class_install_property (object_class,
PROP_ACTIVE,
g_param_spec_boolean ("active",
P_("Active"),
P_("Whether the spinner is active (ie. shown) in the cell"),
FALSE,
G_PARAM_READWRITE));
/* GtkCellRendererSpinner::pulse:
*
* Pulse of the spinner. Increment this value to draw the next frame of the spinner animation.
* Usually, you would update this value in a timeout, every 80 milliseconds to show a full
* animation within one second.
*
* Since 2.20
*/
g_object_class_install_property (object_class,
PROP_PULSE,
g_param_spec_uint ("pulse",
P_("Pulse"),
P_("Pulse of the spinner"),
0, G_MAXUINT, 0,
G_PARAM_READWRITE));
/* GtkCellRendererSpinner::size:
*
* The #GtkIconSize value that specifies the size of the rendered spinner.
*
* Since 2.20
*/
g_object_class_install_property (object_class,
PROP_SIZE,
g_param_spec_enum ("size",
P_("Size"),
P_("The #GtkIconSize value that specifies the size of the rendered spinner"),
GTK_TYPE_ICON_SIZE, GTK_ICON_SIZE_MENU,
G_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (GtkCellRendererSpinnerPrivate));
}
static void
gtk_cell_renderer_spinner_init (GtkCellRendererSpinner *cell)
{
cell->priv = GTK_CELL_RENDERER_SPINNER_GET_PRIVATE (cell);
cell->priv->pulse = 0;
cell->priv->old_icon_size = GTK_ICON_SIZE_INVALID;
cell->priv->icon_size = GTK_ICON_SIZE_MENU;
}
/**
* gtk_cell_renderer_spinner_new
*
* Returns a new cell renderer which will show a spinner to indicate
* activity.
*
* Return value: a new #GtkCellRenderer
*
* Since: 2.20
*/
GtkCellRenderer *
gtk_cell_renderer_spinner_new (void)
{
return g_object_new (GTK_TYPE_CELL_RENDERER_SPINNER, NULL);
}
static void
gtk_cell_renderer_spinner_update_size (GtkCellRendererSpinner *cell,
GtkWidget *widget)
{
GtkCellRendererSpinnerPrivate *priv = cell->priv;
GdkScreen *screen;
GtkIconTheme *icon_theme;
GtkSettings *settings;
if (cell->priv->old_icon_size == cell->priv->icon_size)
return;
screen = gtk_widget_get_screen (GTK_WIDGET (widget));
icon_theme = gtk_icon_theme_get_for_screen (screen);
settings = gtk_settings_get_for_screen (screen);
if (!gtk_icon_size_lookup_for_settings (settings, priv->icon_size, &priv->size, NULL))
{
g_warning ("Invalid icon size %u\n", priv->icon_size);
priv->size = 24;
}
}
static void
gtk_cell_renderer_spinner_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (object);
GtkCellRendererSpinnerPrivate *priv = cell->priv;
switch (param_id)
{
case PROP_ACTIVE:
g_value_set_boolean (value, priv->active);
break;
case PROP_PULSE:
g_value_set_uint (value, priv->pulse);
break;
case PROP_SIZE:
g_value_set_enum (value, priv->icon_size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
static void
gtk_cell_renderer_spinner_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (object);
GtkCellRendererSpinnerPrivate *priv = cell->priv;
switch (param_id)
{
case PROP_ACTIVE:
priv->active = g_value_get_boolean (value);
break;
case PROP_PULSE:
priv->pulse = g_value_get_uint (value);
break;
case PROP_SIZE:
priv->old_icon_size = priv->icon_size;
priv->icon_size = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
static void
gtk_cell_renderer_spinner_get_size (GtkCellRenderer *cellr,
GtkWidget *widget,
GdkRectangle *cell_area,
gint *x_offset,
gint *y_offset,
gint *width,
gint *height)
{
GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (cellr);
GtkCellRendererSpinnerPrivate *priv = cell->priv;
gdouble align;
gint w, h;
gint xpad, ypad;
gfloat xalign, yalign;
gboolean rtl;
rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
gtk_cell_renderer_spinner_update_size (cell, widget);
g_object_get (cellr,
"xpad", &xpad,
"ypad", &ypad,
"xalign", &xalign,
"yalign", &yalign,
NULL);
w = h = priv->size;
if (cell_area)
{
if (x_offset)
{
align = rtl ? 1.0 - xalign : xalign;
*x_offset = align * (cell_area->width - w);
*x_offset = MAX (*x_offset, 0);
}
if (y_offset)
{
align = rtl ? 1.0 - yalign : yalign;
*y_offset = align * (cell_area->height - h);
*y_offset = MAX (*y_offset, 0);
}
}
else
{
if (x_offset)
*x_offset = 0;
if (y_offset)
*y_offset = 0;
}
if (width)
*width = w;
if (height)
*height = h;
}
static void
gtk_cell_renderer_spinner_render (GtkCellRenderer *cellr,
GdkWindow *window,
GtkWidget *widget,
GdkRectangle *background_area,
GdkRectangle *cell_area,
GdkRectangle *expose_area,
guint flags)
{
GtkCellRendererSpinner *cell = GTK_CELL_RENDERER_SPINNER (cellr);
GtkCellRendererSpinnerPrivate *priv = cell->priv;
GtkStateType state;
GdkRectangle pix_rect;
GdkRectangle draw_rect;
gint xpad, ypad;
if (!priv->active)
return;
gtk_cell_renderer_spinner_get_size (cellr, widget, cell_area,
&pix_rect.x, &pix_rect.y,
&pix_rect.width, &pix_rect.height);
g_object_get (cellr,
"xpad", &xpad,
"ypad", &ypad,
NULL);
pix_rect.x += cell_area->x + xpad;
pix_rect.y += cell_area->y + ypad;
pix_rect.width -= xpad * 2;
pix_rect.height -= ypad * 2;
if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect) ||
!gdk_rectangle_intersect (expose_area, &pix_rect, &draw_rect))
{
return;
}
state = GTK_STATE_NORMAL;
if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE || !cellr->sensitive)
{
state = GTK_STATE_INSENSITIVE;
}
else
{
if ((flags & GTK_CELL_RENDERER_SELECTED) != 0)
{
if (GTK_WIDGET_HAS_FOCUS (widget))
state = GTK_STATE_SELECTED;
else
state = GTK_STATE_ACTIVE;
}
else
state = GTK_STATE_PRELIGHT;
}
gtk_paint_spinner (widget->style,
window,
state,
priv->pulse,
draw_rect.x, draw_rect.y,
draw_rect.width, draw_rect.height);
}
#define __GTK_CELL_RENDERER_SPINNER_C__
#include "gtkaliasdef.c"

View File

@ -0,0 +1,60 @@
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2009 Matthias Clasen <mclasen@redhat.com>
* Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2009 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_CELL_RENDERER_SPINNER_H__
#define __GTK_CELL_RENDERER_SPINNER_H__
#include <gtk/gtk.h>
#define GTK_TYPE_CELL_RENDERER_SPINNER (gtk_cell_renderer_spinner_get_type ())
#define GTK_CELL_RENDERER_SPINNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CELL_RENDERER_SPINNER, GtkCellRendererSpinner))
#define GTK_CELL_RENDERER_SPINNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_SPINNER, GtkCellRendererSpinnerClass))
#define GTK_IS_CELL_RENDERER_SPINNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CELL_RENDERER_SPINNER))
#define GTK_IS_CELL_RENDERER_SPINNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CELL_RENDERER_SPINNER))
#define GTK_CELL_RENDERER_SPINNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CELL_RENDERER_SPINNER, GtkCellRendererSpinnerClass))
typedef struct _GtkCellRendererSpinner GtkCellRendererSpinner;
typedef struct _GtkCellRendererSpinnerClass GtkCellRendererSpinnerClass;
typedef struct _GtkCellRendererSpinnerPrivate GtkCellRendererSpinnerPrivate;
struct _GtkCellRendererSpinner
{
GtkCellRenderer parent;
GtkCellRendererSpinnerPrivate *priv;
};
struct _GtkCellRendererSpinnerClass
{
GtkCellRendererClass parent_class;
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
};
GType gtk_cell_renderer_spinner_get_type (void) G_GNUC_CONST;
GtkCellRenderer *gtk_cell_renderer_spinner_new (void);
#endif /* __GTK_CELL_RENDERER_SPINNER_H__ */

525
gtk/gtkspinner.c Normal file
View File

@ -0,0 +1,525 @@
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2007 John Stowers, Neil Jagdish Patel.
* Copyright (C) 2009 Bastien Nocera, David Zeuthen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Code adapted from egg-spinner
* by Christian Hergert <christian.hergert@gmail.com>
*/
/*
* Modified by the GTK+ Team and others 2007. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gtkintl.h"
#include "gtkaccessible.h"
#include "gtkimage.h"
#include "gtkspinner.h"
#include "gtkstyle.h"
#include "gtkalias.h"
#define GTK_SPINNER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SPINNER, GtkSpinnerPrivate))
G_DEFINE_TYPE (GtkSpinner, gtk_spinner, GTK_TYPE_DRAWING_AREA);
enum {
PROP_0,
PROP_ACTIVE
};
struct _GtkSpinnerPrivate
{
guint current;
guint num_steps;
guint timeout;
};
static void gtk_spinner_class_init (GtkSpinnerClass *klass);
static void gtk_spinner_init (GtkSpinner *spinner);
static void gtk_spinner_dispose (GObject *gobject);
static gboolean gtk_spinner_expose (GtkWidget *widget, GdkEventExpose *event);
static void gtk_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen);
static void gtk_spinner_style_set (GtkWidget *widget, GtkStyle *prev_style);
static void gtk_spinner_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec);
static void gtk_spinner_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec);
static AtkObject *gtk_spinner_get_accessible (GtkWidget *widget);
static GType gtk_spinner_accessible_get_type (void);
static void
gtk_spinner_class_init (GtkSpinnerClass *klass)
{
GObjectClass *gobject_class;
GtkWidgetClass *widget_class;
gtk_spinner_parent_class = g_type_class_peek_parent (klass);
gobject_class = G_OBJECT_CLASS(klass);
g_type_class_add_private (gobject_class, sizeof (GtkSpinnerPrivate));
gobject_class->dispose = gtk_spinner_dispose;
gobject_class->get_property = gtk_spinner_get_property;
gobject_class->set_property = gtk_spinner_set_property;
widget_class = GTK_WIDGET_CLASS(klass);
widget_class->expose_event = gtk_spinner_expose;
widget_class->screen_changed = gtk_spinner_screen_changed;
widget_class->style_set = gtk_spinner_style_set;
widget_class->get_accessible = gtk_spinner_get_accessible;
/* GtkSpinner::active:
*
* Whether the spinner is active
*
* Since 2.20
*/
g_object_class_install_property (gobject_class,
PROP_ACTIVE,
g_param_spec_boolean ("active",
P_("Active"),
P_("Whether the spinner is active"),
FALSE,
G_PARAM_READWRITE));
/**
* GtkSpinner::num-steps:
*
* The number of steps for the spinner to complete a full loop. The animation will
* complete a full revolution in one second.
*
* Since: 2.20
*/
gtk_widget_class_install_style_property (widget_class,
g_param_spec_uint ("num-steps",
P_("Number of steps"),
P_("The number of steps for the spinner to complete a full loop. The animation will complete a full revolution in one second."),
1,
G_MAXUINT,
12,
G_PARAM_READABLE));
}
static void
gtk_spinner_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
GtkSpinnerPrivate *priv;
priv = GTK_SPINNER_GET_PRIVATE (object);
switch (param_id)
{
case PROP_ACTIVE:
g_value_set_boolean (value, priv->timeout != 0);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
static void
gtk_spinner_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
switch (param_id)
{
case PROP_ACTIVE:
gtk_spinner_start (GTK_SPINNER (object));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
}
static void
gtk_spinner_init (GtkSpinner *spinner)
{
GtkSpinnerPrivate *priv;
priv = GTK_SPINNER_GET_PRIVATE (spinner);
priv->current = 0;
priv->timeout = 0;
GTK_WIDGET_SET_FLAGS (GTK_WIDGET (spinner), GTK_NO_WINDOW);
}
static gboolean
gtk_spinner_expose (GtkWidget *widget, GdkEventExpose *event)
{
GtkStateType state_type;
GtkSpinnerPrivate *priv;
int width, height;
priv = GTK_SPINNER_GET_PRIVATE (widget);
width = widget->allocation.width;
height = widget->allocation.height;
if ((width < 12) || (height <12))
gtk_widget_set_size_request (widget, 12, 12);
state_type = GTK_STATE_NORMAL;
if (!GTK_WIDGET_IS_SENSITIVE (widget))
state_type = GTK_STATE_INSENSITIVE;
gtk_paint_spinner (widget->style,
widget->window,
state_type,
priv->current,
event->area.x, event->area.y,
event->area.width, event->area.height);
return FALSE;
}
static void
gtk_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen)
{
GtkSpinner *spinner;
GdkScreen* new_screen;
GdkColormap* colormap;
spinner = GTK_SPINNER(widget);
new_screen = gtk_widget_get_screen (widget);
colormap = gdk_screen_get_rgba_colormap (new_screen);
if (!colormap)
{
colormap = gdk_screen_get_rgb_colormap (new_screen);
}
gtk_widget_set_colormap (widget, colormap);
}
static void
gtk_spinner_style_set (GtkWidget *widget,
GtkStyle *prev_style)
{
GtkSpinnerPrivate *priv;
priv = GTK_SPINNER_GET_PRIVATE (widget);
gtk_widget_style_get (GTK_WIDGET (widget),
"num-steps", &(priv->num_steps),
NULL);
if (priv->current > priv->num_steps)
priv->current = 0;
}
static gboolean
gtk_spinner_timeout (gpointer data)
{
GtkSpinnerPrivate *priv;
priv = GTK_SPINNER_GET_PRIVATE (data);
if (priv->current + 1 >= priv->num_steps)
{
priv->current = 0;
}
else
{
priv->current++;
}
gtk_widget_queue_draw (GTK_WIDGET (data));
return TRUE;
}
static void
gtk_spinner_dispose (GObject *gobject)
{
GtkSpinnerPrivate *priv;
priv = GTK_SPINNER_GET_PRIVATE (gobject);
if (priv->timeout != 0)
{
g_source_remove (priv->timeout);
priv->timeout = 0;
}
G_OBJECT_CLASS (gtk_spinner_parent_class)->dispose (gobject);
}
static GType
gtk_spinner_accessible_factory_get_accessible_type (void)
{
return gtk_spinner_accessible_get_type ();
}
static AtkObject *
gtk_spinner_accessible_new (GObject *obj)
{
AtkObject *accessible;
g_return_val_if_fail (GTK_IS_WIDGET (obj), NULL);
accessible = g_object_new (gtk_spinner_accessible_get_type (), NULL);
atk_object_initialize (accessible, obj);
return accessible;
}
static AtkObject*
gtk_spinner_accessible_factory_create_accessible (GObject *obj)
{
return gtk_spinner_accessible_new (obj);
}
static void
gtk_spinner_accessible_factory_class_init (AtkObjectFactoryClass *klass)
{
klass->create_accessible = gtk_spinner_accessible_factory_create_accessible;
klass->get_accessible_type = gtk_spinner_accessible_factory_get_accessible_type;
}
static GType
gtk_spinner_accessible_factory_get_type (void)
{
static GType type = 0;
if (!type)
{
const GTypeInfo tinfo =
{
sizeof (AtkObjectFactoryClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_spinner_accessible_factory_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (AtkObjectFactory),
0, /* n_preallocs */
NULL, NULL
};
type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY,
I_("GtkSpinnerAccessibleFactory"),
&tinfo, 0);
}
return type;
}
static AtkObjectClass *a11y_parent_class = NULL;
static void
gtk_spinner_accessible_initialize (AtkObject *accessible,
gpointer widget)
{
atk_object_set_name (accessible, _("spinner"));
atk_object_set_description (accessible, _("provides visual status"));
a11y_parent_class->initialize (accessible, widget);
}
static void
gtk_spinner_accessible_class_init (AtkObjectClass *klass)
{
a11y_parent_class = g_type_class_peek_parent (klass);
klass->initialize = gtk_spinner_accessible_initialize;
}
static void
gtk_spinner_accessible_image_get_size (AtkImage *image,
gint *width,
gint *height)
{
GtkWidget *widget;
widget = GTK_ACCESSIBLE (image)->widget;
if (!widget)
{
*width = *height = 0;
}
else
{
*width = widget->allocation.width;
*height = widget->allocation.height;
}
}
static void
gtk_spinner_accessible_image_interface_init (AtkImageIface *iface)
{
iface->get_image_size = gtk_spinner_accessible_image_get_size;
}
static GType
gtk_spinner_accessible_get_type (void)
{
static GType type = 0;
/* Action interface
Name etc. ... */
if (G_UNLIKELY (type == 0))
{
const GInterfaceInfo atk_image_info = {
(GInterfaceInitFunc) gtk_spinner_accessible_image_interface_init,
(GInterfaceFinalizeFunc) NULL,
NULL
};
GType type;
GType parent_atk_type;
GTypeInfo tinfo = { 0 };
GTypeQuery query;
AtkObjectFactory *factory;
if ((type = g_type_from_name ("GtkSpinnerAccessible")))
return type;
factory = atk_registry_get_factory (atk_get_default_registry (),
GTK_TYPE_IMAGE);
if (!factory)
return G_TYPE_INVALID;
parent_atk_type = atk_object_factory_get_accessible_type (factory);
if (!parent_atk_type)
return G_TYPE_INVALID;
/*
* Figure out the size of the class and instance
* we are deriving from
*/
g_type_query (parent_atk_type, &query);
tinfo.class_init = (GClassInitFunc) gtk_spinner_accessible_class_init;
tinfo.class_size = query.class_size;
tinfo.instance_size = query.instance_size;
/* Register the type */
type = g_type_register_static (parent_atk_type,
"GtkSpinnerAccessible",
&tinfo, 0);
g_type_add_interface_static (type, ATK_TYPE_IMAGE,
&atk_image_info);
}
return type;
}
static AtkObject *
gtk_spinner_get_accessible (GtkWidget *widget)
{
static gboolean first_time = TRUE;
if (first_time)
{
AtkObjectFactory *factory;
AtkRegistry *registry;
GType derived_type;
GType derived_atk_type;
/*
* Figure out whether accessibility is enabled by looking at the
* type of the accessible object which would be created for
* the parent type of GtkSpinner.
*/
derived_type = g_type_parent (GTK_TYPE_SPINNER);
registry = atk_get_default_registry ();
factory = atk_registry_get_factory (registry,
derived_type);
derived_atk_type = atk_object_factory_get_accessible_type (factory);
if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE))
atk_registry_set_factory_type (registry,
GTK_TYPE_SPINNER,
gtk_spinner_accessible_factory_get_type ());
first_time = FALSE;
}
return GTK_WIDGET_CLASS (gtk_spinner_parent_class)->get_accessible (widget);
}
/**
* gtk_spinner_new
*
* Returns a new spinner widget. Not yet started.
*
* Return value: a new #GtkSpinner
*
* Since: 2.20
*/
GtkWidget *
gtk_spinner_new (void)
{
return g_object_new (GTK_TYPE_SPINNER, NULL);
}
/**
* gtk_spinner_start
*
* Starts the animation on the #GtkSpinner
*
* Since: 2.20
*/
void
gtk_spinner_start (GtkSpinner *spinner)
{
GtkSpinnerPrivate *priv;
g_return_if_fail (GTK_IS_SPINNER (spinner));
priv = GTK_SPINNER_GET_PRIVATE (spinner);
if (priv->timeout != 0)
{
return;
}
priv->timeout = gdk_threads_add_timeout (1000 / priv->num_steps, gtk_spinner_timeout, spinner);
}
/**
* gtk_spinner_stop
*
* Stops the animation on the #GtkSpinner
*
* Since: 2.20
*/
void
gtk_spinner_stop (GtkSpinner *spinner)
{
GtkSpinnerPrivate *priv;
g_return_if_fail (GTK_IS_SPINNER (spinner));
priv = GTK_SPINNER_GET_PRIVATE (spinner);
if (priv->timeout == 0)
{
return;
}
g_source_remove (priv->timeout);
priv->timeout = 0;
}
#define __GTK_SPINNER_C__
#include "gtkaliasdef.c"

65
gtk/gtkspinner.h Normal file
View File

@ -0,0 +1,65 @@
/* GTK - The GIMP Toolkit
*
* Copyright (C) 2007 John Stowers, Neil Jagdish Patel.
* Copyright (C) 2009 Bastien Nocera, David Zeuthen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Code adapted from egg-spinner
* by Christian Hergert <christian.hergert@gmail.com>
*/
#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_SPINNER_H__
#define __GTK_SPINNER_H__
#include <gtk/gtkdrawingarea.h>
G_BEGIN_DECLS
#define GTK_TYPE_SPINNER (gtk_spinner_get_type ())
#define GTK_SPINNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SPINNER, GtkSpinner))
#define GTK_SPINNER_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_SPINNER, GtkSpinnerClass))
#define GTK_IS_SPINNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SPINNER))
#define GTK_IS_SPINNER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GTK_TYPE_SPINNER))
#define GTK_SPINNER_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SPINNER, GtkSpinnerClass))
typedef struct _GtkSpinner GtkSpinner;
typedef struct _GtkSpinnerClass GtkSpinnerClass;
typedef struct _GtkSpinnerPrivate GtkSpinnerPrivate;
struct _GtkSpinner
{
GtkDrawingArea parent;
};
struct _GtkSpinnerClass
{
GtkDrawingAreaClass parent_class;
GtkSpinnerPrivate *priv;
};
GType gtk_spinner_get_type (void) G_GNUC_CONST;
GtkWidget *gtk_spinner_new (void);
void gtk_spinner_start (GtkSpinner *spinner);
void gtk_spinner_stop (GtkSpinner *spinner);
G_END_DECLS
#endif /* __GTK_SPINNER_H__ */

View File

@ -313,6 +313,14 @@ static void gtk_default_draw_resize_grip (GtkStyle *style,
gint y,
gint width,
gint height);
static void gtk_default_draw_spinner (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
guint step,
gint x,
gint y,
gint width,
gint height);
static void rgb_to_hls (gdouble *r,
gdouble *g,
@ -511,6 +519,7 @@ gtk_style_class_init (GtkStyleClass *klass)
klass->draw_expander = gtk_default_draw_expander;
klass->draw_layout = gtk_default_draw_layout;
klass->draw_resize_grip = gtk_default_draw_resize_grip;
klass->draw_spinner = gtk_default_draw_spinner;
g_type_class_add_private (object_class, sizeof (GtkStylePrivate));
@ -1764,8 +1773,9 @@ gtk_style_get_style_property (GtkStyle *style,
GtkRcPropertyParser parser;
const GValue *peek_value;
klass = g_type_class_peek (widget_type);
klass = g_type_class_ref (widget_type);
pspec = gtk_widget_class_find_style_property (klass, property_name);
g_type_class_unref (klass);
if (!pspec)
{
@ -5598,6 +5608,80 @@ gtk_default_draw_resize_grip (GtkStyle *style,
}
}
static void
gtk_default_draw_spinner (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
guint step,
gint x,
gint y,
gint width,
gint height)
{
GdkColor *color;
cairo_t *cr;
guint num_steps;
gdouble dx, dy;
gdouble radius;
gdouble half;
gint i;
guint real_step;
gtk_style_get (style, GTK_TYPE_SPINNER,
"num-steps", &num_steps,
NULL);
real_step = step % num_steps;
/* get cairo context */
cr = gdk_cairo_create (window);
/* set a clip region for the expose event */
cairo_rectangle (cr, x, y, width, height);
cairo_clip (cr);
cairo_translate (cr, x, y);
/* draw clip region */
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
color = &style->fg[state_type];
dx = width / 2;
dy = height / 2;
radius = MIN (width / 2, height / 2);
half = num_steps / 2;
for (i = 0; i < num_steps; i++)
{
gint inset = 0.7 * radius;
/* transparency is a function of time and intial value */
gdouble t = (gdouble) ((i + num_steps - real_step)
% num_steps) / num_steps;
cairo_save (cr);
cairo_set_source_rgba (cr,
color->red / 65535.,
color->green / 65535.,
color->blue / 65535.,
t);
cairo_set_line_width (cr, 2.0);
cairo_move_to (cr,
dx + (radius - inset) * cos (i * G_PI / half),
dy + (radius - inset) * sin (i * G_PI / half));
cairo_line_to (cr,
dx + radius * cos (i * G_PI / half),
dy + radius * sin (i * G_PI / half));
cairo_stroke (cr);
cairo_restore (cr);
}
/* free memory */
cairo_destroy (cr);
}
void
_gtk_style_shade (const GdkColor *a,
GdkColor *b,
@ -6631,6 +6715,38 @@ gtk_paint_resize_grip (GtkStyle *style,
edge, x, y, width, height);
}
/**
* gtk_paint_spinner:
* @style: a #GtkStyle
* @window: a #GdkWindow
* @state_type: a state
* @widget: the widget
* @step: the nth step, a value between 0 and GtkSpinner::num-steps
* @x: the x origin of the rectangle in which to draw the resize grip
* @y: the y origin of the rectangle in which to draw the resize grip
* @width: the width of the rectangle in which to draw the resize grip
* @height: the height of the rectangle in which to draw the resize grip
*
* Draws a spinner on @window using the given parameters.
*/
void
gtk_paint_spinner (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
guint step,
gint x,
gint y,
gint width,
gint height)
{
g_return_if_fail (GTK_IS_STYLE (style));
g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_spinner != NULL);
g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
GTK_STYLE_GET_CLASS (style)->draw_spinner (style, window, state_type,
step, x, y, width, height);
}
/**
* gtk_border_new:
*

View File

@ -403,6 +403,14 @@ struct _GtkStyleClass
gint y,
gint width,
gint height);
void (*draw_spinner) (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
guint step,
gint x,
gint y,
gint width,
gint height);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
@ -416,7 +424,6 @@ struct _GtkStyleClass
void (*_gtk_reserved9) (void);
void (*_gtk_reserved10) (void);
void (*_gtk_reserved11) (void);
void (*_gtk_reserved12) (void);
};
struct _GtkBorder
@ -856,7 +863,14 @@ void gtk_paint_resize_grip (GtkStyle *style,
gint y,
gint width,
gint height);
void gtk_paint_spinner (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
guint step,
gint x,
gint y,
gint width,
gint height);
GType gtk_border_get_type (void) G_GNUC_CONST;
GtkBorder *gtk_border_new (void) G_GNUC_MALLOC;