gtkradiobutton.c 19.8 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1 2 3 4
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10 11
 * 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
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
18
 */
19 20

/*
21
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22 23 24 25 26
 * 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/. 
 */

27
#include "config.h"
Elliot Lee's avatar
Elliot Lee committed
28
#include "gtklabel.h"
29
#include "gtkmarshalers.h"
Elliot Lee's avatar
Elliot Lee committed
30
#include "gtkradiobutton.h"
31
#include "gtkprivate.h"
Manish Singh's avatar
Manish Singh committed
32
#include "gtkintl.h"
33
#include "gtkalias.h"
Elliot Lee's avatar
Elliot Lee committed
34 35


36
enum {
Manish Singh's avatar
Manish Singh committed
37
  PROP_0,
38
  PROP_GROUP
39 40
};

Elliot Lee's avatar
Elliot Lee committed
41

42 43 44 45 46 47
static void     gtk_radio_button_destroy        (GtkObject           *object);
static gboolean gtk_radio_button_focus          (GtkWidget           *widget,
						 GtkDirectionType     direction);
static void     gtk_radio_button_clicked        (GtkButton           *button);
static void     gtk_radio_button_draw_indicator (GtkCheckButton      *check_button,
						 GdkRectangle        *area);
Manish Singh's avatar
Manish Singh committed
48 49 50 51 52 53 54 55
static void     gtk_radio_button_set_property   (GObject             *object,
						 guint                prop_id,
						 const GValue        *value,
						 GParamSpec          *pspec);
static void     gtk_radio_button_get_property   (GObject             *object,
						 guint                prop_id,
						 GValue              *value,
						 GParamSpec          *pspec);
Elliot Lee's avatar
Elliot Lee committed
56

Matthias Clasen's avatar
Matthias Clasen committed
57
G_DEFINE_TYPE (GtkRadioButton, gtk_radio_button, GTK_TYPE_CHECK_BUTTON)
Elliot Lee's avatar
Elliot Lee committed
58

59
static guint group_changed_signal = 0;
Elliot Lee's avatar
Elliot Lee committed
60 61 62 63

static void
gtk_radio_button_class_init (GtkRadioButtonClass *class)
{
Manish Singh's avatar
Manish Singh committed
64
  GObjectClass *gobject_class;
Elliot Lee's avatar
Elliot Lee committed
65 66 67
  GtkObjectClass *object_class;
  GtkButtonClass *button_class;
  GtkCheckButtonClass *check_button_class;
68
  GtkWidgetClass *widget_class;
Elliot Lee's avatar
Elliot Lee committed
69

Manish Singh's avatar
Manish Singh committed
70
  gobject_class = G_OBJECT_CLASS (class);
Elliot Lee's avatar
Elliot Lee committed
71
  object_class = (GtkObjectClass*) class;
72
  widget_class = (GtkWidgetClass*) class;
Elliot Lee's avatar
Elliot Lee committed
73 74 75
  button_class = (GtkButtonClass*) class;
  check_button_class = (GtkCheckButtonClass*) class;

Manish Singh's avatar
Manish Singh committed
76 77
  gobject_class->set_property = gtk_radio_button_set_property;
  gobject_class->get_property = gtk_radio_button_get_property;
78

Manish Singh's avatar
Manish Singh committed
79 80 81
  g_object_class_install_property (gobject_class,
				   PROP_GROUP,
				   g_param_spec_object ("group",
82
							P_("Group"),
83
							P_("The radio button whose group this widget belongs to."),
Manish Singh's avatar
Manish Singh committed
84
							GTK_TYPE_RADIO_BUTTON,
85
							GTK_PARAM_WRITABLE));
Elliot Lee's avatar
Elliot Lee committed
86 87
  object_class->destroy = gtk_radio_button_destroy;

88 89
  widget_class->focus = gtk_radio_button_focus;

Elliot Lee's avatar
Elliot Lee committed
90 91 92
  button_class->clicked = gtk_radio_button_clicked;

  check_button_class->draw_indicator = gtk_radio_button_draw_indicator;
93 94 95 96

  class->group_changed = NULL;

  /**
97
   * GtkRadioButton::group-changed:
98 99 100 101 102
   * @style: the object which received the signal
   *
   * Emitted when the group of radio buttons that a radio button belongs
   * to changes. This is emitted when a radio button switches from
   * being alone to being part of a group of 2 or more buttons, or
Matthias Clasen's avatar
Matthias Clasen committed
103
   * vice-versa, and when a button is moved from one group of 2 or
104 105
   * more buttons to a different one, but not when the composition
   * of the group that a button belongs to changes.
106 107
   *
   * Since: 2.4
108
   */
109
  group_changed_signal = g_signal_new (I_("group-changed"),
110 111 112 113 114 115
				       G_OBJECT_CLASS_TYPE (object_class),
				       G_SIGNAL_RUN_FIRST,
				       G_STRUCT_OFFSET (GtkRadioButtonClass, group_changed),
				       NULL, NULL,
				       _gtk_marshal_VOID__VOID,
				       G_TYPE_NONE, 0);
Elliot Lee's avatar
Elliot Lee committed
116 117 118 119 120
}

static void
gtk_radio_button_init (GtkRadioButton *radio_button)
{
121
  GTK_WIDGET_SET_FLAGS (radio_button, GTK_NO_WINDOW);
122
  GTK_WIDGET_UNSET_FLAGS (radio_button, GTK_RECEIVES_DEFAULT);
123 124 125

  GTK_TOGGLE_BUTTON (radio_button)->active = TRUE;

126 127
  GTK_BUTTON (radio_button)->depress_on_activate = FALSE;

128
  radio_button->group = g_slist_prepend (NULL, radio_button);
129

130
  _gtk_button_set_depressed (GTK_BUTTON (radio_button), TRUE);
131
  gtk_widget_set_state (GTK_WIDGET (radio_button), GTK_STATE_ACTIVE);
Elliot Lee's avatar
Elliot Lee committed
132 133
}

134
static void
Manish Singh's avatar
Manish Singh committed
135 136 137 138
gtk_radio_button_set_property (GObject      *object,
			       guint         prop_id,
			       const GValue *value,
			       GParamSpec   *pspec)
139
{
140 141 142 143
  GtkRadioButton *radio_button;

  radio_button = GTK_RADIO_BUTTON (object);

Manish Singh's avatar
Manish Singh committed
144
  switch (prop_id)
145 146
    {
      GSList *slist;
147
      GtkRadioButton *button;
148

Manish Singh's avatar
Manish Singh committed
149
    case PROP_GROUP:
150
        button = g_value_get_object (value);
151 152 153

      if (button)
	slist = gtk_radio_button_get_group (button);
154 155 156 157 158
      else
	slist = NULL;
      gtk_radio_button_set_group (radio_button, slist);
      break;
    default:
Manish Singh's avatar
Manish Singh committed
159
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
160 161 162 163 164
      break;
    }
}

static void
Manish Singh's avatar
Manish Singh committed
165 166 167 168
gtk_radio_button_get_property (GObject    *object,
			       guint       prop_id,
			       GValue     *value,
			       GParamSpec *pspec)
169
{
Manish Singh's avatar
Manish Singh committed
170
  switch (prop_id)
171 172
    {
    default:
Manish Singh's avatar
Manish Singh committed
173
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
174 175 176 177
      break;
    }
}

178 179
void
gtk_radio_button_set_group (GtkRadioButton *radio_button,
180
			    GSList         *group)
Elliot Lee's avatar
Elliot Lee committed
181
{
182 183 184
  GtkWidget *old_group_singleton = NULL;
  GtkWidget *new_group_singleton = NULL;
  
185 186
  g_return_if_fail (GTK_IS_RADIO_BUTTON (radio_button));
  g_return_if_fail (!g_slist_find (group, radio_button));
187

188 189
  if (radio_button->group)
    {
190
      GSList *slist;
191

192 193
      radio_button->group = g_slist_remove (radio_button->group, radio_button);
      
194 195 196
      if (radio_button->group && !radio_button->group->next)
	old_group_singleton = g_object_ref (radio_button->group->data);
	  
197
      for (slist = radio_button->group; slist; slist = slist->next)
198
	{
199 200 201
	  GtkRadioButton *tmp_button;
	  
	  tmp_button = slist->data;
202 203 204 205
	  
	  tmp_button->group = radio_button->group;
	}
    }
206
  
207 208 209
  if (group && !group->next)
    new_group_singleton = g_object_ref (group->data);
  
Elliot Lee's avatar
Elliot Lee committed
210
  radio_button->group = g_slist_prepend (group, radio_button);
211 212
  
  if (group)
Elliot Lee's avatar
Elliot Lee committed
213
    {
214 215 216
      GSList *slist;
      
      for (slist = group; slist; slist = slist->next)
Elliot Lee's avatar
Elliot Lee committed
217
	{
218 219 220 221
	  GtkRadioButton *tmp_button;
	  
	  tmp_button = slist->data;
	  
Elliot Lee's avatar
Elliot Lee committed
222 223 224
	  tmp_button->group = radio_button->group;
	}
    }
225

226 227
  g_object_ref (radio_button);
  
228
  g_object_notify (G_OBJECT (radio_button), "group");
229 230 231 232 233 234 235 236 237 238 239 240
  g_signal_emit (radio_button, group_changed_signal, 0);
  if (old_group_singleton)
    {
      g_signal_emit (old_group_singleton, group_changed_signal, 0);
      g_object_unref (old_group_singleton);
    }
  if (new_group_singleton)
    {
      g_signal_emit (new_group_singleton, group_changed_signal, 0);
      g_object_unref (new_group_singleton);
    }

241
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), group == NULL);
242 243

  g_object_unref (radio_button);
244 245 246 247 248 249 250
}

GtkWidget*
gtk_radio_button_new (GSList *group)
{
  GtkRadioButton *radio_button;

Manish Singh's avatar
Manish Singh committed
251
  radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, NULL);
252

253 254
  if (group)
    gtk_radio_button_set_group (radio_button, group);
Elliot Lee's avatar
Elliot Lee committed
255 256 257 258 259 260 261 262 263 264

  return GTK_WIDGET (radio_button);
}

GtkWidget*
gtk_radio_button_new_with_label (GSList      *group,
				 const gchar *label)
{
  GtkWidget *radio_button;

265
  radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, "label", label, NULL) ;
Elliot Lee's avatar
Elliot Lee committed
266

267
  if (group)
Havoc Pennington's avatar
Havoc Pennington committed
268
    gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
Elliot Lee's avatar
Elliot Lee committed
269 270 271 272

  return radio_button;
}

273 274 275 276 277 278 279 280

/**
 * gtk_radio_button_new_with_mnemonic:
 * @group: the radio button group
 * @label: the text of the button, with an underscore in front of the
 *         mnemonic character
 * @returns: a new #GtkRadioButton
 *
281 282 283 284
 * Creates a new #GtkRadioButton containing a label, adding it to the same 
 * group as @group. The label will be created using 
 * gtk_label_new_with_mnemonic(), so underscores in @label indicate the 
 * mnemonic for the button.
285 286 287 288 289 290 291
 **/
GtkWidget*
gtk_radio_button_new_with_mnemonic (GSList      *group,
				    const gchar *label)
{
  GtkWidget *radio_button;

292 293 294 295
  radio_button = g_object_new (GTK_TYPE_RADIO_BUTTON, 
			       "label", label, 
			       "use-underline", TRUE, 
			       NULL);
296

297
  if (group)
Havoc Pennington's avatar
Havoc Pennington committed
298
    gtk_radio_button_set_group (GTK_RADIO_BUTTON (radio_button), group);
299 300 301 302

  return radio_button;
}

Elliot Lee's avatar
Elliot Lee committed
303
GtkWidget*
304
gtk_radio_button_new_from_widget (GtkRadioButton *radio_group_member)
Elliot Lee's avatar
Elliot Lee committed
305 306
{
  GSList *l = NULL;
307 308
  if (radio_group_member)
    l = gtk_radio_button_get_group (radio_group_member);
Elliot Lee's avatar
Elliot Lee committed
309 310 311 312 313
  return gtk_radio_button_new (l);
}


GtkWidget*
314
gtk_radio_button_new_with_label_from_widget (GtkRadioButton *radio_group_member,
Elliot Lee's avatar
Elliot Lee committed
315 316 317
					     const gchar    *label)
{
  GSList *l = NULL;
318 319
  if (radio_group_member)
    l = gtk_radio_button_get_group (radio_group_member);
Elliot Lee's avatar
Elliot Lee committed
320 321 322
  return gtk_radio_button_new_with_label (l, label);
}

323 324
/**
 * gtk_radio_button_new_with_mnemonic_from_widget:
325
 * @radio_group_member: widget to get radio group from or %NULL
326 327 328 329 330 331 332 333 334
 * @label: the text of the button, with an underscore in front of the
 *         mnemonic character
 * @returns: a new #GtkRadioButton
 *
 * Creates a new #GtkRadioButton containing a label. The label
 * will be created using gtk_label_new_with_mnemonic(), so underscores
 * in @label indicate the mnemonic for the button.
 **/
GtkWidget*
335
gtk_radio_button_new_with_mnemonic_from_widget (GtkRadioButton *radio_group_member,
336 337 338
					        const gchar    *label)
{
  GSList *l = NULL;
339 340
  if (radio_group_member)
    l = gtk_radio_button_get_group (radio_group_member);
341 342 343
  return gtk_radio_button_new_with_mnemonic (l, label);
}

Elliot Lee's avatar
Elliot Lee committed
344
GSList*
345
gtk_radio_button_get_group (GtkRadioButton *radio_button)
Elliot Lee's avatar
Elliot Lee committed
346 347 348 349 350 351 352 353 354 355
{
  g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_button), NULL);

  return radio_button->group;
}


static void
gtk_radio_button_destroy (GtkObject *object)
{
356
  GtkWidget *old_group_singleton = NULL;
Elliot Lee's avatar
Elliot Lee committed
357 358 359
  GtkRadioButton *radio_button;
  GtkRadioButton *tmp_button;
  GSList *tmp_list;
360 361
  gboolean was_in_group;
  
Elliot Lee's avatar
Elliot Lee committed
362 363
  radio_button = GTK_RADIO_BUTTON (object);

364 365
  was_in_group = radio_button->group && radio_button->group->next;
  
Elliot Lee's avatar
Elliot Lee committed
366
  radio_button->group = g_slist_remove (radio_button->group, radio_button);
367 368 369
  if (radio_button->group && !radio_button->group->next)
    old_group_singleton = radio_button->group->data;

Elliot Lee's avatar
Elliot Lee committed
370 371 372 373 374 375 376 377 378 379
  tmp_list = radio_button->group;

  while (tmp_list)
    {
      tmp_button = tmp_list->data;
      tmp_list = tmp_list->next;

      tmp_button->group = radio_button->group;
    }

380 381
  /* this button is no longer in the group */
  radio_button->group = NULL;
382 383 384 385 386

  if (old_group_singleton)
    g_signal_emit (old_group_singleton, group_changed_signal, 0);
  if (was_in_group)
    g_signal_emit (radio_button, group_changed_signal, 0);
387
  
Matthias Clasen's avatar
Matthias Clasen committed
388 389
  if (GTK_OBJECT_CLASS (gtk_radio_button_parent_class)->destroy)
    (* GTK_OBJECT_CLASS (gtk_radio_button_parent_class)->destroy) (object);
Elliot Lee's avatar
Elliot Lee committed
390 391
}

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
static void
get_coordinates (GtkWidget    *widget,
		 GtkWidget    *reference,
		 gint         *x,
		 gint         *y)
{
  *x = widget->allocation.x + widget->allocation.width / 2;
  *y = widget->allocation.y + widget->allocation.height / 2;
  
  gtk_widget_translate_coordinates (widget, reference, *x, *y, x, y);
}

static gint
left_right_compare (gconstpointer a,
		    gconstpointer b,
		    gpointer      data)
{
  gint x1, y1, x2, y2;

  get_coordinates ((GtkWidget *)a, data, &x1, &y1);
  get_coordinates ((GtkWidget *)b, data, &x2, &y2);

  if (y1 == y2)
    return (x1 < x2) ? -1 : ((x1 == x2) ? 0 : 1);
  else
    return (y1 < y2) ? -1 : 1;
}

static gint
up_down_compare (gconstpointer a,
		 gconstpointer b,
		 gpointer      data)
{
  gint x1, y1, x2, y2;
  
  get_coordinates ((GtkWidget *)a, data, &x1, &y1);
  get_coordinates ((GtkWidget *)b, data, &x2, &y2);
  
  if (x1 == x2)
    return (y1 < y2) ? -1 : ((y1 == y2) ? 0 : 1);
  else
    return (x1 < x2) ? -1 : 1;
}

static gboolean
gtk_radio_button_focus (GtkWidget         *widget,
			GtkDirectionType   direction)
{
  GtkRadioButton *radio_button = GTK_RADIO_BUTTON (widget);
  GSList *tmp_slist;
442 443 444 445 446

  /* Radio buttons with draw_indicator unset focus "normally", since
   * they look like buttons to the user.
   */
  if (!GTK_TOGGLE_BUTTON (widget)->draw_indicator)
Matthias Clasen's avatar
Matthias Clasen committed
447
    return GTK_WIDGET_CLASS (gtk_radio_button_parent_class)->focus (widget, direction);
448 449 450
  
  if (gtk_widget_is_focus (widget))
    {
451
      GtkSettings *settings = gtk_widget_get_settings (widget);
452 453 454
      GSList *focus_list, *tmp_list;
      GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
      GtkWidget *new_focus = NULL;
455 456
      gboolean cursor_only;
      gboolean wrap_around;
457 458 459 460 461

      switch (direction)
	{
	case GTK_DIR_LEFT:
	case GTK_DIR_RIGHT:
Matthias Clasen's avatar
Matthias Clasen committed
462
	  focus_list = g_slist_copy (radio_button->group);
463 464 465 466
	  focus_list = g_slist_sort_with_data (focus_list, left_right_compare, toplevel);
	  break;
	case GTK_DIR_UP:
	case GTK_DIR_DOWN:
Matthias Clasen's avatar
Matthias Clasen committed
467
	  focus_list = g_slist_copy (radio_button->group);
468 469
	  focus_list = g_slist_sort_with_data (focus_list, up_down_compare, toplevel);
	  break;
470 471 472 473 474
	case GTK_DIR_TAB_FORWARD:
	case GTK_DIR_TAB_BACKWARD:
          /* fall through */
        default:
	  return FALSE;
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
	}

      if (direction == GTK_DIR_LEFT || direction == GTK_DIR_UP)
	focus_list = g_slist_reverse (focus_list);

      tmp_list = g_slist_find (focus_list, widget);

      if (tmp_list)
	{
	  tmp_list = tmp_list->next;
	  
	  while (tmp_list)
	    {
	      GtkWidget *child = tmp_list->data;
	      
490
	      if (GTK_WIDGET_REALIZED (child) && GTK_WIDGET_IS_SENSITIVE (child))
491 492 493 494 495 496 497 498 499
		{
		  new_focus = child;
		  break;
		}

	      tmp_list = tmp_list->next;
	    }
	}

500 501 502 503 504
      g_object_get (settings,
                    "gtk-keynav-cursor-only", &cursor_only,
                    "gtk-keynav-wrap-around", &wrap_around,
                    NULL);

505 506
      if (!new_focus)
	{
507
          if (cursor_only)
508 509 510 511 512
            {
              g_slist_free (focus_list);
              return FALSE;
            }

513 514 515 516 517 518 519
          if (!wrap_around)
            {
              g_slist_free (focus_list);
              gtk_widget_error_bell (widget);
              return TRUE;
            }

520 521 522 523 524 525
	  tmp_list = focus_list;

	  while (tmp_list)
	    {
	      GtkWidget *child = tmp_list->data;
	      
526
	      if (GTK_WIDGET_REALIZED (child) && GTK_WIDGET_IS_SENSITIVE (child))
527 528 529 530 531 532 533 534 535 536 537 538 539 540
		{
		  new_focus = child;
		  break;
		}
	      
	      tmp_list = tmp_list->next;
	    }
	}
      
      g_slist_free (focus_list);

      if (new_focus)
	{
	  gtk_widget_grab_focus (new_focus);
541 542 543

          if (!cursor_only)
            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (new_focus), TRUE);
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
	}

      return TRUE;
    }
  else
    {
      GtkRadioButton *selected_button = NULL;
      
      /* We accept the focus if, we don't have the focus and
       *  - we are the currently active button in the group
       *  - there is no currently active radio button.
       */
      
      tmp_slist = radio_button->group;
      while (tmp_slist)
	{
	  if (GTK_TOGGLE_BUTTON (tmp_slist->data)->active)
	    selected_button = tmp_slist->data;
	  tmp_slist = tmp_slist->next;
	}
      
      if (selected_button && selected_button != radio_button)
	return FALSE;

      gtk_widget_grab_focus (widget);
      return TRUE;
    }
}

Elliot Lee's avatar
Elliot Lee committed
573 574 575 576 577 578 579 580 581
static void
gtk_radio_button_clicked (GtkButton *button)
{
  GtkToggleButton *toggle_button;
  GtkRadioButton *radio_button;
  GtkToggleButton *tmp_button;
  GtkStateType new_state;
  GSList *tmp_list;
  gint toggled;
582
  gboolean depressed;
Elliot Lee's avatar
Elliot Lee committed
583 584 585 586 587

  radio_button = GTK_RADIO_BUTTON (button);
  toggle_button = GTK_TOGGLE_BUTTON (button);
  toggled = FALSE;

Manish Singh's avatar
Manish Singh committed
588
  g_object_ref (GTK_WIDGET (button));
589

Elliot Lee's avatar
Elliot Lee committed
590 591 592 593 594 595 596 597 598 599
  if (toggle_button->active)
    {
      tmp_button = NULL;
      tmp_list = radio_button->group;

      while (tmp_list)
	{
	  tmp_button = tmp_list->data;
	  tmp_list = tmp_list->next;

600
	  if (tmp_button->active && tmp_button != toggle_button)
Elliot Lee's avatar
Elliot Lee committed
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
	    break;

	  tmp_button = NULL;
	}

      if (!tmp_button)
	{
	  new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
	}
      else
	{
	  toggled = TRUE;
	  toggle_button->active = !toggle_button->active;
	  new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
	}
    }
  else
    {
      toggled = TRUE;
      toggle_button->active = !toggle_button->active;
621
      
Elliot Lee's avatar
Elliot Lee committed
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
      tmp_list = radio_button->group;
      while (tmp_list)
	{
	  tmp_button = tmp_list->data;
	  tmp_list = tmp_list->next;

	  if (tmp_button->active && (tmp_button != toggle_button))
	    {
	      gtk_button_clicked (GTK_BUTTON (tmp_button));
	      break;
	    }
	}

      new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
    }

638 639 640 641 642 643 644
  if (toggle_button->inconsistent)
    depressed = FALSE;
  else if (button->in_button && button->button_down)
    depressed = !toggle_button->active;
  else
    depressed = toggle_button->active;

Elliot Lee's avatar
Elliot Lee committed
645 646
  if (GTK_WIDGET_STATE (button) != new_state)
    gtk_widget_set_state (GTK_WIDGET (button), new_state);
647

Elliot Lee's avatar
Elliot Lee committed
648
  if (toggled)
649 650 651 652 653
    {
      gtk_toggle_button_toggled (toggle_button);

      g_object_notify (G_OBJECT (toggle_button), "active");
    }
654

655 656
  _gtk_button_set_depressed (button, depressed);

Elliot Lee's avatar
Elliot Lee committed
657
  gtk_widget_queue_draw (GTK_WIDGET (button));
658

Manish Singh's avatar
Manish Singh committed
659
  g_object_unref (button);
Elliot Lee's avatar
Elliot Lee committed
660 661 662 663 664 665 666
}

static void
gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
				 GdkRectangle   *area)
{
  GtkWidget *widget;
667
  GtkWidget *child;
Elliot Lee's avatar
Elliot Lee committed
668 669 670 671 672
  GtkButton *button;
  GtkToggleButton *toggle_button;
  GtkStateType state_type;
  GtkShadowType shadow_type;
  gint x, y;
673
  gint indicator_size, indicator_spacing;
674 675 676
  gint focus_width;
  gint focus_pad;
  gboolean interior_focus;
Elliot Lee's avatar
Elliot Lee committed
677

678
  if (GTK_WIDGET_DRAWABLE (check_button))
Elliot Lee's avatar
Elliot Lee committed
679 680 681 682 683
    {
      widget = GTK_WIDGET (check_button);
      button = GTK_BUTTON (check_button);
      toggle_button = GTK_TOGGLE_BUTTON (check_button);

684
      gtk_widget_style_get (widget,
685
			    "interior-focus", &interior_focus,
686 687 688 689
			    "focus-line-width", &focus_width,
			    "focus-padding", &focus_pad,
			    NULL);

690 691 692 693
      _gtk_check_button_get_props (check_button, &indicator_size, &indicator_spacing);

      x = widget->allocation.x + indicator_spacing + GTK_CONTAINER (widget)->border_width;
      y = widget->allocation.y + (widget->allocation.height - indicator_size) / 2;
694

695 696
      child = GTK_BIN (check_button)->child;
      if (!interior_focus || !(child && GTK_WIDGET_VISIBLE (child)))
697
	x += focus_width + focus_pad;      
698 699 700 701

      if (toggle_button->inconsistent)
	shadow_type = GTK_SHADOW_ETCHED_IN;
      else if (toggle_button->active)
Elliot Lee's avatar
Elliot Lee committed
702 703 704
	shadow_type = GTK_SHADOW_IN;
      else
	shadow_type = GTK_SHADOW_OUT;
705

706 707 708 709
      if (button->activate_timeout || (button->button_down && button->in_button))
	state_type = GTK_STATE_ACTIVE;
      else if (button->in_button)
	state_type = GTK_STATE_PRELIGHT;
710
      else if (!GTK_WIDGET_IS_SENSITIVE (widget))
711
	state_type = GTK_STATE_INSENSITIVE;
712 713 714
      else
	state_type = GTK_STATE_NORMAL;

715
      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
716
	x = widget->allocation.x + widget->allocation.width - (indicator_size + x - widget->allocation.x);
717

718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
      if (GTK_WIDGET_STATE (toggle_button) == GTK_STATE_PRELIGHT)
	{
	  GdkRectangle restrict_area;
	  GdkRectangle new_area;
	      
	  restrict_area.x = widget->allocation.x + GTK_CONTAINER (widget)->border_width;
	  restrict_area.y = widget->allocation.y + GTK_CONTAINER (widget)->border_width;
	  restrict_area.width = widget->allocation.width - (2 * GTK_CONTAINER (widget)->border_width);
	  restrict_area.height = widget->allocation.height - (2 * GTK_CONTAINER (widget)->border_width);
	  
	  if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
	    {
	      gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_PRELIGHT,
				  GTK_SHADOW_ETCHED_OUT, 
				  area, widget, "checkbutton",
				  new_area.x, new_area.y,
				  new_area.width, new_area.height);
	    }
	}

738
      gtk_paint_option (widget->style, widget->window,
739
			state_type, shadow_type,
740
			area, widget, "radiobutton",
741
			x, y, indicator_size, indicator_size);
Elliot Lee's avatar
Elliot Lee committed
742 743
    }
}
744 745 746

#define __GTK_RADIO_BUTTON_C__
#include "gtkaliasdef.c"