gtkstackswitcher.c 17.4 KB
Newer Older
Matthias Clasen's avatar
Matthias Clasen committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright (c) 2013 Red Hat, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "config.h"
#include "gtkstackswitcher.h"
Matthias Clasen's avatar
Matthias Clasen committed
22 23 24
#include "gtkradiobutton.h"
#include "gtklabel.h"
#include "gtkorientable.h"
Matthias Clasen's avatar
Matthias Clasen committed
25 26 27
#include "gtkprivate.h"
#include "gtkintl.h"

28 29
/**
 * SECTION:gtkstackswitcher
30
 * @Short_description: A controller for GtkStack
31 32 33 34 35 36 37 38 39 40 41 42 43 44
 * @Title: GtkStackSwitcher
 * @See_also: #GtkStack
 *
 * The GtkStackSwitcher widget acts as a controller for a
 * #GtkStack; it shows a row of buttons to switch between
 * the various pages of the associated stack widget.
 *
 * All the content for the buttons comes from the child properties
 * of the #GtkStack.
 *
 * It is possible to associate multiple #GtkStackSwitcher widgets
 * with the same stack widget.
 *
 * The GtkStackSwitcher widget was added in 3.10.
45 46 47
 *
 * # CSS nodes
 *
48 49
 * GtkStackSwitcher has a single CSS node named stackswitcher and
 * style class .stack-switcher.
50 51 52 53
 *
 * When circumstances require it, GtkStackSwitcher adds the
 * .needs-attention style class to the widgets representing the
 * stack pages.
54 55
 */

56
typedef struct _GtkStackSwitcherPrivate GtkStackSwitcherPrivate;
Matthias Clasen's avatar
Matthias Clasen committed
57 58 59 60
struct _GtkStackSwitcherPrivate
{
  GtkStack *stack;
  GHashTable *buttons;
61
  gint icon_size;
Matthias Clasen's avatar
Matthias Clasen committed
62 63 64 65 66
  gboolean in_child_changed;
};

enum {
  PROP_0,
67
  PROP_ICON_SIZE,
Matthias Clasen's avatar
Matthias Clasen committed
68 69 70
  PROP_STACK
};

71
G_DEFINE_TYPE_WITH_PRIVATE (GtkStackSwitcher, gtk_stack_switcher, GTK_TYPE_BOX)
Matthias Clasen's avatar
Matthias Clasen committed
72 73 74 75 76 77 78

static void
gtk_stack_switcher_init (GtkStackSwitcher *switcher)
{
  GtkStyleContext *context;
  GtkStackSwitcherPrivate *priv;

79
  priv = gtk_stack_switcher_get_instance_private (switcher);
Matthias Clasen's avatar
Matthias Clasen committed
80

81
  priv->icon_size = GTK_ICON_SIZE_MENU;
Matthias Clasen's avatar
Matthias Clasen committed
82 83 84 85
  priv->stack = NULL;
  priv->buttons = g_hash_table_new (g_direct_hash, g_direct_equal);

  context = gtk_widget_get_style_context (GTK_WIDGET (switcher));
86
  gtk_style_context_add_class (context, "stack-switcher");
Matthias Clasen's avatar
Matthias Clasen committed
87 88 89 90 91 92 93 94 95 96
  gtk_style_context_add_class (context, GTK_STYLE_CLASS_LINKED);

  gtk_orientable_set_orientation (GTK_ORIENTABLE (switcher), GTK_ORIENTATION_HORIZONTAL);
}

static void
on_button_clicked (GtkWidget        *widget,
                   GtkStackSwitcher *self)
{
  GtkWidget *child;
97 98 99
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);
Matthias Clasen's avatar
Matthias Clasen committed
100

101
  if (!priv->in_child_changed)
Matthias Clasen's avatar
Matthias Clasen committed
102 103
    {
      child = g_object_get_data (G_OBJECT (widget), "stack-child");
104
      gtk_stack_set_visible_child (priv->stack, child);
Matthias Clasen's avatar
Matthias Clasen committed
105 106 107 108 109 110
    }
}

static void
rebuild_child (GtkWidget   *self,
               const gchar *icon_name,
111 112
               const gchar *title,
               gint         icon_size)
Matthias Clasen's avatar
Matthias Clasen committed
113 114 115 116 117 118 119 120 121 122 123 124 125
{
  GtkStyleContext *context;
  GtkWidget *button_child;

  button_child = gtk_bin_get_child (GTK_BIN (self));
  if (button_child != NULL)
    gtk_widget_destroy (button_child);

  button_child = NULL;
  context = gtk_widget_get_style_context (GTK_WIDGET (self));

  if (icon_name != NULL)
    {
126
      button_child = gtk_image_new_from_icon_name (icon_name, icon_size);
Matthias Clasen's avatar
Matthias Clasen committed
127 128 129 130 131 132 133 134 135 136
      if (title != NULL)
        gtk_widget_set_tooltip_text (GTK_WIDGET (self), title);

      gtk_style_context_remove_class (context, "text-button");
      gtk_style_context_add_class (context, "image-button");
    }
  else if (title != NULL)
    {
      button_child = gtk_label_new (title);

137 138
      gtk_widget_set_tooltip_text (GTK_WIDGET (self), NULL);

Matthias Clasen's avatar
Matthias Clasen committed
139 140 141 142 143 144
      gtk_style_context_remove_class (context, "image-button");
      gtk_style_context_add_class (context, "text-button");
    }

  if (button_child)
    {
145
      gtk_widget_set_halign (GTK_WIDGET (button_child), GTK_ALIGN_CENTER);
Matthias Clasen's avatar
Matthias Clasen committed
146 147 148 149 150
      gtk_widget_show_all (button_child);
      gtk_container_add (GTK_CONTAINER (self), button_child);
    }
}

151
static void
Matthias Clasen's avatar
Matthias Clasen committed
152
update_needs_attention (GtkWidget *widget, GtkWidget *button, gpointer data)
153 154 155 156 157 158 159 160 161 162 163
{
  GtkContainer *container;
  gboolean needs_attention;
  GtkStyleContext *context;

  container = GTK_CONTAINER (data);
  gtk_container_child_get (container, widget,
                           "needs-attention", &needs_attention,
                           NULL);

  context = gtk_widget_get_style_context (button);
164
  if (needs_attention)
165 166 167 168 169
    gtk_style_context_add_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
  else
    gtk_style_context_remove_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
}

Matthias Clasen's avatar
Matthias Clasen committed
170 171 172 173 174 175 176
static void
update_button (GtkStackSwitcher *self,
               GtkWidget        *widget,
               GtkWidget        *button)
{
  gchar *title;
  gchar *icon_name;
177 178 179
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);
Matthias Clasen's avatar
Matthias Clasen committed
180

181
  gtk_container_child_get (GTK_CONTAINER (priv->stack), widget,
Matthias Clasen's avatar
Matthias Clasen committed
182 183 184 185
                           "title", &title,
                           "icon-name", &icon_name,
                           NULL);

186
  rebuild_child (button, icon_name, title, priv->icon_size);
Matthias Clasen's avatar
Matthias Clasen committed
187

188
  gtk_widget_set_visible (button, gtk_widget_get_visible (widget) && (title != NULL || icon_name != NULL));
Matthias Clasen's avatar
Matthias Clasen committed
189 190 191

  g_free (title);
  g_free (icon_name);
192 193

  update_needs_attention (widget, button, priv->stack);
Matthias Clasen's avatar
Matthias Clasen committed
194 195 196
}

static void
197 198 199
on_title_icon_visible_updated (GtkWidget        *widget,
                               GParamSpec       *pspec,
                               GtkStackSwitcher *self)
Matthias Clasen's avatar
Matthias Clasen committed
200 201
{
  GtkWidget *button;
202 203 204
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);
Matthias Clasen's avatar
Matthias Clasen committed
205

206
  button = g_hash_table_lookup (priv->buttons, widget);
Matthias Clasen's avatar
Matthias Clasen committed
207 208 209 210 211 212 213 214 215 216
  update_button (self, widget, button);
}

static void
on_position_updated (GtkWidget        *widget,
                     GParamSpec       *pspec,
                     GtkStackSwitcher *self)
{
  GtkWidget *button;
  gint position;
217
  GtkStackSwitcherPrivate *priv;
Matthias Clasen's avatar
Matthias Clasen committed
218

219
  priv = gtk_stack_switcher_get_instance_private (self);
Matthias Clasen's avatar
Matthias Clasen committed
220

221 222 223
  button = g_hash_table_lookup (priv->buttons, widget);

  gtk_container_child_get (GTK_CONTAINER (priv->stack), widget,
Matthias Clasen's avatar
Matthias Clasen committed
224 225 226 227 228 229
                           "position", &position,
                           NULL);

  gtk_box_reorder_child (GTK_BOX (self), button, position);
}

230 231 232 233 234 235 236 237 238 239 240 241 242 243
static void
on_needs_attention_updated (GtkWidget        *widget,
                            GParamSpec       *pspec,
                            GtkStackSwitcher *self)
{
  GtkWidget *button;
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);

  button = g_hash_table_lookup (priv->buttons, widget);
  update_button (self, widget, button);
}

Matthias Clasen's avatar
Matthias Clasen committed
244
static void
245 246
add_child (GtkWidget        *widget,
           GtkStackSwitcher *self)
Matthias Clasen's avatar
Matthias Clasen committed
247 248 249
{
  GtkWidget *button;
  GList *group;
250 251 252
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);
Matthias Clasen's avatar
Matthias Clasen committed
253 254

  button = gtk_radio_button_new (NULL);
255
  gtk_widget_set_focus_on_click (button, FALSE);
Matthias Clasen's avatar
Matthias Clasen committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);

  update_button (self, widget, button);

  group = gtk_container_get_children (GTK_CONTAINER (self));
  if (group != NULL)
    {
      gtk_radio_button_join_group (GTK_RADIO_BUTTON (button), GTK_RADIO_BUTTON (group->data));
      g_list_free (group);
    }

  gtk_container_add (GTK_CONTAINER (self), button);

  g_object_set_data (G_OBJECT (button), "stack-child", widget);
  g_signal_connect (button, "clicked", G_CALLBACK (on_button_clicked), self);
271 272 273
  g_signal_connect (widget, "notify::visible", G_CALLBACK (on_title_icon_visible_updated), self);
  g_signal_connect (widget, "child-notify::title", G_CALLBACK (on_title_icon_visible_updated), self);
  g_signal_connect (widget, "child-notify::icon-name", G_CALLBACK (on_title_icon_visible_updated), self);
Matthias Clasen's avatar
Matthias Clasen committed
274
  g_signal_connect (widget, "child-notify::position", G_CALLBACK (on_position_updated), self);
275
  g_signal_connect (widget, "child-notify::needs-attention", G_CALLBACK (on_needs_attention_updated), self);
Matthias Clasen's avatar
Matthias Clasen committed
276

277
  g_hash_table_insert (priv->buttons, widget, button);
Matthias Clasen's avatar
Matthias Clasen committed
278 279 280
}

static void
281 282
remove_child (GtkWidget        *widget,
              GtkStackSwitcher *self)
Matthias Clasen's avatar
Matthias Clasen committed
283
{
284 285 286 287 288 289 290 291 292 293 294 295
  GtkWidget *button;
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);

  g_signal_handlers_disconnect_by_func (widget, on_title_icon_visible_updated, self);
  g_signal_handlers_disconnect_by_func (widget, on_position_updated, self);
  g_signal_handlers_disconnect_by_func (widget, on_needs_attention_updated, self);

  button = g_hash_table_lookup (priv->buttons, widget);
  gtk_container_remove (GTK_CONTAINER (self), button);
  g_hash_table_remove (priv->buttons, widget);
Matthias Clasen's avatar
Matthias Clasen committed
296 297 298 299 300
}

static void
populate_switcher (GtkStackSwitcher *self)
{
301
  GtkStackSwitcherPrivate *priv;
302
  GtkWidget *widget, *button;
303 304

  priv = gtk_stack_switcher_get_instance_private (self);
305
  gtk_container_foreach (GTK_CONTAINER (priv->stack), (GtkCallback)add_child, self);
306 307 308 309 310

  widget = gtk_stack_get_visible_child (priv->stack);
  if (widget)
    {
      button = g_hash_table_lookup (priv->buttons, widget);
311
      priv->in_child_changed = TRUE;
312
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
313
      priv->in_child_changed = FALSE;
314
    }
315 316 317 318 319 320 321 322 323
}

static void
clear_switcher (GtkStackSwitcher *self)
{
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);
  gtk_container_foreach (GTK_CONTAINER (priv->stack), (GtkCallback)remove_child, self);
Matthias Clasen's avatar
Matthias Clasen committed
324 325 326 327 328 329 330 331 332
}

static void
on_child_changed (GtkWidget        *widget,
                  GParamSpec       *pspec,
                  GtkStackSwitcher *self)
{
  GtkWidget *child;
  GtkWidget *button;
333 334 335
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (self);
Matthias Clasen's avatar
Matthias Clasen committed
336 337

  child = gtk_stack_get_visible_child (GTK_STACK (widget));
338
  button = g_hash_table_lookup (priv->buttons, child);
Matthias Clasen's avatar
Matthias Clasen committed
339 340
  if (button != NULL)
    {
341
      priv->in_child_changed = TRUE;
Matthias Clasen's avatar
Matthias Clasen committed
342
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
343
      priv->in_child_changed = FALSE;
Matthias Clasen's avatar
Matthias Clasen committed
344 345 346 347 348 349 350 351
    }
}

static void
on_stack_child_added (GtkContainer     *container,
                      GtkWidget        *widget,
                      GtkStackSwitcher *self)
{
352
  add_child (widget, self);
Matthias Clasen's avatar
Matthias Clasen committed
353 354 355 356 357 358 359
}

static void
on_stack_child_removed (GtkContainer     *container,
                        GtkWidget        *widget,
                        GtkStackSwitcher *self)
{
360
  remove_child (widget, self);
Matthias Clasen's avatar
Matthias Clasen committed
361 362 363 364 365
}

static void
disconnect_stack_signals (GtkStackSwitcher *switcher)
{
366
  GtkStackSwitcherPrivate *priv;
Matthias Clasen's avatar
Matthias Clasen committed
367

368
  priv = gtk_stack_switcher_get_instance_private (switcher);
Matthias Clasen's avatar
Matthias Clasen committed
369 370 371 372 373 374 375 376 377
  g_signal_handlers_disconnect_by_func (priv->stack, on_stack_child_added, switcher);
  g_signal_handlers_disconnect_by_func (priv->stack, on_stack_child_removed, switcher);
  g_signal_handlers_disconnect_by_func (priv->stack, on_child_changed, switcher);
  g_signal_handlers_disconnect_by_func (priv->stack, disconnect_stack_signals, switcher);
}

static void
connect_stack_signals (GtkStackSwitcher *switcher)
{
378
  GtkStackSwitcherPrivate *priv;
Matthias Clasen's avatar
Matthias Clasen committed
379

380
  priv = gtk_stack_switcher_get_instance_private (switcher);
Matthias Clasen's avatar
Matthias Clasen committed
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
  g_signal_connect_after (priv->stack, "add",
                          G_CALLBACK (on_stack_child_added), switcher);
  g_signal_connect_after (priv->stack, "remove",
                          G_CALLBACK (on_stack_child_removed), switcher);
  g_signal_connect (priv->stack, "notify::visible-child",
                    G_CALLBACK (on_child_changed), switcher);
  g_signal_connect_swapped (priv->stack, "destroy",
                            G_CALLBACK (disconnect_stack_signals), switcher);
}

/**
 * gtk_stack_switcher_set_stack:
 * @switcher: a #GtkStackSwitcher
 * @stack: (allow-none): a #GtkStack
 *
 * Sets the stack to control.
397 398
 *
 * Since: 3.10
Matthias Clasen's avatar
Matthias Clasen committed
399 400 401 402 403 404 405 406
 */
void
gtk_stack_switcher_set_stack (GtkStackSwitcher *switcher,
                              GtkStack         *stack)
{
  GtkStackSwitcherPrivate *priv;

  g_return_if_fail (GTK_IS_STACK_SWITCHER (switcher));
407
  g_return_if_fail (GTK_IS_STACK (stack) || stack == NULL);
Matthias Clasen's avatar
Matthias Clasen committed
408

409
  priv = gtk_stack_switcher_get_instance_private (switcher);
Matthias Clasen's avatar
Matthias Clasen committed
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

  if (priv->stack == stack)
    return;

  if (priv->stack)
    {
      disconnect_stack_signals (switcher);
      clear_switcher (switcher);
      g_clear_object (&priv->stack);
    }
  if (stack)
    {
      priv->stack = g_object_ref (stack);
      populate_switcher (switcher);
      connect_stack_signals (switcher);
    }

  gtk_widget_queue_resize (GTK_WIDGET (switcher));

  g_object_notify (G_OBJECT (switcher), "stack");
}

/**
 * gtk_stack_switcher_get_stack:
 * @switcher: a #GtkStackSwitcher
 *
436 437
 * Retrieves the stack.
 * See gtk_stack_switcher_set_stack().
Matthias Clasen's avatar
Matthias Clasen committed
438
 *
439
 * Returns: (transfer none): the stack, or %NULL if
Matthias Clasen's avatar
Matthias Clasen committed
440
 *    none has been set explicitly.
441 442
 *
 * Since: 3.10
Matthias Clasen's avatar
Matthias Clasen committed
443 444 445 446
 */
GtkStack *
gtk_stack_switcher_get_stack (GtkStackSwitcher *switcher)
{
447
  GtkStackSwitcherPrivate *priv;
Matthias Clasen's avatar
Matthias Clasen committed
448 449
  g_return_val_if_fail (GTK_IS_STACK_SWITCHER (switcher), NULL);

450 451
  priv = gtk_stack_switcher_get_instance_private (switcher);
  return priv->stack;
Matthias Clasen's avatar
Matthias Clasen committed
452 453
}

454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
static void
gtk_stack_switcher_set_icon_size (GtkStackSwitcher *switcher,
                                  gint              icon_size)
{
  GtkStackSwitcherPrivate *priv;

  g_return_if_fail (GTK_IS_STACK_SWITCHER (switcher));

  priv = gtk_stack_switcher_get_instance_private (switcher);

  if (icon_size != priv->icon_size)
    {
      priv->icon_size = icon_size;

      if (priv->stack != NULL)
        {
          clear_switcher (switcher);
          populate_switcher (switcher);
        }
473 474

      g_object_notify (G_OBJECT (switcher), "icon-size");
475 476 477
    }
}

Matthias Clasen's avatar
Matthias Clasen committed
478 479 480 481 482 483 484
static void
gtk_stack_switcher_get_property (GObject      *object,
                                 guint         prop_id,
                                 GValue       *value,
                                 GParamSpec   *pspec)
{
  GtkStackSwitcher *switcher = GTK_STACK_SWITCHER (object);
485
  GtkStackSwitcherPrivate *priv;
Matthias Clasen's avatar
Matthias Clasen committed
486

487
  priv = gtk_stack_switcher_get_instance_private (switcher);
Matthias Clasen's avatar
Matthias Clasen committed
488 489
  switch (prop_id)
    {
490 491 492 493
    case PROP_ICON_SIZE:
      g_value_set_int (value, priv->icon_size);
      break;

Matthias Clasen's avatar
Matthias Clasen committed
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
    case PROP_STACK:
      g_value_set_object (value, priv->stack);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gtk_stack_switcher_set_property (GObject      *object,
                                 guint         prop_id,
                                 const GValue *value,
                                 GParamSpec   *pspec)
{
  GtkStackSwitcher *switcher = GTK_STACK_SWITCHER (object);

  switch (prop_id)
    {
514 515 516 517
    case PROP_ICON_SIZE:
      gtk_stack_switcher_set_icon_size (switcher, g_value_get_int (value));
      break;

Matthias Clasen's avatar
Matthias Clasen committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
    case PROP_STACK:
      gtk_stack_switcher_set_stack (switcher, g_value_get_object (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gtk_stack_switcher_dispose (GObject *object)
{
  GtkStackSwitcher *switcher = GTK_STACK_SWITCHER (object);

  gtk_stack_switcher_set_stack (switcher, NULL);

  G_OBJECT_CLASS (gtk_stack_switcher_parent_class)->dispose (object);
}

538 539 540 541 542 543 544 545 546 547 548 549 550
static void
gtk_stack_switcher_finalize (GObject *object)
{
  GtkStackSwitcher *switcher = GTK_STACK_SWITCHER (object);
  GtkStackSwitcherPrivate *priv;

  priv = gtk_stack_switcher_get_instance_private (switcher);

  g_hash_table_destroy (priv->buttons);

  G_OBJECT_CLASS (gtk_stack_switcher_parent_class)->finalize (object);
}

Matthias Clasen's avatar
Matthias Clasen committed
551 552 553 554
static void
gtk_stack_switcher_class_init (GtkStackSwitcherClass *class)
{
  GObjectClass *object_class = G_OBJECT_CLASS (class);
555
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
Matthias Clasen's avatar
Matthias Clasen committed
556 557 558 559

  object_class->get_property = gtk_stack_switcher_get_property;
  object_class->set_property = gtk_stack_switcher_set_property;
  object_class->dispose = gtk_stack_switcher_dispose;
560
  object_class->finalize = gtk_stack_switcher_finalize;
Matthias Clasen's avatar
Matthias Clasen committed
561

562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
  /**
   * GtkStackSwitcher:icon-size:
   *
   * Use the "icon-size" property to change the size of the image displayed
   * when a #GtkStackSwitcher is displaying icons.
   *
   * Since: 3.20
   */
  g_object_class_install_property (object_class,
                                   PROP_ICON_SIZE,
                                   g_param_spec_int ("icon-size",
                                                     P_("Icon Size"),
                                                     P_("Symbolic size to use for named icon"),
                                                     0, G_MAXINT,
                                                     GTK_ICON_SIZE_MENU,
                                                     G_PARAM_EXPLICIT_NOTIFY | GTK_PARAM_READWRITE));

Matthias Clasen's avatar
Matthias Clasen committed
579 580 581 582 583 584 585 586
  g_object_class_install_property (object_class,
                                   PROP_STACK,
                                   g_param_spec_object ("stack",
                                                        P_("Stack"),
                                                        P_("Stack"),
                                                        GTK_TYPE_STACK,
                                                        GTK_PARAM_READWRITE |
                                                        G_PARAM_CONSTRUCT));
587 588

  gtk_widget_class_set_css_name (widget_class, "stackswitcher");
Matthias Clasen's avatar
Matthias Clasen committed
589 590
}

591 592 593 594 595
/**
 * gtk_stack_switcher_new:
 *
 * Create a new #GtkStackSwitcher.
 *
596
 * Returns: a new #GtkStackSwitcher.
597 598 599
 *
 * Since: 3.10
 */
Matthias Clasen's avatar
Matthias Clasen committed
600 601 602
GtkWidget *
gtk_stack_switcher_new (void)
{
603
  return g_object_new (GTK_TYPE_STACK_SWITCHER, NULL);
Matthias Clasen's avatar
Matthias Clasen committed
604
}