~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gtk/gtkbutton.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GTK - The GIMP Toolkit
 
2
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
/*
 
21
 * Modified by the GTK+ Team and others 1997-2001.  See the AUTHORS
 
22
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 
23
 * files for a list of changes.  These files are distributed with
 
24
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 
25
 */
 
26
 
 
27
#include <config.h>
 
28
#include <string.h>
 
29
#include "gtkalignment.h"
 
30
#include "gtkbutton.h"
 
31
#include "gtklabel.h"
 
32
#include "gtkmain.h"
 
33
#include "gtkmarshalers.h"
 
34
#include "gtkimage.h"
 
35
#include "gtkhbox.h"
 
36
#include "gtkvbox.h"
 
37
#include "gtkstock.h"
 
38
#include "gtkiconfactory.h"
 
39
#include "gtkprivate.h"
 
40
#include "gtkintl.h"
 
41
#include "gtkalias.h"
 
42
 
 
43
static const GtkBorder default_default_border = { 1, 1, 1, 1 };
 
44
static const GtkBorder default_default_outside_border = { 0, 0, 0, 0 };
 
45
static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
 
46
 
 
47
/* Time out before giving up on getting a key release when animating
 
48
 * the close button.
 
49
 */
 
50
#define ACTIVATE_TIMEOUT 250
 
51
 
 
52
enum {
 
53
  PRESSED,
 
54
  RELEASED,
 
55
  CLICKED,
 
56
  ENTER,
 
57
  LEAVE,
 
58
  ACTIVATE,
 
59
  LAST_SIGNAL
 
60
};
 
61
 
 
62
enum {
 
63
  PROP_0,
 
64
  PROP_LABEL,
 
65
  PROP_IMAGE,
 
66
  PROP_RELIEF,
 
67
  PROP_USE_UNDERLINE,
 
68
  PROP_USE_STOCK,
 
69
  PROP_FOCUS_ON_CLICK,
 
70
  PROP_XALIGN,
 
71
  PROP_YALIGN,
 
72
  PROP_IMAGE_POSITION
 
73
};
 
74
 
 
75
#define GTK_BUTTON_GET_PRIVATE(o)       (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_BUTTON, GtkButtonPrivate))
 
76
typedef struct _GtkButtonPrivate GtkButtonPrivate;
 
77
 
 
78
struct _GtkButtonPrivate
 
79
{
 
80
  gfloat          xalign;
 
81
  gfloat          yalign;
 
82
  GtkWidget      *image;
 
83
  guint           align_set      : 1;
 
84
  guint           image_is_stock : 1;
 
85
  guint           has_grab       : 1;
 
86
  guint32         grab_time;
 
87
  GtkPositionType image_position;
 
88
};
 
89
 
 
90
static void gtk_button_destroy        (GtkObject          *object);
 
91
static void gtk_button_set_property   (GObject            *object,
 
92
                                       guint               prop_id,
 
93
                                       const GValue       *value,
 
94
                                       GParamSpec         *pspec);
 
95
static void gtk_button_get_property   (GObject            *object,
 
96
                                       guint               prop_id,
 
97
                                       GValue             *value,
 
98
                                       GParamSpec         *pspec);
 
99
static void gtk_button_screen_changed (GtkWidget          *widget,
 
100
                                       GdkScreen          *previous_screen);
 
101
static void gtk_button_realize        (GtkWidget          *widget);
 
102
static void gtk_button_unrealize      (GtkWidget          *widget);
 
103
static void gtk_button_map            (GtkWidget          *widget);
 
104
static void gtk_button_unmap          (GtkWidget          *widget);
 
105
static void gtk_button_style_set      (GtkWidget          *widget,
 
106
                                       GtkStyle           *prev_style);
 
107
static void gtk_button_size_request   (GtkWidget          *widget,
 
108
                                       GtkRequisition     *requisition);
 
109
static void gtk_button_size_allocate  (GtkWidget          *widget,
 
110
                                       GtkAllocation      *allocation);
 
111
static gint gtk_button_expose         (GtkWidget          *widget,
 
112
                                       GdkEventExpose     *event);
 
113
static gint gtk_button_button_press   (GtkWidget          *widget,
 
114
                                       GdkEventButton     *event);
 
115
static gint gtk_button_button_release (GtkWidget          *widget,
 
116
                                       GdkEventButton     *event);
 
117
static gint gtk_button_grab_broken    (GtkWidget          *widget,
 
118
                                       GdkEventGrabBroken *event);
 
119
static gint gtk_button_key_release    (GtkWidget          *widget,
 
120
                                       GdkEventKey        *event);
 
121
static gint gtk_button_enter_notify   (GtkWidget          *widget,
 
122
                                       GdkEventCrossing   *event);
 
123
static gint gtk_button_leave_notify   (GtkWidget          *widget,
 
124
                                       GdkEventCrossing   *event);
 
125
static void gtk_real_button_pressed   (GtkButton          *button);
 
126
static void gtk_real_button_released  (GtkButton          *button);
 
127
static void gtk_real_button_activate  (GtkButton          *button);
 
128
static void gtk_button_update_state   (GtkButton          *button);
 
129
static void gtk_button_add            (GtkContainer       *container,
 
130
                                       GtkWidget          *widget);
 
131
static GType gtk_button_child_type    (GtkContainer       *container);
 
132
static void gtk_button_finish_activate (GtkButton         *button,
 
133
                                        gboolean           do_it);
 
134
 
 
135
static GObject* gtk_button_constructor (GType                  type,
 
136
                                        guint                  n_construct_properties,
 
137
                                        GObjectConstructParam *construct_params);
 
138
static void gtk_button_construct_child (GtkButton             *button);
 
139
static void gtk_button_state_changed   (GtkWidget             *widget,
 
140
                                        GtkStateType           previous_state);
 
141
static void gtk_button_grab_notify     (GtkWidget             *widget,
 
142
                                        gboolean               was_grabbed);
 
143
 
 
144
 
 
145
static guint button_signals[LAST_SIGNAL] = { 0 };
 
146
 
 
147
G_DEFINE_TYPE (GtkButton, gtk_button, GTK_TYPE_BIN)
 
148
 
 
149
static void
 
150
gtk_button_class_init (GtkButtonClass *klass)
 
151
{
 
152
  GObjectClass *gobject_class;
 
153
  GtkObjectClass *object_class;
 
154
  GtkWidgetClass *widget_class;
 
155
  GtkContainerClass *container_class;
 
156
 
 
157
  gobject_class = G_OBJECT_CLASS (klass);
 
158
  object_class = (GtkObjectClass*) klass;
 
159
  widget_class = (GtkWidgetClass*) klass;
 
160
  container_class = (GtkContainerClass*) klass;
 
161
  
 
162
  gobject_class->constructor = gtk_button_constructor;
 
163
  gobject_class->set_property = gtk_button_set_property;
 
164
  gobject_class->get_property = gtk_button_get_property;
 
165
 
 
166
  object_class->destroy = gtk_button_destroy;
 
167
 
 
168
  widget_class->screen_changed = gtk_button_screen_changed;
 
169
  widget_class->realize = gtk_button_realize;
 
170
  widget_class->unrealize = gtk_button_unrealize;
 
171
  widget_class->map = gtk_button_map;
 
172
  widget_class->unmap = gtk_button_unmap;
 
173
  widget_class->style_set = gtk_button_style_set;
 
174
  widget_class->size_request = gtk_button_size_request;
 
175
  widget_class->size_allocate = gtk_button_size_allocate;
 
176
  widget_class->expose_event = gtk_button_expose;
 
177
  widget_class->button_press_event = gtk_button_button_press;
 
178
  widget_class->button_release_event = gtk_button_button_release;
 
179
  widget_class->grab_broken_event = gtk_button_grab_broken;
 
180
  widget_class->key_release_event = gtk_button_key_release;
 
181
  widget_class->enter_notify_event = gtk_button_enter_notify;
 
182
  widget_class->leave_notify_event = gtk_button_leave_notify;
 
183
  widget_class->state_changed = gtk_button_state_changed;
 
184
  widget_class->grab_notify = gtk_button_grab_notify;
 
185
 
 
186
  container_class->child_type = gtk_button_child_type;
 
187
  container_class->add = gtk_button_add;
 
188
 
 
189
  klass->pressed = gtk_real_button_pressed;
 
190
  klass->released = gtk_real_button_released;
 
191
  klass->clicked = NULL;
 
192
  klass->enter = gtk_button_update_state;
 
193
  klass->leave = gtk_button_update_state;
 
194
  klass->activate = gtk_real_button_activate;
 
195
 
 
196
  g_object_class_install_property (gobject_class,
 
197
                                   PROP_LABEL,
 
198
                                   g_param_spec_string ("label",
 
199
                                                        P_("Label"),
 
200
                                                        P_("Text of the label widget inside the button, if the button contains a label widget"),
 
201
                                                        NULL,
 
202
                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
203
  
 
204
  g_object_class_install_property (gobject_class,
 
205
                                   PROP_USE_UNDERLINE,
 
206
                                   g_param_spec_boolean ("use-underline",
 
207
                                                         P_("Use underline"),
 
208
                                                         P_("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
 
209
                                                        FALSE,
 
210
                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
211
  
 
212
  g_object_class_install_property (gobject_class,
 
213
                                   PROP_USE_STOCK,
 
214
                                   g_param_spec_boolean ("use-stock",
 
215
                                                         P_("Use stock"),
 
216
                                                         P_("If set, the label is used to pick a stock item instead of being displayed"),
 
217
                                                        FALSE,
 
218
                                                        GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
219
  
 
220
  g_object_class_install_property (gobject_class,
 
221
                                   PROP_FOCUS_ON_CLICK,
 
222
                                   g_param_spec_boolean ("focus-on-click",
 
223
                                                         P_("Focus on click"),
 
224
                                                         P_("Whether the button grabs focus when it is clicked with the mouse"),
 
225
                                                         TRUE,
 
226
                                                         GTK_PARAM_READWRITE));
 
227
  
 
228
  g_object_class_install_property (gobject_class,
 
229
                                   PROP_RELIEF,
 
230
                                   g_param_spec_enum ("relief",
 
231
                                                      P_("Border relief"),
 
232
                                                      P_("The border relief style"),
 
233
                                                      GTK_TYPE_RELIEF_STYLE,
 
234
                                                      GTK_RELIEF_NORMAL,
 
235
                                                      GTK_PARAM_READWRITE));
 
236
  
 
237
  /**
 
238
   * GtkButton:xalign:
 
239
   *
 
240
   * If the child of the button is a #GtkMisc or #GtkAlignment, this property 
 
241
   * can be used to control it's horizontal alignment. 0.0 is left aligned, 
 
242
   * 1.0 is right aligned.
 
243
   * 
 
244
   * Since: 2.4
 
245
   */
 
246
  g_object_class_install_property (gobject_class,
 
247
                                   PROP_XALIGN,
 
248
                                   g_param_spec_float("xalign",
 
249
                                                      P_("Horizontal alignment for child"),
 
250
                                                      P_("Horizontal position of child in available space. 0.0 is left aligned, 1.0 is right aligned"),
 
251
                                                      0.0,
 
252
                                                      1.0,
 
253
                                                      0.5,
 
254
                                                      GTK_PARAM_READWRITE));
 
255
 
 
256
  /**
 
257
   * GtkButton:yalign:
 
258
   *
 
259
   * If the child of the button is a #GtkMisc or #GtkAlignment, this property 
 
260
   * can be used to control it's vertical alignment. 0.0 is top aligned, 
 
261
   * 1.0 is bottom aligned.
 
262
   * 
 
263
   * Since: 2.4
 
264
   */
 
265
  g_object_class_install_property (gobject_class,
 
266
                                   PROP_YALIGN,
 
267
                                   g_param_spec_float("yalign",
 
268
                                                      P_("Vertical alignment for child"),
 
269
                                                      P_("Vertical position of child in available space. 0.0 is top aligned, 1.0 is bottom aligned"),
 
270
                                                      0.0,
 
271
                                                      1.0,
 
272
                                                      0.5,
 
273
                                                      GTK_PARAM_READWRITE));
 
274
 
 
275
  /**
 
276
   * GtkButton::image:
 
277
   * 
 
278
   * The child widget to appear next to the button text.
 
279
   * 
 
280
   * Since: 2.6
 
281
   */
 
282
  g_object_class_install_property (gobject_class,
 
283
                                   PROP_IMAGE,
 
284
                                   g_param_spec_object ("image",
 
285
                                                        P_("Image widget"),
 
286
                                                        P_("Child widget to appear next to the button text"),
 
287
                                                        GTK_TYPE_WIDGET,
 
288
                                                        GTK_PARAM_READWRITE));
 
289
 
 
290
  /**
 
291
   * GtkButton:image-position:
 
292
   *
 
293
   * The position of the image relative to the text inside the button.
 
294
   * 
 
295
   * Since: 2.10
 
296
   */
 
297
  g_object_class_install_property (gobject_class,
 
298
                                   PROP_IMAGE_POSITION,
 
299
                                   g_param_spec_enum ("image-position",
 
300
                                            P_("Image position"),
 
301
                                                      P_("The position of the image relative to the text"),
 
302
                                                      GTK_TYPE_POSITION_TYPE,
 
303
                                                      GTK_POS_LEFT,
 
304
                                                      GTK_PARAM_READWRITE));
 
305
 
 
306
  /**
 
307
   * GtkButton::pressed:
 
308
   * @button: the object that received the signal
 
309
   *
 
310
   * Emitted when the button is pressed.
 
311
   * 
 
312
   * @Deprecated: Use the GtkWidget::button-press-event signal.
 
313
   */ 
 
314
  button_signals[PRESSED] =
 
315
    g_signal_new (I_("pressed"),
 
316
                  G_OBJECT_CLASS_TYPE (object_class),
 
317
                  G_SIGNAL_RUN_FIRST,
 
318
                  G_STRUCT_OFFSET (GtkButtonClass, pressed),
 
319
                  NULL, NULL,
 
320
                  _gtk_marshal_VOID__VOID,
 
321
                  G_TYPE_NONE, 0);
 
322
 
 
323
  /**
 
324
   * GtkButton::released:
 
325
   * @button: the object that received the signal
 
326
   *
 
327
   * Emitted when the button is released.
 
328
   * 
 
329
   * @Deprecated: Use the GtkWidget::button-release-event signal.
 
330
   */ 
 
331
  button_signals[RELEASED] =
 
332
    g_signal_new (I_("released"),
 
333
                  G_OBJECT_CLASS_TYPE (object_class),
 
334
                  G_SIGNAL_RUN_FIRST,
 
335
                  G_STRUCT_OFFSET (GtkButtonClass, released),
 
336
                  NULL, NULL,
 
337
                  _gtk_marshal_VOID__VOID,
 
338
                  G_TYPE_NONE, 0);
 
339
 
 
340
  /**
 
341
   * GtkButton::clicked:
 
342
   * @button: the object that received the signal
 
343
   *
 
344
   * Emitted when the button has been activated (pressed and released).
 
345
   */ 
 
346
  button_signals[CLICKED] =
 
347
    g_signal_new (I_("clicked"),
 
348
                  G_OBJECT_CLASS_TYPE (object_class),
 
349
                  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
 
350
                  G_STRUCT_OFFSET (GtkButtonClass, clicked),
 
351
                  NULL, NULL,
 
352
                  _gtk_marshal_VOID__VOID,
 
353
                  G_TYPE_NONE, 0);
 
354
 
 
355
  /**
 
356
   * GtkButton::enter:
 
357
   * @button: the object that received the signal
 
358
   *
 
359
   * Emitted when the pointer enters the button.
 
360
   * 
 
361
   * @Deprecated: Use the GtkWidget::enter-notify-event signal.
 
362
   */ 
 
363
  button_signals[ENTER] =
 
364
    g_signal_new (I_("enter"),
 
365
                  G_OBJECT_CLASS_TYPE (object_class),
 
366
                  G_SIGNAL_RUN_FIRST,
 
367
                  G_STRUCT_OFFSET (GtkButtonClass, enter),
 
368
                  NULL, NULL,
 
369
                  _gtk_marshal_VOID__VOID,
 
370
                  G_TYPE_NONE, 0);
 
371
 
 
372
  /**
 
373
   * GtkButton::leave:
 
374
   * @button: the object that received the signal
 
375
   *
 
376
   * Emitted when the pointer leaves the button.
 
377
   * 
 
378
   * @Deprecated: Use the GtkWidget::leave-notify-event signal.
 
379
   */ 
 
380
  button_signals[LEAVE] =
 
381
    g_signal_new (I_("leave"),
 
382
                  G_OBJECT_CLASS_TYPE (object_class),
 
383
                  G_SIGNAL_RUN_FIRST,
 
384
                  G_STRUCT_OFFSET (GtkButtonClass, leave),
 
385
                  NULL, NULL,
 
386
                  _gtk_marshal_VOID__VOID,
 
387
                  G_TYPE_NONE, 0);
 
388
 
 
389
  /**
 
390
   * GtkButton::activate:
 
391
   * @widget: the object which received the signal.
 
392
   *
 
393
   * The "activate" signal on GtkButton is an action signal and
 
394
   * emitting it causes the button to animate press then release. 
 
395
   * Applications should never connect to this signal, but use the
 
396
   * "clicked" signal.
 
397
   */
 
398
  button_signals[ACTIVATE] =
 
399
    g_signal_new (I_("activate"),
 
400
                  G_OBJECT_CLASS_TYPE (object_class),
 
401
                  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
 
402
                  G_STRUCT_OFFSET (GtkButtonClass, activate),
 
403
                  NULL, NULL,
 
404
                  _gtk_marshal_VOID__VOID,
 
405
                  G_TYPE_NONE, 0);
 
406
  widget_class->activate_signal = button_signals[ACTIVATE];
 
407
 
 
408
  gtk_widget_class_install_style_property (widget_class,
 
409
                                           g_param_spec_boxed ("default-border",
 
410
                                                               P_("Default Spacing"),
 
411
                                                               P_("Extra space to add for CAN_DEFAULT buttons"),
 
412
                                                               GTK_TYPE_BORDER,
 
413
                                                               GTK_PARAM_READABLE));
 
414
 
 
415
  gtk_widget_class_install_style_property (widget_class,
 
416
                                           g_param_spec_boxed ("default-outside-border",
 
417
                                                               P_("Default Outside Spacing"),
 
418
                                                               P_("Extra space to add for CAN_DEFAULT buttons that is always drawn outside the border"),
 
419
                                                               GTK_TYPE_BORDER,
 
420
                                                               GTK_PARAM_READABLE));
 
421
  gtk_widget_class_install_style_property (widget_class,
 
422
                                           g_param_spec_int ("child-displacement-x",
 
423
                                                             P_("Child X Displacement"),
 
424
                                                             P_("How far in the x direction to move the child when the button is depressed"),
 
425
                                                             G_MININT,
 
426
                                                             G_MAXINT,
 
427
                                                             0,
 
428
                                                             GTK_PARAM_READABLE));
 
429
  gtk_widget_class_install_style_property (widget_class,
 
430
                                           g_param_spec_int ("child-displacement-y",
 
431
                                                             P_("Child Y Displacement"),
 
432
                                                             P_("How far in the y direction to move the child when the button is depressed"),
 
433
                                                             G_MININT,
 
434
                                                             G_MAXINT,
 
435
                                                             0,
 
436
                                                             GTK_PARAM_READABLE));
 
437
 
 
438
  /**
 
439
   * GtkButton:displace-focus:
 
440
   *
 
441
   * Whether the child_displacement_x/child_displacement_y properties should also 
 
442
   * affect the focus rectangle.
 
443
   *
 
444
   * Since: 2.6
 
445
   */
 
446
  gtk_widget_class_install_style_property (widget_class,
 
447
                                           g_param_spec_boolean ("displace-focus",
 
448
                                                                 P_("Displace focus"),
 
449
                                                                 P_("Whether the child_displacement_x/_y properties should also affect the focus rectangle"),
 
450
                                                       FALSE,
 
451
                                                       GTK_PARAM_READABLE));
 
452
 
 
453
  /**
 
454
   * GtkButton:inner-border:
 
455
   *
 
456
   * Sets the border between the button edges and child.
 
457
   *
 
458
   * Since: 2.10
 
459
   */
 
460
  gtk_widget_class_install_style_property (widget_class,
 
461
                                           g_param_spec_boxed ("inner-border",
 
462
                                                               P_("Inner Border"),
 
463
                                                               P_("Border between button edges and child."),
 
464
                                                               GTK_TYPE_BORDER,
 
465
                                                               GTK_PARAM_READABLE));
 
466
 
 
467
  /**
 
468
   * GtkButton::image-spacing:
 
469
   * 
 
470
   * Spacing in pixels between the image and label.
 
471
   * 
 
472
   * Since: 2.10
 
473
   */
 
474
  gtk_widget_class_install_style_property (widget_class,
 
475
                                           g_param_spec_int ("image-spacing",
 
476
                                                             P_("Image spacing"),
 
477
                                                             P_("Spacing in pixels between the image and label"),
 
478
                                                             0,
 
479
                                                             G_MAXINT,
 
480
                                                             2,
 
481
                                                             GTK_PARAM_READABLE));
 
482
  
 
483
 
 
484
  gtk_settings_install_property (g_param_spec_boolean ("gtk-button-images",
 
485
                                                       P_("Show button images"),
 
486
                                                       P_("Whether stock icons should be shown in buttons"),
 
487
                                                       TRUE,
 
488
                                                       GTK_PARAM_READWRITE));
 
489
 
 
490
  g_type_class_add_private (gobject_class, sizeof (GtkButtonPrivate));
 
491
}
 
492
 
 
493
static void
 
494
gtk_button_init (GtkButton *button)
 
495
{
 
496
  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
 
497
 
 
498
  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
 
499
  GTK_WIDGET_SET_FLAGS (button, GTK_NO_WINDOW);
 
500
 
 
501
  button->label_text = NULL;
 
502
  
 
503
  button->constructed = FALSE;
 
504
  button->in_button = FALSE;
 
505
  button->button_down = FALSE;
 
506
  button->relief = GTK_RELIEF_NORMAL;
 
507
  button->use_stock = FALSE;
 
508
  button->use_underline = FALSE;
 
509
  button->depressed = FALSE;
 
510
  button->depress_on_activate = TRUE;
 
511
  button->focus_on_click = TRUE;
 
512
 
 
513
  priv->xalign = 0.5;
 
514
  priv->yalign = 0.5;
 
515
  priv->align_set = 0;
 
516
  priv->image_is_stock = TRUE;
 
517
  priv->image_position = GTK_POS_LEFT;
 
518
}
 
519
 
 
520
static void
 
521
gtk_button_destroy (GtkObject *object)
 
522
{
 
523
  GtkButton *button = GTK_BUTTON (object);
 
524
  
 
525
  if (button->label_text)
 
526
    {
 
527
      g_free (button->label_text);
 
528
      button->label_text = NULL;
 
529
    }
 
530
  
 
531
  (* GTK_OBJECT_CLASS (gtk_button_parent_class)->destroy) (object);
 
532
}
 
533
 
 
534
static GObject*
 
535
gtk_button_constructor (GType                  type,
 
536
                        guint                  n_construct_properties,
 
537
                        GObjectConstructParam *construct_params)
 
538
{
 
539
  GObject *object;
 
540
  GtkButton *button;
 
541
 
 
542
  object = (* G_OBJECT_CLASS (gtk_button_parent_class)->constructor) (type,
 
543
                                                                      n_construct_properties,
 
544
                                                                      construct_params);
 
545
 
 
546
  button = GTK_BUTTON (object);
 
547
  button->constructed = TRUE;
 
548
 
 
549
  if (button->label_text != NULL)
 
550
    gtk_button_construct_child (button);
 
551
  
 
552
  return object;
 
553
}
 
554
 
 
555
 
 
556
static GType
 
557
gtk_button_child_type  (GtkContainer     *container)
 
558
{
 
559
  if (!GTK_BIN (container)->child)
 
560
    return GTK_TYPE_WIDGET;
 
561
  else
 
562
    return G_TYPE_NONE;
 
563
}
 
564
 
 
565
static void
 
566
maybe_set_alignment (GtkButton *button,
 
567
                     GtkWidget *widget)
 
568
{
 
569
  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
 
570
 
 
571
  if (GTK_IS_MISC (widget))
 
572
    {
 
573
      GtkMisc *misc = GTK_MISC (widget);
 
574
      
 
575
      if (priv->align_set)
 
576
        gtk_misc_set_alignment (misc, priv->xalign, priv->yalign);
 
577
    }
 
578
  else if (GTK_IS_ALIGNMENT (widget))
 
579
    {
 
580
      GtkAlignment *alignment = GTK_ALIGNMENT (widget);
 
581
 
 
582
      if (priv->align_set)
 
583
        gtk_alignment_set (alignment, priv->xalign, priv->yalign, 
 
584
                           alignment->xscale, alignment->yscale);
 
585
    }
 
586
}
 
587
 
 
588
static void
 
589
gtk_button_add (GtkContainer *container,
 
590
                GtkWidget    *widget)
 
591
{
 
592
  maybe_set_alignment (GTK_BUTTON (container), widget);
 
593
 
 
594
  GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, widget);
 
595
}
 
596
 
 
597
static void
 
598
gtk_button_set_property (GObject         *object,
 
599
                         guint            prop_id,
 
600
                         const GValue    *value,
 
601
                         GParamSpec      *pspec)
 
602
{
 
603
  GtkButton *button = GTK_BUTTON (object);
 
604
  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
 
605
 
 
606
  switch (prop_id)
 
607
    {
 
608
    case PROP_LABEL:
 
609
      gtk_button_set_label (button, g_value_get_string (value));
 
610
      break;
 
611
    case PROP_IMAGE:
 
612
      gtk_button_set_image (button, (GtkWidget *) g_value_get_object (value));
 
613
      break;
 
614
    case PROP_RELIEF:
 
615
      gtk_button_set_relief (button, g_value_get_enum (value));
 
616
      break;
 
617
    case PROP_USE_UNDERLINE:
 
618
      gtk_button_set_use_underline (button, g_value_get_boolean (value));
 
619
      break;
 
620
    case PROP_USE_STOCK:
 
621
      gtk_button_set_use_stock (button, g_value_get_boolean (value));
 
622
      break;
 
623
    case PROP_FOCUS_ON_CLICK:
 
624
      gtk_button_set_focus_on_click (button, g_value_get_boolean (value));
 
625
      break;
 
626
    case PROP_XALIGN:
 
627
      gtk_button_set_alignment (button, g_value_get_float (value), priv->yalign);
 
628
      break;
 
629
    case PROP_YALIGN:
 
630
      gtk_button_set_alignment (button, priv->xalign, g_value_get_float (value));
 
631
      break;
 
632
    case PROP_IMAGE_POSITION:
 
633
      gtk_button_set_image_position (button, g_value_get_enum (value));
 
634
      break;
 
635
    default:
 
636
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
637
      break;
 
638
    }
 
639
}
 
640
 
 
641
static void
 
642
gtk_button_get_property (GObject         *object,
 
643
                         guint            prop_id,
 
644
                         GValue          *value,
 
645
                         GParamSpec      *pspec)
 
646
{
 
647
  GtkButton *button = GTK_BUTTON (object);
 
648
  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
 
649
 
 
650
  switch (prop_id)
 
651
    {
 
652
    case PROP_LABEL:
 
653
      g_value_set_string (value, button->label_text);
 
654
      break;
 
655
    case PROP_IMAGE:
 
656
      g_value_set_object (value, (GObject *)priv->image);
 
657
      break;
 
658
    case PROP_RELIEF:
 
659
      g_value_set_enum (value, gtk_button_get_relief (button));
 
660
      break;
 
661
    case PROP_USE_UNDERLINE:
 
662
      g_value_set_boolean (value, button->use_underline);
 
663
      break;
 
664
    case PROP_USE_STOCK:
 
665
      g_value_set_boolean (value, button->use_stock);
 
666
      break;
 
667
    case PROP_FOCUS_ON_CLICK:
 
668
      g_value_set_boolean (value, button->focus_on_click);
 
669
      break;
 
670
    case PROP_XALIGN:
 
671
      g_value_set_float (value, priv->xalign);
 
672
      break;
 
673
    case PROP_YALIGN:
 
674
      g_value_set_float (value, priv->yalign);
 
675
      break;
 
676
    case PROP_IMAGE_POSITION:
 
677
      g_value_set_enum (value, priv->image_position);
 
678
      break;
 
679
    default:
 
680
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
681
      break;
 
682
    }
 
683
}
 
684
 
 
685
GtkWidget*
 
686
gtk_button_new (void)
 
687
{
 
688
  return g_object_new (GTK_TYPE_BUTTON, NULL);
 
689
}
 
690
 
 
691
static gboolean
 
692
show_image (GtkButton *button)
 
693
{
 
694
  gboolean show;
 
695
  
 
696
  if (button->label_text)
 
697
    {
 
698
      GtkSettings *settings;
 
699
 
 
700
      settings = gtk_widget_get_settings (GTK_WIDGET (button));        
 
701
      g_object_get (settings, "gtk-button-images", &show, NULL);
 
702
    }
 
703
  else
 
704
    show = TRUE;
 
705
 
 
706
  return show;
 
707
}
 
708
 
 
709
static void
 
710
gtk_button_construct_child (GtkButton *button)
 
711
{
 
712
  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
 
713
  GtkStockItem item;
 
714
  GtkWidget *label;
 
715
  GtkWidget *box;
 
716
  GtkWidget *align;
 
717
  GtkWidget *image = NULL;
 
718
  gchar *label_text = NULL;
 
719
  gint image_spacing;
 
720
  
 
721
  if (!button->constructed)
 
722
    return;
 
723
 
 
724
  if (!button->label_text && !priv->image)
 
725
    return;
 
726
  
 
727
  gtk_widget_style_get (GTK_WIDGET (button), 
 
728
                        "image-spacing", &image_spacing, 
 
729
                        NULL);
 
730
 
 
731
  if (priv->image && !priv->image_is_stock)
 
732
    {
 
733
      image = g_object_ref (priv->image);
 
734
      if (image->parent)
 
735
        gtk_container_remove (GTK_CONTAINER (image->parent), image);
 
736
      
 
737
      priv->image = NULL;
 
738
    }
 
739
  
 
740
  if (GTK_BIN (button)->child)
 
741
    gtk_container_remove (GTK_CONTAINER (button),
 
742
                          GTK_BIN (button)->child);
 
743
  
 
744
  if (button->use_stock &&
 
745
      button->label_text &&
 
746
      gtk_stock_lookup (button->label_text, &item))
 
747
    {
 
748
      if (!image)
 
749
        image = g_object_ref (gtk_image_new_from_stock (button->label_text, GTK_ICON_SIZE_BUTTON));
 
750
 
 
751
      label_text = item.label;
 
752
    }
 
753
  else
 
754
    label_text = button->label_text;
 
755
 
 
756
  if (image)
 
757
    {
 
758
      priv->image = image;
 
759
      g_object_set (priv->image, 
 
760
                    "visible", show_image (button),
 
761
                    "no-show-all", TRUE,
 
762
                    NULL);
 
763
 
 
764
      if (priv->image_position == GTK_POS_LEFT ||
 
765
          priv->image_position == GTK_POS_RIGHT)
 
766
        box = gtk_hbox_new (FALSE, image_spacing);
 
767
      else
 
768
        box = gtk_vbox_new (FALSE, image_spacing);
 
769
 
 
770
      if (priv->align_set)
 
771
        align = gtk_alignment_new (priv->xalign, priv->yalign, 0.0, 0.0);
 
772
      else
 
773
        align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
 
774
 
 
775
      if (priv->image_position == GTK_POS_LEFT ||
 
776
          priv->image_position == GTK_POS_TOP)
 
777
        gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
 
778
      else
 
779
        gtk_box_pack_end (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
 
780
 
 
781
      if (label_text)
 
782
        {
 
783
          label = gtk_label_new_with_mnemonic (label_text);
 
784
          gtk_label_set_mnemonic_widget (GTK_LABEL (label), 
 
785
                                         GTK_WIDGET (button));
 
786
 
 
787
          if (priv->image_position == GTK_POS_RIGHT ||
 
788
              priv->image_position == GTK_POS_BOTTOM)
 
789
            gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
 
790
          else
 
791
            gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
 
792
        }
 
793
      
 
794
      gtk_container_add (GTK_CONTAINER (button), align);
 
795
      gtk_container_add (GTK_CONTAINER (align), box);
 
796
      gtk_widget_show_all (align);
 
797
 
 
798
      g_object_unref (image);
 
799
 
 
800
      return;
 
801
    }
 
802
  
 
803
  if (button->use_underline)
 
804
    {
 
805
      label = gtk_label_new_with_mnemonic (button->label_text);
 
806
      gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
 
807
    }
 
808
  else
 
809
    label = gtk_label_new (button->label_text);
 
810
  
 
811
  if (priv->align_set)
 
812
    gtk_misc_set_alignment (GTK_MISC (label), priv->xalign, priv->yalign);
 
813
  
 
814
  gtk_widget_show (label);
 
815
  gtk_container_add (GTK_CONTAINER (button), label);
 
816
}
 
817
 
 
818
 
 
819
GtkWidget*
 
820
gtk_button_new_with_label (const gchar *label)
 
821
{
 
822
  return g_object_new (GTK_TYPE_BUTTON, "label", label, NULL);
 
823
}
 
824
 
 
825
/**
 
826
 * gtk_button_new_from_stock:
 
827
 * @stock_id: the name of the stock item 
 
828
 *
 
829
 * Creates a new #GtkButton containing the image and text from a stock item.
 
830
 * Some stock ids have preprocessor macros like #GTK_STOCK_OK and
 
831
 * #GTK_STOCK_APPLY.
 
832
 *
 
833
 * If @stock_id is unknown, then it will be treated as a mnemonic
 
834
 * label (as for gtk_button_new_with_mnemonic()).
 
835
 *
 
836
 * Returns: a new #GtkButton
 
837
 **/
 
838
GtkWidget*
 
839
gtk_button_new_from_stock (const gchar *stock_id)
 
840
{
 
841
  return g_object_new (GTK_TYPE_BUTTON,
 
842
                       "label", stock_id,
 
843
                       "use-stock", TRUE,
 
844
                       "use-underline", TRUE,
 
845
                       NULL);
 
846
}
 
847
 
 
848
/**
 
849
 * gtk_button_new_with_mnemonic:
 
850
 * @label: The text of the button, with an underscore in front of the
 
851
 *         mnemonic character
 
852
 * @returns: a new #GtkButton
 
853
 *
 
854
 * Creates a new #GtkButton containing a label.
 
855
 * If characters in @label are preceded by an underscore, they are underlined.
 
856
 * If you need a literal underscore character in a label, use '__' (two 
 
857
 * underscores). The first underlined character represents a keyboard 
 
858
 * accelerator called a mnemonic.
 
859
 * Pressing Alt and that key activates the button.
 
860
 **/
 
861
GtkWidget*
 
862
gtk_button_new_with_mnemonic (const gchar *label)
 
863
{
 
864
  return g_object_new (GTK_TYPE_BUTTON, "label", label, "use-underline", TRUE,  NULL);
 
865
}
 
866
 
 
867
void
 
868
gtk_button_pressed (GtkButton *button)
 
869
{
 
870
  g_return_if_fail (GTK_IS_BUTTON (button));
 
871
 
 
872
  
 
873
  g_signal_emit (button, button_signals[PRESSED], 0);
 
874
}
 
875
 
 
876
void
 
877
gtk_button_released (GtkButton *button)
 
878
{
 
879
  g_return_if_fail (GTK_IS_BUTTON (button));
 
880
 
 
881
  g_signal_emit (button, button_signals[RELEASED], 0);
 
882
}
 
883
 
 
884
void
 
885
gtk_button_clicked (GtkButton *button)
 
886
{
 
887
  g_return_if_fail (GTK_IS_BUTTON (button));
 
888
 
 
889
  g_signal_emit (button, button_signals[CLICKED], 0);
 
890
}
 
891
 
 
892
void
 
893
gtk_button_enter (GtkButton *button)
 
894
{
 
895
  g_return_if_fail (GTK_IS_BUTTON (button));
 
896
 
 
897
  g_signal_emit (button, button_signals[ENTER], 0);
 
898
}
 
899
 
 
900
void
 
901
gtk_button_leave (GtkButton *button)
 
902
{
 
903
  g_return_if_fail (GTK_IS_BUTTON (button));
 
904
 
 
905
  g_signal_emit (button, button_signals[LEAVE], 0);
 
906
}
 
907
 
 
908
void
 
909
gtk_button_set_relief (GtkButton *button,
 
910
                       GtkReliefStyle newrelief)
 
911
{
 
912
  g_return_if_fail (GTK_IS_BUTTON (button));
 
913
 
 
914
  if (newrelief != button->relief) 
 
915
    {
 
916
       button->relief = newrelief;
 
917
       g_object_notify (G_OBJECT (button), "relief");
 
918
       gtk_widget_queue_draw (GTK_WIDGET (button));
 
919
    }
 
920
}
 
921
 
 
922
GtkReliefStyle
 
923
gtk_button_get_relief (GtkButton *button)
 
924
{
 
925
  g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
 
926
 
 
927
  return button->relief;
 
928
}
 
929
 
 
930
static void
 
931
gtk_button_realize (GtkWidget *widget)
 
932
{
 
933
  GtkButton *button;
 
934
  GdkWindowAttr attributes;
 
935
  gint attributes_mask;
 
936
  gint border_width;
 
937
 
 
938
  button = GTK_BUTTON (widget);
 
939
  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
940
 
 
941
  border_width = GTK_CONTAINER (widget)->border_width;
 
942
 
 
943
  attributes.window_type = GDK_WINDOW_CHILD;
 
944
  attributes.x = widget->allocation.x + border_width;
 
945
  attributes.y = widget->allocation.y + border_width;
 
946
  attributes.width = widget->allocation.width - border_width * 2;
 
947
  attributes.height = widget->allocation.height - border_width * 2;
 
948
  attributes.wclass = GDK_INPUT_ONLY;
 
949
  attributes.event_mask = gtk_widget_get_events (widget);
 
950
  attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
 
951
                            GDK_BUTTON_RELEASE_MASK |
 
952
                            GDK_ENTER_NOTIFY_MASK |
 
953
                            GDK_LEAVE_NOTIFY_MASK);
 
954
 
 
955
  attributes_mask = GDK_WA_X | GDK_WA_Y;
 
956
 
 
957
  widget->window = gtk_widget_get_parent_window (widget);
 
958
  g_object_ref (widget->window);
 
959
  
 
960
  button->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
 
961
                                         &attributes, attributes_mask);
 
962
  gdk_window_set_user_data (button->event_window, button);
 
963
 
 
964
  widget->style = gtk_style_attach (widget->style, widget->window);
 
965
}
 
966
 
 
967
static void
 
968
gtk_button_unrealize (GtkWidget *widget)
 
969
{
 
970
  GtkButton *button = GTK_BUTTON (widget);
 
971
 
 
972
  if (button->activate_timeout)
 
973
    gtk_button_finish_activate (button, FALSE);
 
974
 
 
975
  if (button->event_window)
 
976
    {
 
977
      gdk_window_set_user_data (button->event_window, NULL);
 
978
      gdk_window_destroy (button->event_window);
 
979
      button->event_window = NULL;
 
980
    }
 
981
  
 
982
  GTK_WIDGET_CLASS (gtk_button_parent_class)->unrealize (widget);
 
983
}
 
984
 
 
985
static void
 
986
gtk_button_map (GtkWidget *widget)
 
987
{
 
988
  GtkButton *button = GTK_BUTTON (widget);
 
989
  
 
990
  GTK_WIDGET_CLASS (gtk_button_parent_class)->map (widget);
 
991
 
 
992
  if (button->event_window)
 
993
    gdk_window_show (button->event_window);
 
994
}
 
995
 
 
996
static void
 
997
gtk_button_unmap (GtkWidget *widget)
 
998
{
 
999
  GtkButton *button = GTK_BUTTON (widget);
 
1000
    
 
1001
  if (button->event_window)
 
1002
    gdk_window_hide (button->event_window);
 
1003
 
 
1004
  GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
 
1005
}
 
1006
 
 
1007
static void
 
1008
gtk_button_update_image_spacing (GtkButton *button)
 
1009
{
 
1010
  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
 
1011
  GtkWidget *child; 
 
1012
  gint spacing;
 
1013
 
 
1014
  /* Keep in sync with gtk_button_construct_child,
 
1015
   * we only want to update the spacing if the box 
 
1016
   * was constructed there.
 
1017
   */
 
1018
  if (!button->constructed || !priv->image)
 
1019
    return;
 
1020
 
 
1021
  child = GTK_BIN (button)->child;
 
1022
  if (GTK_IS_ALIGNMENT (child))
 
1023
    {
 
1024
      child = GTK_BIN (child)->child;
 
1025
      if (GTK_IS_BOX (child))
 
1026
        {
 
1027
          gtk_widget_style_get (GTK_WIDGET (button),
 
1028
                                "image-spacing", &spacing,
 
1029
                                NULL);
 
1030
 
 
1031
          gtk_box_set_spacing (GTK_BOX (child), spacing);
 
1032
        }
 
1033
    }   
 
1034
}
 
1035
 
 
1036
static void
 
1037
gtk_button_style_set (GtkWidget *widget,
 
1038
                      GtkStyle  *prev_style)
 
1039
{
 
1040
  gtk_button_update_image_spacing (GTK_BUTTON (widget));
 
1041
}
 
1042
 
 
1043
static void
 
1044
gtk_button_get_props (GtkButton *button,
 
1045
                      GtkBorder *default_border,
 
1046
                      GtkBorder *default_outside_border,
 
1047
                      GtkBorder *inner_border,
 
1048
                      gboolean  *interior_focus)
 
1049
{
 
1050
  GtkWidget *widget =  GTK_WIDGET (button);
 
1051
  GtkBorder *tmp_border;
 
1052
 
 
1053
  if (default_border)
 
1054
    {
 
1055
      gtk_widget_style_get (widget, "default-border", &tmp_border, NULL);
 
1056
 
 
1057
      if (tmp_border)
 
1058
        {
 
1059
          *default_border = *tmp_border;
 
1060
          g_free (tmp_border);
 
1061
        }
 
1062
      else
 
1063
        *default_border = default_default_border;
 
1064
    }
 
1065
 
 
1066
  if (default_outside_border)
 
1067
    {
 
1068
      gtk_widget_style_get (widget, "default-outside-border", &tmp_border, NULL);
 
1069
 
 
1070
      if (tmp_border)
 
1071
        {
 
1072
          *default_outside_border = *tmp_border;
 
1073
          g_free (tmp_border);
 
1074
        }
 
1075
      else
 
1076
        *default_outside_border = default_default_outside_border;
 
1077
    }
 
1078
 
 
1079
  if (inner_border)
 
1080
    {
 
1081
      gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
 
1082
 
 
1083
      if (tmp_border)
 
1084
        {
 
1085
          *inner_border = *tmp_border;
 
1086
          g_free (tmp_border);
 
1087
        }
 
1088
      else
 
1089
        *inner_border = default_inner_border;
 
1090
    }
 
1091
 
 
1092
  if (interior_focus)
 
1093
    gtk_widget_style_get (widget, "interior-focus", interior_focus, NULL);
 
1094
}
 
1095
        
 
1096
static void
 
1097
gtk_button_size_request (GtkWidget      *widget,
 
1098
                         GtkRequisition *requisition)
 
1099
{
 
1100
  GtkButton *button = GTK_BUTTON (widget);
 
1101
  GtkBorder default_border;
 
1102
  GtkBorder inner_border;
 
1103
  gint focus_width;
 
1104
  gint focus_pad;
 
1105
 
 
1106
  gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
 
1107
  gtk_widget_style_get (GTK_WIDGET (widget),
 
1108
                        "focus-line-width", &focus_width,
 
1109
                        "focus-padding", &focus_pad,
 
1110
                        NULL);
 
1111
 
 
1112
  requisition->width = ((GTK_CONTAINER (widget)->border_width +
 
1113
                         GTK_WIDGET (widget)->style->xthickness) * 2 +
 
1114
                        inner_border.left + inner_border.right);
 
1115
  requisition->height = ((GTK_CONTAINER (widget)->border_width +
 
1116
                          GTK_WIDGET (widget)->style->ythickness) * 2 +
 
1117
                         inner_border.top + inner_border.bottom);
 
1118
 
 
1119
  if (GTK_WIDGET_CAN_DEFAULT (widget))
 
1120
    {
 
1121
      requisition->width += default_border.left + default_border.right;
 
1122
      requisition->height += default_border.top + default_border.bottom;
 
1123
    }
 
1124
 
 
1125
  if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
 
1126
    {
 
1127
      GtkRequisition child_requisition;
 
1128
 
 
1129
      gtk_widget_size_request (GTK_BIN (button)->child, &child_requisition);
 
1130
 
 
1131
      requisition->width += child_requisition.width;
 
1132
      requisition->height += child_requisition.height;
 
1133
    }
 
1134
  
 
1135
  requisition->width += 2 * (focus_width + focus_pad);
 
1136
  requisition->height += 2 * (focus_width + focus_pad);
 
1137
}
 
1138
 
 
1139
static void
 
1140
gtk_button_size_allocate (GtkWidget     *widget,
 
1141
                          GtkAllocation *allocation)
 
1142
{
 
1143
  GtkButton *button = GTK_BUTTON (widget);
 
1144
  GtkAllocation child_allocation;
 
1145
 
 
1146
  gint border_width = GTK_CONTAINER (widget)->border_width;
 
1147
  gint xthickness = GTK_WIDGET (widget)->style->xthickness;
 
1148
  gint ythickness = GTK_WIDGET (widget)->style->ythickness;
 
1149
  GtkBorder default_border;
 
1150
  GtkBorder inner_border;
 
1151
  gint focus_width;
 
1152
  gint focus_pad;
 
1153
 
 
1154
  gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
 
1155
  gtk_widget_style_get (GTK_WIDGET (widget),
 
1156
                        "focus-line-width", &focus_width,
 
1157
                        "focus-padding", &focus_pad,
 
1158
                        NULL);
 
1159
 
 
1160
                            
 
1161
  widget->allocation = *allocation;
 
1162
 
 
1163
  if (GTK_WIDGET_REALIZED (widget))
 
1164
    gdk_window_move_resize (button->event_window,
 
1165
                            widget->allocation.x + border_width,
 
1166
                            widget->allocation.y + border_width,
 
1167
                            widget->allocation.width - border_width * 2,
 
1168
                            widget->allocation.height - border_width * 2);
 
1169
 
 
1170
  if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
 
1171
    {
 
1172
      child_allocation.x = widget->allocation.x + border_width + inner_border.left + xthickness;
 
1173
      child_allocation.y = widget->allocation.y + border_width + inner_border.top + ythickness;
 
1174
      
 
1175
      child_allocation.width = MAX (1, widget->allocation.width -
 
1176
                                    xthickness * 2 -
 
1177
                                    inner_border.left -
 
1178
                                    inner_border.right -
 
1179
                                    border_width * 2);
 
1180
      child_allocation.height = MAX (1, widget->allocation.height -
 
1181
                                     ythickness * 2 -
 
1182
                                     inner_border.top -
 
1183
                                     inner_border.bottom -
 
1184
                                     border_width * 2);
 
1185
 
 
1186
      if (GTK_WIDGET_CAN_DEFAULT (button))
 
1187
        {
 
1188
          child_allocation.x += default_border.left;
 
1189
          child_allocation.y += default_border.top;
 
1190
          child_allocation.width =  MAX (1, child_allocation.width - default_border.left - default_border.right);
 
1191
          child_allocation.height = MAX (1, child_allocation.height - default_border.top - default_border.bottom);
 
1192
        }
 
1193
 
 
1194
      if (GTK_WIDGET_CAN_FOCUS (button))
 
1195
        {
 
1196
          child_allocation.x += focus_width + focus_pad;
 
1197
          child_allocation.y += focus_width + focus_pad;
 
1198
          child_allocation.width =  MAX (1, child_allocation.width - (focus_width + focus_pad) * 2);
 
1199
          child_allocation.height = MAX (1, child_allocation.height - (focus_width + focus_pad) * 2);
 
1200
        }
 
1201
 
 
1202
      if (button->depressed)
 
1203
        {
 
1204
          gint child_displacement_x;
 
1205
          gint child_displacement_y;
 
1206
          
 
1207
          gtk_widget_style_get (widget,
 
1208
                                "child-displacement-x", &child_displacement_x, 
 
1209
                                "child-displacement-y", &child_displacement_y,
 
1210
                                NULL);
 
1211
          child_allocation.x += child_displacement_x;
 
1212
          child_allocation.y += child_displacement_y;
 
1213
        }
 
1214
 
 
1215
      gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
 
1216
    }
 
1217
}
 
1218
 
 
1219
void
 
1220
_gtk_button_paint (GtkButton    *button,
 
1221
                   GdkRectangle *area,
 
1222
                   GtkStateType  state_type,
 
1223
                   GtkShadowType shadow_type,
 
1224
                   const gchar  *main_detail,
 
1225
                   const gchar  *default_detail)
 
1226
{
 
1227
  GtkWidget *widget;
 
1228
  gint width, height;
 
1229
  gint x, y;
 
1230
  gint border_width;
 
1231
  GtkBorder default_border;
 
1232
  GtkBorder default_outside_border;
 
1233
  gboolean interior_focus;
 
1234
  gint focus_width;
 
1235
  gint focus_pad;
 
1236
   
 
1237
  if (GTK_WIDGET_DRAWABLE (button))
 
1238
    {
 
1239
      widget = GTK_WIDGET (button);
 
1240
      border_width = GTK_CONTAINER (widget)->border_width;
 
1241
 
 
1242
      gtk_button_get_props (button, &default_border, &default_outside_border, NULL, &interior_focus);
 
1243
      gtk_widget_style_get (GTK_WIDGET (widget),
 
1244
                            "focus-line-width", &focus_width,
 
1245
                            "focus-padding", &focus_pad,
 
1246
                            NULL); 
 
1247
        
 
1248
      x = widget->allocation.x + border_width;
 
1249
      y = widget->allocation.y + border_width;
 
1250
      width = widget->allocation.width - border_width * 2;
 
1251
      height = widget->allocation.height - border_width * 2;
 
1252
 
 
1253
      if (GTK_WIDGET_HAS_DEFAULT (widget) &&
 
1254
          GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
 
1255
        {
 
1256
          gtk_paint_box (widget->style, widget->window,
 
1257
                         GTK_STATE_NORMAL, GTK_SHADOW_IN,
 
1258
                         area, widget, "buttondefault",
 
1259
                         x, y, width, height);
 
1260
 
 
1261
          x += default_border.left;
 
1262
          y += default_border.top;
 
1263
          width -= default_border.left + default_border.right;
 
1264
          height -= default_border.top + default_border.bottom;
 
1265
        }
 
1266
      else if (GTK_WIDGET_CAN_DEFAULT (widget))
 
1267
        {
 
1268
          x += default_outside_border.left;
 
1269
          y += default_outside_border.top;
 
1270
          width -= default_outside_border.left + default_outside_border.right;
 
1271
          height -= default_outside_border.top + default_outside_border.bottom;
 
1272
        }
 
1273
       
 
1274
      if (!interior_focus && GTK_WIDGET_HAS_FOCUS (widget))
 
1275
        {
 
1276
          x += focus_width + focus_pad;
 
1277
          y += focus_width + focus_pad;
 
1278
          width -= 2 * (focus_width + focus_pad);
 
1279
          height -= 2 * (focus_width + focus_pad);
 
1280
        }
 
1281
 
 
1282
      if (button->relief != GTK_RELIEF_NONE || button->depressed ||
 
1283
          GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT)
 
1284
        gtk_paint_box (widget->style, widget->window,
 
1285
                       state_type,
 
1286
                       shadow_type, area, widget, "button",
 
1287
                       x, y, width, height);
 
1288
       
 
1289
      if (GTK_WIDGET_HAS_FOCUS (widget))
 
1290
        {
 
1291
          gint child_displacement_x;
 
1292
          gint child_displacement_y;
 
1293
          gboolean displace_focus;
 
1294
          
 
1295
          gtk_widget_style_get (GTK_WIDGET (widget),
 
1296
                                "child-displacement-y", &child_displacement_y,
 
1297
                                "child-displacement-x", &child_displacement_x,
 
1298
                                "displace-focus", &displace_focus,
 
1299
                                NULL);
 
1300
 
 
1301
          if (interior_focus)
 
1302
            {
 
1303
              x += widget->style->xthickness + focus_pad;
 
1304
              y += widget->style->ythickness + focus_pad;
 
1305
              width -= 2 * (widget->style->xthickness + focus_pad);
 
1306
              height -=  2 * (widget->style->ythickness + focus_pad);
 
1307
            }
 
1308
          else
 
1309
            {
 
1310
              x -= focus_width + focus_pad;
 
1311
              y -= focus_width + focus_pad;
 
1312
              width += 2 * (focus_width + focus_pad);
 
1313
              height += 2 * (focus_width + focus_pad);
 
1314
            }
 
1315
 
 
1316
          if (button->depressed && displace_focus)
 
1317
            {
 
1318
              x += child_displacement_x;
 
1319
              y += child_displacement_y;
 
1320
            }
 
1321
 
 
1322
          gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
 
1323
                           area, widget, "button",
 
1324
                           x, y, width, height);
 
1325
        }
 
1326
    }
 
1327
}
 
1328
 
 
1329
static gboolean
 
1330
gtk_button_expose (GtkWidget      *widget,
 
1331
                   GdkEventExpose *event)
 
1332
{
 
1333
  if (GTK_WIDGET_DRAWABLE (widget))
 
1334
    {
 
1335
      GtkButton *button = GTK_BUTTON (widget);
 
1336
      
 
1337
      _gtk_button_paint (button, &event->area,
 
1338
                         GTK_WIDGET_STATE (widget),
 
1339
                         button->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
 
1340
                         "button", "buttondefault");
 
1341
      
 
1342
      (* GTK_WIDGET_CLASS (gtk_button_parent_class)->expose_event) (widget, event);
 
1343
    }
 
1344
  
 
1345
  return FALSE;
 
1346
}
 
1347
 
 
1348
static gboolean
 
1349
gtk_button_button_press (GtkWidget      *widget,
 
1350
                         GdkEventButton *event)
 
1351
{
 
1352
  GtkButton *button;
 
1353
 
 
1354
  if (event->type == GDK_BUTTON_PRESS)
 
1355
    {
 
1356
      button = GTK_BUTTON (widget);
 
1357
 
 
1358
      if (button->focus_on_click && !GTK_WIDGET_HAS_FOCUS (widget))
 
1359
        gtk_widget_grab_focus (widget);
 
1360
 
 
1361
      if (event->button == 1)
 
1362
        gtk_button_pressed (button);
 
1363
    }
 
1364
 
 
1365
  return TRUE;
 
1366
}
 
1367
 
 
1368
static gboolean
 
1369
gtk_button_button_release (GtkWidget      *widget,
 
1370
                           GdkEventButton *event)
 
1371
{
 
1372
  GtkButton *button;
 
1373
 
 
1374
  if (event->button == 1)
 
1375
    {
 
1376
      button = GTK_BUTTON (widget);
 
1377
      gtk_button_released (button);
 
1378
    }
 
1379
 
 
1380
  return TRUE;
 
1381
}
 
1382
 
 
1383
static gboolean
 
1384
gtk_button_grab_broken (GtkWidget          *widget,
 
1385
                        GdkEventGrabBroken *event)
 
1386
{
 
1387
  GtkButton *button = GTK_BUTTON (widget);
 
1388
  gboolean save_in;
 
1389
  
 
1390
  /* Simulate a button release without the pointer in the button */
 
1391
  if (button->button_down)
 
1392
    {
 
1393
      save_in = button->in_button;
 
1394
      button->in_button = FALSE;
 
1395
      gtk_button_released (button);
 
1396
      if (save_in != button->in_button)
 
1397
        {
 
1398
          button->in_button = save_in;
 
1399
          gtk_button_update_state (button);
 
1400
        }
 
1401
    }
 
1402
 
 
1403
  return TRUE;
 
1404
}
 
1405
 
 
1406
static gboolean
 
1407
gtk_button_key_release (GtkWidget   *widget,
 
1408
                        GdkEventKey *event)
 
1409
{
 
1410
  GtkButton *button = GTK_BUTTON (widget);
 
1411
 
 
1412
  if (button->activate_timeout)
 
1413
    {
 
1414
      gtk_button_finish_activate (button, TRUE);
 
1415
      return TRUE;
 
1416
    }
 
1417
  else if (GTK_WIDGET_CLASS (gtk_button_parent_class)->key_release_event)
 
1418
    return GTK_WIDGET_CLASS (gtk_button_parent_class)->key_release_event (widget, event);
 
1419
  else
 
1420
    return FALSE;
 
1421
}
 
1422
 
 
1423
static gboolean
 
1424
gtk_button_enter_notify (GtkWidget        *widget,
 
1425
                         GdkEventCrossing *event)
 
1426
{
 
1427
  GtkButton *button;
 
1428
  GtkWidget *event_widget;
 
1429
 
 
1430
  button = GTK_BUTTON (widget);
 
1431
  event_widget = gtk_get_event_widget ((GdkEvent*) event);
 
1432
 
 
1433
  if ((event_widget == widget) &&
 
1434
      (event->detail != GDK_NOTIFY_INFERIOR))
 
1435
    {
 
1436
      button->in_button = TRUE;
 
1437
      gtk_button_enter (button);
 
1438
    }
 
1439
 
 
1440
  return FALSE;
 
1441
}
 
1442
 
 
1443
static gboolean
 
1444
gtk_button_leave_notify (GtkWidget        *widget,
 
1445
                         GdkEventCrossing *event)
 
1446
{
 
1447
  GtkButton *button;
 
1448
  GtkWidget *event_widget;
 
1449
 
 
1450
  button = GTK_BUTTON (widget);
 
1451
  event_widget = gtk_get_event_widget ((GdkEvent*) event);
 
1452
 
 
1453
  if ((event_widget == widget) &&
 
1454
      (event->detail != GDK_NOTIFY_INFERIOR))
 
1455
    {
 
1456
      button->in_button = FALSE;
 
1457
      gtk_button_leave (button);
 
1458
    }
 
1459
 
 
1460
  return FALSE;
 
1461
}
 
1462
 
 
1463
static void
 
1464
gtk_real_button_pressed (GtkButton *button)
 
1465
{
 
1466
  if (button->activate_timeout)
 
1467
    return;
 
1468
  
 
1469
  button->button_down = TRUE;
 
1470
  gtk_button_update_state (button);
 
1471
}
 
1472
 
 
1473
static void
 
1474
gtk_real_button_released (GtkButton *button)
 
1475
{
 
1476
  if (button->button_down)
 
1477
    {
 
1478
      button->button_down = FALSE;
 
1479
 
 
1480
      if (button->activate_timeout)
 
1481
        return;
 
1482
      
 
1483
      if (button->in_button)
 
1484
        gtk_button_clicked (button);
 
1485
 
 
1486
      gtk_button_update_state (button);
 
1487
    }
 
1488
}
 
1489
 
 
1490
static gboolean
 
1491
button_activate_timeout (gpointer data)
 
1492
{
 
1493
  GDK_THREADS_ENTER ();
 
1494
  
 
1495
  gtk_button_finish_activate (data, TRUE);
 
1496
 
 
1497
  GDK_THREADS_LEAVE ();
 
1498
 
 
1499
  return FALSE;
 
1500
}
 
1501
 
 
1502
static void
 
1503
gtk_real_button_activate (GtkButton *button)
 
1504
{
 
1505
  GtkWidget *widget = GTK_WIDGET (button);
 
1506
  GtkButtonPrivate *priv;
 
1507
  guint32 time;
 
1508
 
 
1509
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
1510
 
 
1511
  if (GTK_WIDGET_REALIZED (button) && !button->activate_timeout)
 
1512
    {
 
1513
      time = gtk_get_current_event_time ();
 
1514
      if (gdk_keyboard_grab (button->event_window, TRUE, time) == 
 
1515
          GDK_GRAB_SUCCESS)
 
1516
        {
 
1517
          priv->has_grab = TRUE;
 
1518
          priv->grab_time = time;
 
1519
        }
 
1520
 
 
1521
      gtk_grab_add (widget);
 
1522
      
 
1523
      button->activate_timeout = g_timeout_add (ACTIVATE_TIMEOUT,
 
1524
                                                button_activate_timeout,
 
1525
                                                button);
 
1526
      button->button_down = TRUE;
 
1527
      gtk_button_update_state (button);
 
1528
      gtk_widget_queue_draw (GTK_WIDGET (button));
 
1529
    }
 
1530
}
 
1531
 
 
1532
static void
 
1533
gtk_button_finish_activate (GtkButton *button,
 
1534
                            gboolean   do_it)
 
1535
{
 
1536
  GtkWidget *widget = GTK_WIDGET (button);
 
1537
  GtkButtonPrivate *priv;
 
1538
  
 
1539
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
1540
 
 
1541
  g_source_remove (button->activate_timeout);
 
1542
  button->activate_timeout = 0;
 
1543
 
 
1544
  if (priv->has_grab)
 
1545
    {
 
1546
      gdk_display_keyboard_ungrab (gtk_widget_get_display (widget),
 
1547
                                   priv->grab_time);
 
1548
    }
 
1549
  gtk_grab_remove (widget);
 
1550
 
 
1551
  button->button_down = FALSE;
 
1552
 
 
1553
  gtk_button_update_state (button);
 
1554
  gtk_widget_queue_draw (GTK_WIDGET (button));
 
1555
 
 
1556
  if (do_it)
 
1557
    gtk_button_clicked (button);
 
1558
}
 
1559
 
 
1560
/**
 
1561
 * gtk_button_set_label:
 
1562
 * @button: a #GtkButton
 
1563
 * @label: a string
 
1564
 *
 
1565
 * Sets the text of the label of the button to @str. This text is
 
1566
 * also used to select the stock item if gtk_button_set_use_stock()
 
1567
 * is used.
 
1568
 *
 
1569
 * This will also clear any previously set labels.
 
1570
 **/
 
1571
void
 
1572
gtk_button_set_label (GtkButton   *button,
 
1573
                      const gchar *label)
 
1574
{
 
1575
  gchar *new_label;
 
1576
  
 
1577
  g_return_if_fail (GTK_IS_BUTTON (button));
 
1578
 
 
1579
  new_label = g_strdup (label);
 
1580
  g_free (button->label_text);
 
1581
  button->label_text = new_label;
 
1582
  
 
1583
  gtk_button_construct_child (button);
 
1584
  
 
1585
  g_object_notify (G_OBJECT (button), "label");
 
1586
}
 
1587
 
 
1588
/**
 
1589
 * gtk_button_get_label:
 
1590
 * @button: a #GtkButton
 
1591
 *
 
1592
 * Fetches the text from the label of the button, as set by
 
1593
 * gtk_button_set_label(). If the label text has not 
 
1594
 * been set the return value will be %NULL. This will be the 
 
1595
 * case if you create an empty button with gtk_button_new() to 
 
1596
 * use as a container.
 
1597
 *
 
1598
 * Return value: The text of the label widget. This string is owned
 
1599
 * by the widget and must not be modified or freed.
 
1600
 **/
 
1601
G_CONST_RETURN gchar *
 
1602
gtk_button_get_label (GtkButton *button)
 
1603
{
 
1604
  g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
 
1605
  
 
1606
  return button->label_text;
 
1607
}
 
1608
 
 
1609
/**
 
1610
 * gtk_button_set_use_underline:
 
1611
 * @button: a #GtkButton
 
1612
 * @use_underline: %TRUE if underlines in the text indicate mnemonics
 
1613
 *
 
1614
 * If true, an underline in the text of the button label indicates
 
1615
 * the next character should be used for the mnemonic accelerator key.
 
1616
 */
 
1617
void
 
1618
gtk_button_set_use_underline (GtkButton *button,
 
1619
                              gboolean   use_underline)
 
1620
{
 
1621
  g_return_if_fail (GTK_IS_BUTTON (button));
 
1622
 
 
1623
  use_underline = use_underline != FALSE;
 
1624
 
 
1625
  if (use_underline != button->use_underline)
 
1626
    {
 
1627
      button->use_underline = use_underline;
 
1628
  
 
1629
      gtk_button_construct_child (button);
 
1630
      
 
1631
      g_object_notify (G_OBJECT (button), "use-underline");
 
1632
    }
 
1633
}
 
1634
 
 
1635
/**
 
1636
 * gtk_button_get_use_underline:
 
1637
 * @button: a #GtkButton
 
1638
 *
 
1639
 * Returns whether an embedded underline in the button label indicates a
 
1640
 * mnemonic. See gtk_button_set_use_underline ().
 
1641
 *
 
1642
 * Return value: %TRUE if an embedded underline in the button label
 
1643
 *               indicates the mnemonic accelerator keys.
 
1644
 **/
 
1645
gboolean
 
1646
gtk_button_get_use_underline (GtkButton *button)
 
1647
{
 
1648
  g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
 
1649
  
 
1650
  return button->use_underline;
 
1651
}
 
1652
 
 
1653
/**
 
1654
 * gtk_button_set_use_stock:
 
1655
 * @button: a #GtkButton
 
1656
 * @use_stock: %TRUE if the button should use a stock item
 
1657
 *
 
1658
 * If true, the label set on the button is used as a
 
1659
 * stock id to select the stock item for the button.
 
1660
 */
 
1661
void
 
1662
gtk_button_set_use_stock (GtkButton *button,
 
1663
                          gboolean   use_stock)
 
1664
{
 
1665
  g_return_if_fail (GTK_IS_BUTTON (button));
 
1666
 
 
1667
  use_stock = use_stock != FALSE;
 
1668
 
 
1669
  if (use_stock != button->use_stock)
 
1670
    {
 
1671
      button->use_stock = use_stock;
 
1672
  
 
1673
      gtk_button_construct_child (button);
 
1674
      
 
1675
      g_object_notify (G_OBJECT (button), "use-stock");
 
1676
    }
 
1677
}
 
1678
 
 
1679
/**
 
1680
 * gtk_button_get_use_stock:
 
1681
 * @button: a #GtkButton
 
1682
 *
 
1683
 * Returns whether the button label is a stock item.
 
1684
 *
 
1685
 * Return value: %TRUE if the button label is used to
 
1686
 *               select a stock item instead of being
 
1687
 *               used directly as the label text.
 
1688
 */
 
1689
gboolean
 
1690
gtk_button_get_use_stock (GtkButton *button)
 
1691
{
 
1692
  g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
 
1693
  
 
1694
  return button->use_stock;
 
1695
}
 
1696
 
 
1697
/**
 
1698
 * gtk_button_set_focus_on_click:
 
1699
 * @button: a #GtkButton
 
1700
 * @focus_on_click: whether the button grabs focus when clicked with the mouse
 
1701
 * 
 
1702
 * Sets whether the button will grab focus when it is clicked with the mouse.
 
1703
 * Making mouse clicks not grab focus is useful in places like toolbars where
 
1704
 * you don't want the keyboard focus removed from the main area of the
 
1705
 * application.
 
1706
 *
 
1707
 * Since: 2.4
 
1708
 **/
 
1709
void
 
1710
gtk_button_set_focus_on_click (GtkButton *button,
 
1711
                               gboolean   focus_on_click)
 
1712
{
 
1713
  g_return_if_fail (GTK_IS_BUTTON (button));
 
1714
  
 
1715
  focus_on_click = focus_on_click != FALSE;
 
1716
 
 
1717
  if (button->focus_on_click != focus_on_click)
 
1718
    {
 
1719
      button->focus_on_click = focus_on_click;
 
1720
      
 
1721
      g_object_notify (G_OBJECT (button), "focus-on-click");
 
1722
    }
 
1723
}
 
1724
 
 
1725
/**
 
1726
 * gtk_button_get_focus_on_click:
 
1727
 * @button: a #GtkButton
 
1728
 * 
 
1729
 * Returns whether the button grabs focus when it is clicked with the mouse.
 
1730
 * See gtk_button_set_focus_on_click().
 
1731
 *
 
1732
 * Return value: %TRUE if the button grabs focus when it is clicked with
 
1733
 *               the mouse.
 
1734
 *
 
1735
 * Since: 2.4
 
1736
 **/
 
1737
gboolean
 
1738
gtk_button_get_focus_on_click (GtkButton *button)
 
1739
{
 
1740
  g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
 
1741
  
 
1742
  return button->focus_on_click;
 
1743
}
 
1744
 
 
1745
/**
 
1746
 * gtk_button_set_alignment:
 
1747
 * @button: a #GtkButton
 
1748
 * @xalign: the horizontal position of the child, 0.0 is left aligned, 
 
1749
 *   1.0 is right aligned
 
1750
 * @yalign: the vertical position of the child, 0.0 is top aligned, 
 
1751
 *   1.0 is bottom aligned
 
1752
 *
 
1753
 * Sets the alignment of the child. This property has no effect unless 
 
1754
 * the child is a #GtkMisc or a #GtkAligment.
 
1755
 *
 
1756
 * Since: 2.4
 
1757
 */
 
1758
void
 
1759
gtk_button_set_alignment (GtkButton *button,
 
1760
                          gfloat     xalign,
 
1761
                          gfloat     yalign)
 
1762
{
 
1763
  GtkButtonPrivate *priv;
 
1764
 
 
1765
  g_return_if_fail (GTK_IS_BUTTON (button));
 
1766
  
 
1767
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
1768
 
 
1769
  priv->xalign = xalign;
 
1770
  priv->yalign = yalign;
 
1771
  priv->align_set = 1;
 
1772
 
 
1773
  maybe_set_alignment (button, GTK_BIN (button)->child);
 
1774
 
 
1775
  g_object_freeze_notify (G_OBJECT (button));
 
1776
  g_object_notify (G_OBJECT (button), "xalign");
 
1777
  g_object_notify (G_OBJECT (button), "yalign");
 
1778
  g_object_thaw_notify (G_OBJECT (button));
 
1779
}
 
1780
 
 
1781
/**
 
1782
 * gtk_button_get_alignment:
 
1783
 * @button: a #GtkButton
 
1784
 * @xalign: return location for horizontal alignment
 
1785
 * @yalign: return location for vertical alignment
 
1786
 *
 
1787
 * Gets the alignment of the child in the button.
 
1788
 *
 
1789
 * Since: 2.4
 
1790
 */
 
1791
void
 
1792
gtk_button_get_alignment (GtkButton *button,
 
1793
                          gfloat    *xalign,
 
1794
                          gfloat    *yalign)
 
1795
{
 
1796
  GtkButtonPrivate *priv;
 
1797
 
 
1798
  g_return_if_fail (GTK_IS_BUTTON (button));
 
1799
  
 
1800
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
1801
 
 
1802
  if (xalign) 
 
1803
    *xalign = priv->xalign;
 
1804
 
 
1805
  if (yalign)
 
1806
    *yalign = priv->yalign;
 
1807
}
 
1808
 
 
1809
/**
 
1810
 * _gtk_button_set_depressed:
 
1811
 * @button: a #GtkButton
 
1812
 * @depressed: %TRUE if the button should be drawn with a recessed shadow.
 
1813
 * 
 
1814
 * Sets whether the button is currently drawn as down or not. This is 
 
1815
 * purely a visual setting, and is meant only for use by derived widgets
 
1816
 * such as #GtkToggleButton.
 
1817
 **/
 
1818
void
 
1819
_gtk_button_set_depressed (GtkButton *button,
 
1820
                           gboolean   depressed)
 
1821
{
 
1822
  GtkWidget *widget = GTK_WIDGET (button);
 
1823
 
 
1824
  depressed = depressed != FALSE;
 
1825
 
 
1826
  if (depressed != button->depressed)
 
1827
    {
 
1828
      button->depressed = depressed;
 
1829
      gtk_widget_queue_resize (widget);
 
1830
    }
 
1831
}
 
1832
 
 
1833
static void
 
1834
gtk_button_update_state (GtkButton *button)
 
1835
{
 
1836
  gboolean depressed;
 
1837
  GtkStateType new_state;
 
1838
 
 
1839
  if (button->activate_timeout)
 
1840
    depressed = button->depress_on_activate;
 
1841
  else
 
1842
    depressed = button->in_button && button->button_down;
 
1843
 
 
1844
  if (button->in_button && (!button->button_down || !depressed))
 
1845
    new_state = GTK_STATE_PRELIGHT;
 
1846
  else
 
1847
    new_state = depressed ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL;
 
1848
 
 
1849
  _gtk_button_set_depressed (button, depressed); 
 
1850
  gtk_widget_set_state (GTK_WIDGET (button), new_state);
 
1851
}
 
1852
 
 
1853
static void 
 
1854
show_image_change_notify (GtkButton *button)
 
1855
{
 
1856
  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
 
1857
 
 
1858
  if (priv->image) 
 
1859
    {
 
1860
      if (show_image (button))
 
1861
        gtk_widget_show (priv->image);
 
1862
      else
 
1863
        gtk_widget_hide (priv->image);
 
1864
    }
 
1865
}
 
1866
 
 
1867
static void
 
1868
traverse_container (GtkWidget *widget,
 
1869
                    gpointer   data)
 
1870
{
 
1871
  if (GTK_IS_BUTTON (widget))
 
1872
    show_image_change_notify (GTK_BUTTON (widget));
 
1873
  else if (GTK_IS_CONTAINER (widget))
 
1874
    gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL);
 
1875
}
 
1876
 
 
1877
static void
 
1878
gtk_button_setting_changed (GtkSettings *settings)
 
1879
{
 
1880
  GList *list, *l;
 
1881
 
 
1882
  list = gtk_window_list_toplevels ();
 
1883
 
 
1884
  for (l = list; l; l = l->next)
 
1885
    gtk_container_forall (GTK_CONTAINER (l->data), 
 
1886
                          traverse_container, NULL);
 
1887
 
 
1888
  g_list_free (list);
 
1889
}
 
1890
 
 
1891
 
 
1892
static void
 
1893
gtk_button_screen_changed (GtkWidget *widget,
 
1894
                           GdkScreen *previous_screen)
 
1895
{
 
1896
  GtkSettings *settings;
 
1897
  guint show_image_connection;
 
1898
 
 
1899
  if (!gtk_widget_has_screen (widget))
 
1900
    return;
 
1901
 
 
1902
  settings = gtk_widget_get_settings (widget);
 
1903
 
 
1904
  show_image_connection = 
 
1905
    GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (settings), 
 
1906
                                         "gtk-button-connection"));
 
1907
  
 
1908
  if (show_image_connection)
 
1909
    return;
 
1910
 
 
1911
  show_image_connection =
 
1912
    g_signal_connect (settings, "notify::gtk-button-images",
 
1913
                      G_CALLBACK (gtk_button_setting_changed), 0);
 
1914
  g_object_set_data (G_OBJECT (settings), 
 
1915
                     I_("gtk-button-connection"),
 
1916
                     GUINT_TO_POINTER (show_image_connection));
 
1917
 
 
1918
  show_image_change_notify (GTK_BUTTON (widget));
 
1919
}
 
1920
 
 
1921
static void
 
1922
gtk_button_state_changed (GtkWidget    *widget,
 
1923
                          GtkStateType  previous_state)
 
1924
{
 
1925
  GtkButton *button = GTK_BUTTON (widget);
 
1926
 
 
1927
  if (!GTK_WIDGET_IS_SENSITIVE (widget))
 
1928
    {
 
1929
      button->in_button = FALSE;
 
1930
      gtk_real_button_released (button);
 
1931
    }
 
1932
}
 
1933
 
 
1934
static void
 
1935
gtk_button_grab_notify (GtkWidget *widget,
 
1936
                        gboolean   was_grabbed)
 
1937
{
 
1938
  GtkButton *button = GTK_BUTTON (widget);
 
1939
  gboolean save_in;
 
1940
 
 
1941
  if (!was_grabbed)
 
1942
    {
 
1943
      save_in = button->in_button;
 
1944
      button->in_button = FALSE; 
 
1945
      gtk_real_button_released (button);
 
1946
      if (save_in != button->in_button)
 
1947
        {
 
1948
          button->in_button = save_in;
 
1949
          gtk_button_update_state (button);
 
1950
        }
 
1951
    }
 
1952
}
 
1953
 
 
1954
/**
 
1955
 * gtk_button_set_image:
 
1956
 * @button: a #GtkButton
 
1957
 * @image: a widget to set as the image for the button
 
1958
 *
 
1959
 * Set the image of @button to the given widget. Note that
 
1960
 * it depends on the gtk-button-images setting whether the
 
1961
 * image will be displayed or not, you don't have to call
 
1962
 * gtk_widget_show() on @image yourself.
 
1963
 *
 
1964
 * Since: 2.6
 
1965
 */ 
 
1966
void
 
1967
gtk_button_set_image (GtkButton *button,
 
1968
                      GtkWidget *image)
 
1969
{
 
1970
  GtkButtonPrivate *priv;
 
1971
 
 
1972
  g_return_if_fail (GTK_IS_BUTTON (button));
 
1973
  g_return_if_fail (image == NULL || GTK_IS_WIDGET (image));
 
1974
 
 
1975
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
1976
 
 
1977
  priv->image = image;
 
1978
  priv->image_is_stock = (image == NULL);
 
1979
 
 
1980
  gtk_button_construct_child (button);
 
1981
 
 
1982
  g_object_notify (G_OBJECT (button), "image");
 
1983
}
 
1984
 
 
1985
/**
 
1986
 * gtk_button_get_image:
 
1987
 * @button: a #GtkButton
 
1988
 *
 
1989
 * Gets the widget that is currenty set as the image of @button.
 
1990
 * This may have been explicitly set by gtk_button_set_image()
 
1991
 * or constructed by gtk_button_new_from_stock().
 
1992
 *
 
1993
 * Return value: a #GtkWidget or %NULL in case there is no image
 
1994
 *
 
1995
 * Since: 2.6
 
1996
 */
 
1997
GtkWidget *
 
1998
gtk_button_get_image (GtkButton *button)
 
1999
{
 
2000
  GtkButtonPrivate *priv;
 
2001
 
 
2002
  g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
 
2003
 
 
2004
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
2005
  
 
2006
  return priv->image;
 
2007
}
 
2008
 
 
2009
/**
 
2010
 * gtk_button_set_image_position:
 
2011
 * @button: a #GtkButton
 
2012
 * @position: the position
 
2013
 *
 
2014
 * Sets the position of the image relative to the text 
 
2015
 * inside the button.
 
2016
 *
 
2017
 * Since: 2.10
 
2018
 */ 
 
2019
void
 
2020
gtk_button_set_image_position (GtkButton       *button,
 
2021
                               GtkPositionType  position)
 
2022
{
 
2023
 
 
2024
  GtkButtonPrivate *priv;
 
2025
 
 
2026
  g_return_if_fail (GTK_IS_BUTTON (button));
 
2027
  g_return_if_fail (position >= GTK_POS_LEFT && position <= GTK_POS_BOTTOM);
 
2028
  
 
2029
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
2030
 
 
2031
  if (priv->image_position != position)
 
2032
    {
 
2033
      priv->image_position = position;
 
2034
 
 
2035
      gtk_button_construct_child (button);
 
2036
 
 
2037
      g_object_notify (G_OBJECT (button), "image-position");
 
2038
    }
 
2039
}
 
2040
 
 
2041
/**
 
2042
 * gtk_button_get_image_position:
 
2043
 * @button: a #GtkButton
 
2044
 *
 
2045
 * Gets the position of the image relative to the text 
 
2046
 * inside the button.
 
2047
 *
 
2048
 * Return value: the position
 
2049
 *
 
2050
 * Since: 2.10
 
2051
 */
 
2052
GtkPositionType
 
2053
gtk_button_get_image_position (GtkButton *button)
 
2054
{
 
2055
  GtkButtonPrivate *priv;
 
2056
 
 
2057
  g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_POS_LEFT);
 
2058
 
 
2059
  priv = GTK_BUTTON_GET_PRIVATE (button);
 
2060
  
 
2061
  return priv->image_position;
 
2062
}
 
2063
 
 
2064
 
 
2065
#define __GTK_BUTTON_C__
 
2066
#include "gtkaliasdef.c"