Fri, 18 Apr 2003 02:28:06 +0000
[gaim-migrate @ 5524]
1) Added neat little protocol icons next to the set away message menu when
you have more than one account signed on. I basically just copied
Nathan's code, so it should be ok.
2) Changed the horizontal rules in the away message menu so they show up
for me. This is how horizontal rules are done in other menus, I'm
not sure why the away message menu was different.
3) Moved 2 gtkish functions from util.c to gtkutils.c. Earlier I used one
of these functions, and then earlier, but not as early, I realized that
gtkutils.c existed, so I put 2 and 2 together and realized you were
probably flying somewhere.
Well then, let's put another shrimp on the barbi'!
| 4553 | 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ |
| 2 | /* | |
| 3 | * Authors: Iain Holmes <iain@ximian.com> | |
| 4 | * | |
| 5 | * Copyright 2002 Iain Holmes | |
| 6 | * | |
| 7 | * This program is free software; you can redistribute it and/or modify | |
| 8 | * it under the terms of the GNU General Public License as published by | |
| 9 | * the Free Software Foundation; either version 2 of the License, or | |
| 10 | * (at your option) any later version. | |
| 11 | * | |
| 12 | * This program is distributed in the hope that it will be useful, | |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | * GNU General Public License for more details. | |
| 16 | * | |
| 17 | * You should have received a copy of the GNU General Public License | |
| 18 | * along with this program; if not, write to the Free Software | |
| 19 | * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. | |
| 20 | * | |
| 21 | */ | |
| 22 | ||
| 23 | #ifdef HAVE_CONFIG_H | |
| 24 | #include <config.h> | |
| 25 | #endif | |
| 26 | ||
| 27 | #include <gtk/gtktogglebutton.h> | |
| 28 | ||
| 29 | #include "gaim-disclosure.h" | |
| 30 | ||
| 31 | #ifdef ENABLE_NLS | |
| 32 | # include <libintl.h> | |
| 33 | # define _(x) gettext(x) | |
| 34 | # ifdef gettext_noop | |
| 35 | # define N_(String) gettext_noop (String) | |
| 36 | # else | |
| 37 | # define N_(String) (String) | |
| 38 | # endif | |
| 39 | #else | |
| 40 | # define N_(String) (String) | |
| 41 | # define _(x) (x) | |
| 42 | #endif | |
| 43 | ||
| 44 | static GtkCheckButtonClass *parent_class = NULL; | |
| 45 | ||
| 46 | struct _GaimDisclosurePrivate { | |
| 47 | GtkWidget *container; | |
| 48 | char *shown; | |
| 49 | char *hidden; | |
| 50 | ||
| 51 | guint32 expand_id; | |
| 52 | GtkExpanderStyle style; | |
| 53 | ||
| 54 | int expander_size; | |
| 55 | int direction; | |
| 56 | }; | |
| 57 | ||
| 58 | static void | |
| 59 | finalize (GObject *object) | |
| 60 | { | |
| 61 | GaimDisclosure *disclosure; | |
| 62 | ||
| 63 | disclosure = GAIM_DISCLOSURE (object); | |
| 64 | if (disclosure->priv == NULL) { | |
| 65 | return; | |
| 66 | } | |
| 67 | ||
| 68 | g_free (disclosure->priv->hidden); | |
| 69 | g_free (disclosure->priv->shown); | |
| 70 | ||
| 71 | if (disclosure->priv->container != NULL) { | |
| 72 | g_object_unref (G_OBJECT (disclosure->priv->container)); | |
| 73 | } | |
| 74 | ||
| 75 | g_free (disclosure->priv); | |
| 76 | disclosure->priv = NULL; | |
| 77 | ||
| 78 | G_OBJECT_CLASS (parent_class)->finalize (object); | |
| 79 | } | |
| 80 | ||
| 81 | static void | |
| 82 | get_x_y (GaimDisclosure *disclosure, | |
| 83 | int *x, | |
| 84 | int *y, | |
| 85 | GtkStateType *state_type) | |
| 86 | { | |
| 87 | GtkCheckButton *check_button; | |
| 88 | int indicator_size = 0; | |
| 89 | int focus_width; | |
| 90 | int focus_pad; | |
| 91 | gboolean interior_focus; | |
| 92 | GtkWidget *widget = GTK_WIDGET (disclosure); | |
| 93 | GtkBin *bin = GTK_BIN (disclosure); | |
| 94 | int width; | |
| 95 | ||
| 96 | if (GTK_WIDGET_VISIBLE (disclosure) && | |
| 97 | GTK_WIDGET_MAPPED (disclosure)) { | |
| 98 | check_button = GTK_CHECK_BUTTON (disclosure); | |
| 99 | ||
| 100 | gtk_widget_style_get (widget, | |
| 101 | "interior_focus", &interior_focus, | |
| 102 | "focus-line-width", &focus_width, | |
| 103 | "focus-padding", &focus_pad, | |
| 104 | NULL); | |
| 105 | ||
| 106 | *state_type = GTK_WIDGET_STATE (widget); | |
| 107 | if ((*state_type != GTK_STATE_NORMAL) && | |
| 108 | (*state_type != GTK_STATE_PRELIGHT)) { | |
| 109 | *state_type = GTK_STATE_NORMAL; | |
| 110 | } | |
| 111 | ||
| 112 | if (bin->child) { | |
| 113 | width = bin->child->allocation.x - widget->allocation.x - (2 * GTK_CONTAINER (widget)->border_width); | |
| 114 | } else { | |
| 115 | width = widget->allocation.width; | |
| 116 | } | |
| 117 | ||
| 118 | *x = widget->allocation.x + (width) / 2; | |
| 119 | *y = widget->allocation.y + widget->allocation.height / 2; | |
| 120 | ||
| 121 | if (interior_focus == FALSE) { | |
| 122 | *x += focus_width + focus_pad; | |
| 123 | } | |
| 124 | ||
| 125 | *state_type = GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE ? GTK_STATE_NORMAL : GTK_WIDGET_STATE (widget); | |
| 126 | ||
| 127 | if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) { | |
| 128 | *x = widget->allocation.x + widget->allocation.width - (indicator_size + *x - widget->allocation.x); | |
| 129 | } | |
| 130 | } else { | |
| 131 | *x = 0; | |
| 132 | *y = 0; | |
| 133 | *state_type = GTK_STATE_NORMAL; | |
| 134 | } | |
| 135 | } | |
| 136 | ||
| 137 | static gboolean | |
| 138 | expand_collapse_timeout (gpointer data) | |
| 139 | { | |
| 140 | GtkWidget *widget = data; | |
| 141 | GaimDisclosure *disclosure = data; | |
| 142 | GtkStateType state_type; | |
| 143 | int x, y; | |
| 144 | ||
| 145 | gdk_window_invalidate_rect (widget->window, &widget->allocation, TRUE); | |
| 146 | get_x_y (disclosure, &x, &y, &state_type); | |
| 147 | ||
| 148 | gtk_paint_expander (widget->style, | |
| 149 | widget->window, | |
| 150 | state_type, | |
| 151 | &widget->allocation, | |
| 152 | widget, | |
| 153 | "disclosure", | |
| 154 | x, y, | |
| 155 | disclosure->priv->style); | |
| 156 | ||
| 157 | disclosure->priv->style += disclosure->priv->direction; | |
| 158 | if ((int) disclosure->priv->style > (int) GTK_EXPANDER_EXPANDED) { | |
| 159 | disclosure->priv->style = GTK_EXPANDER_EXPANDED; | |
| 160 | ||
| 161 | if (disclosure->priv->container != NULL) { | |
| 162 | gtk_widget_show (disclosure->priv->container); | |
| 163 | } | |
| 164 | ||
| 165 | g_object_set (G_OBJECT (disclosure), | |
| 166 | "label", disclosure->priv->hidden, | |
| 167 | NULL); | |
| 168 | return FALSE; | |
| 169 | } else if ((int) disclosure->priv->style < (int) GTK_EXPANDER_COLLAPSED) { | |
| 170 | disclosure->priv->style = GTK_EXPANDER_COLLAPSED; | |
| 171 | ||
| 172 | if (disclosure->priv->container != NULL) { | |
| 173 | gtk_widget_hide (disclosure->priv->container); | |
| 174 | } | |
| 175 | ||
| 176 | g_object_set (G_OBJECT (disclosure), | |
| 177 | "label", disclosure->priv->shown, | |
| 178 | NULL); | |
| 179 | ||
| 180 | return FALSE; | |
| 181 | } else { | |
| 182 | return TRUE; | |
| 183 | } | |
| 184 | } | |
| 185 | ||
| 186 | static void | |
| 187 | do_animation (GaimDisclosure *disclosure, | |
| 188 | gboolean opening) | |
| 189 | { | |
| 190 | if (disclosure->priv->expand_id > 0) { | |
| 191 | g_source_remove(disclosure->priv->expand_id); | |
| 192 | } | |
| 193 | ||
| 194 | disclosure->priv->direction = opening ? 1 : -1; | |
| 195 | disclosure->priv->expand_id = g_timeout_add (50, expand_collapse_timeout, disclosure); | |
| 196 | } | |
| 197 | ||
| 198 | static void | |
| 199 | toggled (GtkToggleButton *tb) | |
| 200 | { | |
| 201 | GaimDisclosure *disclosure; | |
| 202 | ||
| 203 | disclosure = GAIM_DISCLOSURE (tb); | |
| 204 | do_animation (disclosure, gtk_toggle_button_get_active (tb)); | |
| 205 | ||
| 206 | if (disclosure->priv->container == NULL) { | |
| 207 | return; | |
| 208 | } | |
| 209 | } | |
| 210 | ||
| 211 | static void | |
| 212 | draw_indicator (GtkCheckButton *check, | |
| 213 | GdkRectangle *area) | |
| 214 | { | |
| 215 | GtkWidget *widget = GTK_WIDGET (check); | |
| 216 | GaimDisclosure *disclosure = GAIM_DISCLOSURE (check); | |
| 217 | GtkStateType state_type; | |
| 218 | int x, y; | |
| 219 | ||
| 220 | get_x_y (disclosure, &x, &y, &state_type); | |
| 221 | gtk_paint_expander (widget->style, | |
| 222 | widget->window, | |
| 223 | state_type, | |
| 224 | area, | |
| 225 | widget, | |
| 226 | "treeview", | |
| 227 | x, y, | |
| 228 | disclosure->priv->style); | |
| 229 | } | |
| 230 | ||
| 231 | static void | |
| 232 | class_init (GaimDisclosureClass *klass) | |
| 233 | { | |
| 234 | GObjectClass *object_class; | |
| 235 | GtkWidgetClass *widget_class; | |
| 236 | GtkCheckButtonClass *button_class; | |
| 237 | GtkToggleButtonClass *toggle_class; | |
| 238 | ||
| 239 | object_class = G_OBJECT_CLASS (klass); | |
| 240 | widget_class = GTK_WIDGET_CLASS (klass); | |
| 241 | button_class = GTK_CHECK_BUTTON_CLASS (klass); | |
| 242 | toggle_class = GTK_TOGGLE_BUTTON_CLASS (klass); | |
| 243 | ||
| 244 | toggle_class->toggled = toggled; | |
| 245 | button_class->draw_indicator = draw_indicator; | |
| 246 | ||
| 247 | object_class->finalize = finalize; | |
| 248 | ||
| 249 | parent_class = g_type_class_peek_parent (klass); | |
| 250 | ||
| 251 | gtk_widget_class_install_style_property (widget_class, | |
| 252 | g_param_spec_int ("expander_size", | |
| 253 | _("Expander Size"), | |
| 254 | _("Size of the expander arrow"), | |
| 255 | 0, G_MAXINT, | |
| 256 | 10, G_PARAM_READABLE)); | |
| 257 | } | |
| 258 | ||
| 259 | static void | |
| 260 | init (GaimDisclosure *disclosure) | |
| 261 | { | |
| 262 | disclosure->priv = g_new0 (GaimDisclosurePrivate, 1); | |
| 263 | disclosure->priv->expander_size = 10; | |
| 264 | } | |
| 265 | ||
| 266 | GType | |
| 267 | gaim_disclosure_get_type (void) | |
| 268 | { | |
| 269 | static GType type = 0; | |
| 270 | ||
| 271 | if (type == 0) { | |
| 272 | GTypeInfo info = { | |
| 273 | sizeof (GaimDisclosureClass), | |
| 274 | NULL, NULL, (GClassInitFunc) class_init, NULL, NULL, | |
| 275 | sizeof (GaimDisclosure), 0, (GInstanceInitFunc) init | |
| 276 | }; | |
| 277 | ||
| 278 | type = g_type_register_static (GTK_TYPE_CHECK_BUTTON, "GaimDisclosure", &info, 0); | |
| 279 | } | |
| 280 | ||
| 281 | return type; | |
| 282 | } | |
| 283 | ||
| 284 | GtkWidget * | |
| 285 | gaim_disclosure_new (const char *shown, | |
| 286 | const char *hidden) | |
| 287 | { | |
| 288 | GaimDisclosure *disclosure; | |
| 289 | ||
| 290 | disclosure = g_object_new (gaim_disclosure_get_type (), "label", shown, NULL); | |
| 291 | ||
| 292 | disclosure->priv->shown = g_strdup (shown); | |
| 293 | disclosure->priv->hidden = g_strdup (hidden); | |
| 294 | return GTK_WIDGET (disclosure); | |
| 295 | } | |
| 296 | ||
| 297 | void | |
| 298 | gaim_disclosure_set_container (GaimDisclosure *disclosure, | |
| 299 | GtkWidget *container) | |
| 300 | { | |
| 301 | g_object_ref (G_OBJECT (container)); | |
| 302 | disclosure->priv->container = container; | |
| 303 | } |