forked from AuroraMiddleware/gtk
d9a146f54a
We no longer support registering custom icon sizes, so we can make these properties just enums. This also lets us specify them by nick in ui files. Nice!
714 lines
20 KiB
C
714 lines
20 KiB
C
/*
|
|
* 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"
|
|
#include "gtkradiobutton.h"
|
|
#include "gtklabel.h"
|
|
#include "gtkdnd.h"
|
|
#include "gtkdragdest.h"
|
|
#include "gtkorientable.h"
|
|
#include "gtkprivate.h"
|
|
#include "gtkintl.h"
|
|
#include "gtkwidgetprivate.h"
|
|
#include "gtktypebuiltins.h"
|
|
|
|
/**
|
|
* SECTION:gtkstackswitcher
|
|
* @Short_description: A controller for GtkStack
|
|
* @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; the button visibility in a #GtkStackSwitcher
|
|
* widget is controlled by the visibility of the child in the
|
|
* #GtkStack.
|
|
*
|
|
* It is possible to associate multiple #GtkStackSwitcher widgets
|
|
* with the same #GtkStack widget.
|
|
*
|
|
* The GtkStackSwitcher widget was added in 3.10.
|
|
*
|
|
* # CSS nodes
|
|
*
|
|
* GtkStackSwitcher has a single CSS node named stackswitcher and
|
|
* style class .stack-switcher.
|
|
*
|
|
* When circumstances require it, GtkStackSwitcher adds the
|
|
* .needs-attention style class to the widgets representing the
|
|
* stack pages.
|
|
*/
|
|
|
|
#define TIMEOUT_EXPAND 500
|
|
|
|
typedef struct _GtkStackSwitcherPrivate GtkStackSwitcherPrivate;
|
|
struct _GtkStackSwitcherPrivate
|
|
{
|
|
GtkStack *stack;
|
|
GHashTable *buttons;
|
|
GtkIconSize icon_size;
|
|
gboolean in_child_changed;
|
|
GtkWidget *switch_button;
|
|
guint switch_timer;
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_ICON_SIZE,
|
|
PROP_STACK
|
|
};
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GtkStackSwitcher, gtk_stack_switcher, GTK_TYPE_BOX)
|
|
|
|
static void
|
|
gtk_stack_switcher_init (GtkStackSwitcher *switcher)
|
|
{
|
|
GtkStyleContext *context;
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
gtk_widget_set_has_window (GTK_WIDGET (switcher), FALSE);
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (switcher);
|
|
|
|
priv->icon_size = GTK_ICON_SIZE_INHERIT;
|
|
priv->stack = NULL;
|
|
priv->buttons = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
|
|
context = gtk_widget_get_style_context (GTK_WIDGET (switcher));
|
|
gtk_style_context_add_class (context, "stack-switcher");
|
|
gtk_style_context_add_class (context, GTK_STYLE_CLASS_LINKED);
|
|
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (switcher), GTK_ORIENTATION_HORIZONTAL);
|
|
|
|
gtk_drag_dest_set (GTK_WIDGET (switcher), 0, NULL, 0);
|
|
gtk_drag_dest_set_track_motion (GTK_WIDGET (switcher), TRUE);
|
|
}
|
|
|
|
static void
|
|
on_button_clicked (GtkWidget *widget,
|
|
GtkStackSwitcher *self)
|
|
{
|
|
GtkWidget *child;
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
if (!priv->in_child_changed)
|
|
{
|
|
child = g_object_get_data (G_OBJECT (widget), "stack-child");
|
|
gtk_stack_set_visible_child (priv->stack, child);
|
|
}
|
|
}
|
|
|
|
static void
|
|
rebuild_child (GtkWidget *self,
|
|
const gchar *icon_name,
|
|
const gchar *title,
|
|
gint icon_size)
|
|
{
|
|
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)
|
|
{
|
|
button_child = gtk_image_new_from_icon_name (icon_name);
|
|
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);
|
|
|
|
gtk_widget_set_tooltip_text (GTK_WIDGET (self), NULL);
|
|
|
|
gtk_style_context_remove_class (context, "image-button");
|
|
gtk_style_context_add_class (context, "text-button");
|
|
}
|
|
|
|
if (button_child)
|
|
{
|
|
gtk_widget_set_halign (GTK_WIDGET (button_child), GTK_ALIGN_CENTER);
|
|
gtk_container_add (GTK_CONTAINER (self), button_child);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_needs_attention (GtkWidget *widget, GtkWidget *button, gpointer data)
|
|
{
|
|
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);
|
|
if (needs_attention)
|
|
gtk_style_context_add_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
|
|
else
|
|
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
|
|
}
|
|
|
|
static void
|
|
update_button (GtkStackSwitcher *self,
|
|
GtkWidget *widget,
|
|
GtkWidget *button)
|
|
{
|
|
gchar *title;
|
|
gchar *icon_name;
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
gtk_container_child_get (GTK_CONTAINER (priv->stack), widget,
|
|
"title", &title,
|
|
"icon-name", &icon_name,
|
|
NULL);
|
|
|
|
rebuild_child (button, icon_name, title, priv->icon_size);
|
|
|
|
gtk_widget_set_visible (button, gtk_widget_get_visible (widget) && (title != NULL || icon_name != NULL));
|
|
|
|
g_free (title);
|
|
g_free (icon_name);
|
|
|
|
update_needs_attention (widget, button, priv->stack);
|
|
}
|
|
|
|
static void
|
|
on_title_icon_visible_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);
|
|
}
|
|
|
|
static void
|
|
on_position_updated (GtkWidget *widget,
|
|
GParamSpec *pspec,
|
|
GtkStackSwitcher *self)
|
|
{
|
|
GtkWidget *button;
|
|
gint position;
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
button = g_hash_table_lookup (priv->buttons, widget);
|
|
|
|
gtk_container_child_get (GTK_CONTAINER (priv->stack), widget,
|
|
"position", &position,
|
|
NULL);
|
|
|
|
gtk_box_reorder_child (GTK_BOX (self), button, position);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static void
|
|
remove_switch_timer (GtkStackSwitcher *self)
|
|
{
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
if (priv->switch_timer)
|
|
{
|
|
g_source_remove (priv->switch_timer);
|
|
priv->switch_timer = 0;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gtk_stack_switcher_switch_timeout (gpointer data)
|
|
{
|
|
GtkStackSwitcher *self = data;
|
|
GtkStackSwitcherPrivate *priv;
|
|
GtkWidget *button;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
priv->switch_timer = 0;
|
|
|
|
button = priv->switch_button;
|
|
priv->switch_button = NULL;
|
|
|
|
if (button)
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
|
|
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static gboolean
|
|
gtk_stack_switcher_drag_motion (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
gint x,
|
|
gint y,
|
|
guint time)
|
|
{
|
|
GtkStackSwitcher *self = GTK_STACK_SWITCHER (widget);
|
|
GtkStackSwitcherPrivate *priv;
|
|
GtkWidget *button;
|
|
GHashTableIter iter;
|
|
gpointer value;
|
|
gboolean retval = FALSE;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
button = NULL;
|
|
g_hash_table_iter_init (&iter, priv->buttons);
|
|
while (g_hash_table_iter_next (&iter, NULL, &value))
|
|
{
|
|
GdkRectangle allocation;
|
|
|
|
gtk_widget_get_outer_allocation (GTK_WIDGET (value), &allocation);
|
|
if (gdk_rectangle_contains_point (&allocation, (int)x, (int)y))
|
|
{
|
|
button = GTK_WIDGET (value);
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (button != priv->switch_button)
|
|
remove_switch_timer (self);
|
|
|
|
priv->switch_button = button;
|
|
|
|
if (button && !priv->switch_timer)
|
|
{
|
|
priv->switch_timer = gdk_threads_add_timeout (TIMEOUT_EXPAND,
|
|
gtk_stack_switcher_switch_timeout,
|
|
self);
|
|
g_source_set_name_by_id (priv->switch_timer, "[gtk+] gtk_stack_switcher_switch_timeout");
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
static void
|
|
gtk_stack_switcher_drag_leave (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
guint time)
|
|
{
|
|
GtkStackSwitcher *self = GTK_STACK_SWITCHER (widget);
|
|
|
|
remove_switch_timer (self);
|
|
}
|
|
|
|
static void
|
|
add_child (GtkWidget *widget,
|
|
GtkStackSwitcher *self)
|
|
{
|
|
GtkWidget *button;
|
|
GList *group;
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
button = gtk_radio_button_new (NULL);
|
|
|
|
gtk_widget_set_focus_on_click (button, FALSE);
|
|
gtk_check_button_set_draw_indicator (GTK_CHECK_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);
|
|
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);
|
|
g_signal_connect (widget, "child-notify::position", G_CALLBACK (on_position_updated), self);
|
|
g_signal_connect (widget, "child-notify::needs-attention", G_CALLBACK (on_needs_attention_updated), self);
|
|
|
|
g_hash_table_insert (priv->buttons, widget, button);
|
|
}
|
|
|
|
static void
|
|
remove_child (GtkWidget *widget,
|
|
GtkStackSwitcher *self)
|
|
{
|
|
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);
|
|
}
|
|
|
|
static void
|
|
populate_switcher (GtkStackSwitcher *self)
|
|
{
|
|
GtkStackSwitcherPrivate *priv;
|
|
GtkWidget *widget, *button;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
gtk_container_foreach (GTK_CONTAINER (priv->stack), (GtkCallback)add_child, self);
|
|
|
|
widget = gtk_stack_get_visible_child (priv->stack);
|
|
if (widget)
|
|
{
|
|
button = g_hash_table_lookup (priv->buttons, widget);
|
|
priv->in_child_changed = TRUE;
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
|
|
priv->in_child_changed = FALSE;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static void
|
|
on_child_changed (GtkWidget *widget,
|
|
GParamSpec *pspec,
|
|
GtkStackSwitcher *self)
|
|
{
|
|
GtkWidget *child;
|
|
GtkWidget *button;
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (self);
|
|
|
|
child = gtk_stack_get_visible_child (GTK_STACK (widget));
|
|
button = g_hash_table_lookup (priv->buttons, child);
|
|
if (button != NULL)
|
|
{
|
|
priv->in_child_changed = TRUE;
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
|
|
priv->in_child_changed = FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_stack_child_added (GtkContainer *container,
|
|
GtkWidget *widget,
|
|
GtkStackSwitcher *self)
|
|
{
|
|
add_child (widget, self);
|
|
}
|
|
|
|
static void
|
|
on_stack_child_removed (GtkContainer *container,
|
|
GtkWidget *widget,
|
|
GtkStackSwitcher *self)
|
|
{
|
|
remove_child (widget, self);
|
|
}
|
|
|
|
static void
|
|
disconnect_stack_signals (GtkStackSwitcher *switcher)
|
|
{
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (switcher);
|
|
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)
|
|
{
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (switcher);
|
|
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.
|
|
*
|
|
* Since: 3.10
|
|
*/
|
|
void
|
|
gtk_stack_switcher_set_stack (GtkStackSwitcher *switcher,
|
|
GtkStack *stack)
|
|
{
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
g_return_if_fail (GTK_IS_STACK_SWITCHER (switcher));
|
|
g_return_if_fail (GTK_IS_STACK (stack) || stack == NULL);
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (switcher);
|
|
|
|
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
|
|
*
|
|
* Retrieves the stack.
|
|
* See gtk_stack_switcher_set_stack().
|
|
*
|
|
* Returns: (nullable) (transfer none): the stack, or %NULL if
|
|
* none has been set explicitly.
|
|
*
|
|
* Since: 3.10
|
|
*/
|
|
GtkStack *
|
|
gtk_stack_switcher_get_stack (GtkStackSwitcher *switcher)
|
|
{
|
|
GtkStackSwitcherPrivate *priv;
|
|
g_return_val_if_fail (GTK_IS_STACK_SWITCHER (switcher), NULL);
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (switcher);
|
|
return priv->stack;
|
|
}
|
|
|
|
static void
|
|
gtk_stack_switcher_set_icon_size (GtkStackSwitcher *switcher,
|
|
GtkIconSize 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);
|
|
}
|
|
|
|
g_object_notify (G_OBJECT (switcher), "icon-size");
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_stack_switcher_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GtkStackSwitcher *switcher = GTK_STACK_SWITCHER (object);
|
|
GtkStackSwitcherPrivate *priv;
|
|
|
|
priv = gtk_stack_switcher_get_instance_private (switcher);
|
|
switch (prop_id)
|
|
{
|
|
case PROP_ICON_SIZE:
|
|
g_value_set_enum (value, priv->icon_size);
|
|
break;
|
|
|
|
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)
|
|
{
|
|
case PROP_ICON_SIZE:
|
|
gtk_stack_switcher_set_icon_size (switcher, g_value_get_enum (value));
|
|
break;
|
|
|
|
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);
|
|
|
|
remove_switch_timer (switcher);
|
|
gtk_stack_switcher_set_stack (switcher, NULL);
|
|
|
|
G_OBJECT_CLASS (gtk_stack_switcher_parent_class)->dispose (object);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static void
|
|
gtk_stack_switcher_class_init (GtkStackSwitcherClass *class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
|
|
|
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;
|
|
object_class->finalize = gtk_stack_switcher_finalize;
|
|
|
|
widget_class->drag_motion = gtk_stack_switcher_drag_motion;
|
|
widget_class->drag_leave = gtk_stack_switcher_drag_leave;
|
|
/**
|
|
* 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_enum ("icon-size",
|
|
P_("Icon Size"),
|
|
P_("Symbolic size to use for named icon"),
|
|
GTK_TYPE_ICON_SIZE,
|
|
GTK_ICON_SIZE_INHERIT,
|
|
G_PARAM_EXPLICIT_NOTIFY | GTK_PARAM_READWRITE));
|
|
|
|
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));
|
|
|
|
gtk_widget_class_set_css_name (widget_class, "stackswitcher");
|
|
}
|
|
|
|
/**
|
|
* gtk_stack_switcher_new:
|
|
*
|
|
* Create a new #GtkStackSwitcher.
|
|
*
|
|
* Returns: a new #GtkStackSwitcher.
|
|
*
|
|
* Since: 3.10
|
|
*/
|
|
GtkWidget *
|
|
gtk_stack_switcher_new (void)
|
|
{
|
|
return g_object_new (GTK_TYPE_STACK_SWITCHER, NULL);
|
|
}
|