Mercurial > pidgin.yaz
diff src/gaim-disclosure.c @ 4553:d03fcb3f4be2
[gaim-migrate @ 4833]
We have a brand new file transfer dialog!
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Fri, 07 Feb 2003 20:55:20 +0000 |
parents | |
children | fa6395637e2c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gaim-disclosure.c Fri Feb 07 20:55:20 2003 +0000 @@ -0,0 +1,303 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Iain Holmes <iain@ximian.com> + * + * Copyright 2002 Iain Holmes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtktogglebutton.h> + +#include "gaim-disclosure.h" + +#ifdef ENABLE_NLS +# include <libintl.h> +# define _(x) gettext(x) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define N_(String) (String) +# define _(x) (x) +#endif + +static GtkCheckButtonClass *parent_class = NULL; + +struct _GaimDisclosurePrivate { + GtkWidget *container; + char *shown; + char *hidden; + + guint32 expand_id; + GtkExpanderStyle style; + + int expander_size; + int direction; +}; + +static void +finalize (GObject *object) +{ + GaimDisclosure *disclosure; + + disclosure = GAIM_DISCLOSURE (object); + if (disclosure->priv == NULL) { + return; + } + + g_free (disclosure->priv->hidden); + g_free (disclosure->priv->shown); + + if (disclosure->priv->container != NULL) { + g_object_unref (G_OBJECT (disclosure->priv->container)); + } + + g_free (disclosure->priv); + disclosure->priv = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +get_x_y (GaimDisclosure *disclosure, + int *x, + int *y, + GtkStateType *state_type) +{ + GtkCheckButton *check_button; + int indicator_size = 0; + int focus_width; + int focus_pad; + gboolean interior_focus; + GtkWidget *widget = GTK_WIDGET (disclosure); + GtkBin *bin = GTK_BIN (disclosure); + int width; + + if (GTK_WIDGET_VISIBLE (disclosure) && + GTK_WIDGET_MAPPED (disclosure)) { + check_button = GTK_CHECK_BUTTON (disclosure); + + gtk_widget_style_get (widget, + "interior_focus", &interior_focus, + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, + NULL); + + *state_type = GTK_WIDGET_STATE (widget); + if ((*state_type != GTK_STATE_NORMAL) && + (*state_type != GTK_STATE_PRELIGHT)) { + *state_type = GTK_STATE_NORMAL; + } + + if (bin->child) { + width = bin->child->allocation.x - widget->allocation.x - (2 * GTK_CONTAINER (widget)->border_width); + } else { + width = widget->allocation.width; + } + + *x = widget->allocation.x + (width) / 2; + *y = widget->allocation.y + widget->allocation.height / 2; + + if (interior_focus == FALSE) { + *x += focus_width + focus_pad; + } + + *state_type = GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE ? GTK_STATE_NORMAL : GTK_WIDGET_STATE (widget); + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) { + *x = widget->allocation.x + widget->allocation.width - (indicator_size + *x - widget->allocation.x); + } + } else { + *x = 0; + *y = 0; + *state_type = GTK_STATE_NORMAL; + } +} + +static gboolean +expand_collapse_timeout (gpointer data) +{ + GtkWidget *widget = data; + GaimDisclosure *disclosure = data; + GtkStateType state_type; + int x, y; + + gdk_window_invalidate_rect (widget->window, &widget->allocation, TRUE); + get_x_y (disclosure, &x, &y, &state_type); + + gtk_paint_expander (widget->style, + widget->window, + state_type, + &widget->allocation, + widget, + "disclosure", + x, y, + disclosure->priv->style); + + disclosure->priv->style += disclosure->priv->direction; + if ((int) disclosure->priv->style > (int) GTK_EXPANDER_EXPANDED) { + disclosure->priv->style = GTK_EXPANDER_EXPANDED; + + if (disclosure->priv->container != NULL) { + gtk_widget_show (disclosure->priv->container); + } + + g_object_set (G_OBJECT (disclosure), + "label", disclosure->priv->hidden, + NULL); + return FALSE; + } else if ((int) disclosure->priv->style < (int) GTK_EXPANDER_COLLAPSED) { + disclosure->priv->style = GTK_EXPANDER_COLLAPSED; + + if (disclosure->priv->container != NULL) { + gtk_widget_hide (disclosure->priv->container); + } + + g_object_set (G_OBJECT (disclosure), + "label", disclosure->priv->shown, + NULL); + + return FALSE; + } else { + return TRUE; + } +} + +static void +do_animation (GaimDisclosure *disclosure, + gboolean opening) +{ + if (disclosure->priv->expand_id > 0) { + g_source_remove(disclosure->priv->expand_id); + } + + disclosure->priv->direction = opening ? 1 : -1; + disclosure->priv->expand_id = g_timeout_add (50, expand_collapse_timeout, disclosure); +} + +static void +toggled (GtkToggleButton *tb) +{ + GaimDisclosure *disclosure; + + disclosure = GAIM_DISCLOSURE (tb); + do_animation (disclosure, gtk_toggle_button_get_active (tb)); + + if (disclosure->priv->container == NULL) { + return; + } +} + +static void +draw_indicator (GtkCheckButton *check, + GdkRectangle *area) +{ + GtkWidget *widget = GTK_WIDGET (check); + GaimDisclosure *disclosure = GAIM_DISCLOSURE (check); + GtkStateType state_type; + int x, y; + + get_x_y (disclosure, &x, &y, &state_type); + gtk_paint_expander (widget->style, + widget->window, + state_type, + area, + widget, + "treeview", + x, y, + disclosure->priv->style); +} + +static void +class_init (GaimDisclosureClass *klass) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkCheckButtonClass *button_class; + GtkToggleButtonClass *toggle_class; + + object_class = G_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + button_class = GTK_CHECK_BUTTON_CLASS (klass); + toggle_class = GTK_TOGGLE_BUTTON_CLASS (klass); + + toggle_class->toggled = toggled; + button_class->draw_indicator = draw_indicator; + + object_class->finalize = finalize; + + parent_class = g_type_class_peek_parent (klass); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("expander_size", + _("Expander Size"), + _("Size of the expander arrow"), + 0, G_MAXINT, + 10, G_PARAM_READABLE)); +} + +static void +init (GaimDisclosure *disclosure) +{ + disclosure->priv = g_new0 (GaimDisclosurePrivate, 1); + disclosure->priv->expander_size = 10; +} + +GType +gaim_disclosure_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + GTypeInfo info = { + sizeof (GaimDisclosureClass), + NULL, NULL, (GClassInitFunc) class_init, NULL, NULL, + sizeof (GaimDisclosure), 0, (GInstanceInitFunc) init + }; + + type = g_type_register_static (GTK_TYPE_CHECK_BUTTON, "GaimDisclosure", &info, 0); + } + + return type; +} + +GtkWidget * +gaim_disclosure_new (const char *shown, + const char *hidden) +{ + GaimDisclosure *disclosure; + + disclosure = g_object_new (gaim_disclosure_get_type (), "label", shown, NULL); + + disclosure->priv->shown = g_strdup (shown); + disclosure->priv->hidden = g_strdup (hidden); + return GTK_WIDGET (disclosure); +} + +void +gaim_disclosure_set_container (GaimDisclosure *disclosure, + GtkWidget *container) +{ + g_object_ref (G_OBJECT (container)); + disclosure->priv->container = container; +}