Mercurial > pidgin.yaz
annotate plugins/ticker/gtkticker.c @ 12744:fcd9477e4476
[gaim-migrate @ 15091]
" Adds an emblem to a buddy if they have a queued message
(hidden conversation). In the large buddy list it is
added in the northwest corner, sliding the existing
northwest emblem (if specified) to the northeast
position and discarding the northeast emblem. In the
small buddy list, the emblem is added to the southeast.
Attached is a patch and an emblem image to be dropped
in pixmaps/status/default/. The emblem image is a
scaled down version of the send-im.png image." -- Casey Harkins
as I asked for this patch, and since there don't seem to be objections to
it (yet), I'm going ahead and applying it.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Fri, 06 Jan 2006 04:46:00 +0000 |
parents | e856f985a0b9 |
children |
rev | line source |
---|---|
3391 | 1 /* GTK - The GIMP Toolkit |
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald | |
3 * | |
4 * This library is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Library General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2 of the License, or (at your option) any later version. | |
8 * | |
9 * This library is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Library General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Library General Public | |
15 * License along with this library; if not, write to the | |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 * Boston, MA 02111-1307, USA. | |
18 */ | |
19 | |
20 /* | |
21 * GtkTicker Copyright 2000 Syd Logan | |
22 */ | |
23 | |
24 #include "gtkticker.h" | |
25 #include <gtk/gtk.h> | |
26 | |
27 static void gtk_ticker_compute_offsets (GtkTicker *ticker); | |
28 static void gtk_ticker_class_init (GtkTickerClass *klass); | |
29 static void gtk_ticker_init (GtkTicker *ticker); | |
30 static void gtk_ticker_map (GtkWidget *widget); | |
31 static void gtk_ticker_realize (GtkWidget *widget); | |
32 static void gtk_ticker_size_request (GtkWidget *widget, | |
5170 | 33 GtkRequisition *requisition); |
3391 | 34 static void gtk_ticker_size_allocate (GtkWidget *widget, |
5170 | 35 GtkAllocation *allocation); |
3391 | 36 static void gtk_ticker_add_real (GtkContainer *container, |
5170 | 37 GtkWidget *widget); |
3391 | 38 static void gtk_ticker_remove_real (GtkContainer *container, |
5170 | 39 GtkWidget *widget); |
3391 | 40 static void gtk_ticker_forall (GtkContainer *container, |
5170 | 41 gboolean include_internals, |
42 GtkCallback callback, | |
43 gpointer callback_data); | |
3391 | 44 static GtkType gtk_ticker_child_type (GtkContainer *container); |
45 | |
46 | |
47 static GtkContainerClass *parent_class = NULL; | |
48 | |
49 | |
5170 | 50 GType gtk_ticker_get_type (void) |
3391 | 51 { |
5170 | 52 static GType ticker_type = 0; |
3391 | 53 |
6560 | 54 ticker_type = g_type_from_name("GtkTicker"); |
55 | |
5170 | 56 if (!ticker_type) |
57 { | |
58 static const GTypeInfo ticker_info = | |
59 { | |
60 sizeof(GtkTickerClass), | |
61 NULL, | |
62 NULL, | |
63 (GClassInitFunc) gtk_ticker_class_init, | |
64 NULL, | |
65 NULL, | |
66 sizeof(GtkTicker), | |
67 0, | |
12600
e856f985a0b9
[gaim-migrate @ 14934]
Richard Laager <rlaager@wiktel.com>
parents:
6560
diff
changeset
|
68 (GInstanceInitFunc) gtk_ticker_init, |
e856f985a0b9
[gaim-migrate @ 14934]
Richard Laager <rlaager@wiktel.com>
parents:
6560
diff
changeset
|
69 NULL |
5170 | 70 }; |
3391 | 71 |
5170 | 72 ticker_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTicker", |
73 &ticker_info, 0); | |
74 } | |
3391 | 75 |
6560 | 76 /* kludge to re-initialise the class if it's already registered */ |
77 else if (parent_class == NULL) { | |
78 gtk_ticker_class_init((GtkTickerClass *)g_type_class_peek(ticker_type)); | |
79 } | |
80 | |
5170 | 81 return ticker_type; |
82 } | |
83 | |
84 static void gtk_ticker_finalize(GObject *object) { | |
85 gtk_ticker_stop_scroll(GTK_TICKER(object)); | |
86 | |
87 G_OBJECT_CLASS(parent_class)->finalize(object); | |
3391 | 88 } |
89 | |
5170 | 90 static void gtk_ticker_class_init (GtkTickerClass *class) |
3391 | 91 { |
5170 | 92 GObjectClass *gobject_class; |
93 GtkWidgetClass *widget_class; | |
94 GtkContainerClass *container_class; | |
3391 | 95 |
5170 | 96 gobject_class = (GObjectClass*) class; |
97 widget_class = (GtkWidgetClass*) class; | |
98 container_class = (GtkContainerClass*) class; | |
99 | |
100 parent_class = gtk_type_class (GTK_TYPE_CONTAINER); | |
3391 | 101 |
5170 | 102 gobject_class->finalize = gtk_ticker_finalize; |
3391 | 103 |
5170 | 104 widget_class->map = gtk_ticker_map; |
105 widget_class->realize = gtk_ticker_realize; | |
106 widget_class->size_request = gtk_ticker_size_request; | |
107 widget_class->size_allocate = gtk_ticker_size_allocate; | |
3391 | 108 |
5170 | 109 container_class->add = gtk_ticker_add_real; |
110 container_class->remove = gtk_ticker_remove_real; | |
111 container_class->forall = gtk_ticker_forall; | |
112 container_class->child_type = gtk_ticker_child_type; | |
3391 | 113 } |
114 | |
5170 | 115 static GtkType gtk_ticker_child_type (GtkContainer *container) |
3391 | 116 { |
5170 | 117 return GTK_TYPE_WIDGET; |
3391 | 118 } |
119 | |
5170 | 120 static void gtk_ticker_init (GtkTicker *ticker) |
3391 | 121 { |
5170 | 122 GTK_WIDGET_UNSET_FLAGS (ticker, GTK_NO_WINDOW); |
3391 | 123 |
5170 | 124 ticker->interval = (guint) 200; |
125 ticker->scootch = (guint) 2; | |
126 ticker->children = NULL; | |
127 ticker->timer = 0; | |
128 ticker->dirty = TRUE; | |
3391 | 129 } |
130 | |
5170 | 131 GtkWidget* gtk_ticker_new (void) |
3391 | 132 { |
4635 | 133 return GTK_WIDGET(g_object_new(GTK_TYPE_TICKER, NULL)); |
3391 | 134 } |
135 | |
5170 | 136 static void gtk_ticker_put (GtkTicker *ticker, GtkWidget *widget) |
3391 | 137 { |
5170 | 138 GtkTickerChild *child_info; |
3391 | 139 |
5170 | 140 g_return_if_fail (ticker != NULL); |
141 g_return_if_fail (GTK_IS_TICKER (ticker)); | |
142 g_return_if_fail (widget != NULL); | |
3391 | 143 |
5170 | 144 child_info = g_new(GtkTickerChild, 1); |
145 child_info->widget = widget; | |
146 child_info->x = 0; | |
3391 | 147 |
5170 | 148 gtk_widget_set_parent(widget, GTK_WIDGET (ticker)); |
3391 | 149 |
5170 | 150 ticker->children = g_list_append (ticker->children, child_info); |
3391 | 151 |
5170 | 152 if (GTK_WIDGET_REALIZED (ticker)) |
153 gtk_widget_realize (widget); | |
3391 | 154 |
5170 | 155 if (GTK_WIDGET_VISIBLE (ticker) && GTK_WIDGET_VISIBLE (widget)) |
156 { | |
157 if (GTK_WIDGET_MAPPED (ticker)) | |
158 gtk_widget_map (widget); | |
159 | |
160 gtk_widget_queue_resize (GTK_WIDGET (ticker)); | |
161 } | |
3391 | 162 } |
163 | |
5170 | 164 void gtk_ticker_set_interval (GtkTicker *ticker, gint interval) |
3391 | 165 { |
5170 | 166 g_return_if_fail (ticker != NULL); |
167 g_return_if_fail (GTK_IS_TICKER (ticker)); | |
3391 | 168 |
5170 | 169 if ( interval < 0 ) |
170 interval = 200; | |
171 ticker->interval = interval; | |
3391 | 172 } |
173 | |
5170 | 174 guint gtk_ticker_get_interval (GtkTicker *ticker) |
3391 | 175 { |
5170 | 176 g_return_val_if_fail (ticker != NULL, -1); |
177 g_return_val_if_fail (GTK_IS_TICKER (ticker), -1); | |
3391 | 178 |
5170 | 179 return ticker->interval; |
3391 | 180 } |
181 | |
5170 | 182 void gtk_ticker_set_scootch (GtkTicker *ticker, gint scootch) |
3391 | 183 { |
5170 | 184 g_return_if_fail (ticker != NULL); |
185 g_return_if_fail (GTK_IS_TICKER (ticker)); | |
3391 | 186 |
5170 | 187 if (scootch <= 0) |
188 scootch = 2; | |
189 ticker->scootch = scootch; | |
190 ticker->dirty = TRUE; | |
3391 | 191 } |
192 | |
5170 | 193 guint gtk_ticker_get_scootch (GtkTicker *ticker ) |
3391 | 194 { |
5170 | 195 g_return_val_if_fail (ticker != NULL, -1); |
196 g_return_val_if_fail (GTK_IS_TICKER (ticker), -1); | |
3391 | 197 |
5170 | 198 return ticker->scootch; |
3391 | 199 } |
200 | |
5170 | 201 void gtk_ticker_set_spacing (GtkTicker *ticker, gint spacing ) |
3391 | 202 { |
5170 | 203 g_return_if_fail (ticker != NULL); |
204 g_return_if_fail (GTK_IS_TICKER (ticker)); | |
3391 | 205 |
5170 | 206 if ( spacing < 0 ) |
207 spacing = 0; | |
208 ticker->spacing = spacing; | |
209 ticker->dirty = TRUE; | |
3391 | 210 } |
211 | |
5170 | 212 static int ticker_timeout(gpointer data) |
3391 | 213 { |
214 GtkTicker *ticker = (GtkTicker *) data; | |
215 | |
5170 | 216 if (GTK_WIDGET_VISIBLE (ticker)) |
217 gtk_widget_queue_resize (GTK_WIDGET (ticker)); | |
3391 | 218 |
219 return( TRUE ); | |
220 } | |
221 | |
5170 | 222 void gtk_ticker_start_scroll(GtkTicker *ticker) |
3391 | 223 { |
5170 | 224 g_return_if_fail (ticker != NULL); |
225 g_return_if_fail (GTK_IS_TICKER (ticker)); | |
3391 | 226 if ( ticker->timer != 0 ) |
227 return; | |
4168 | 228 ticker->timer = g_timeout_add(ticker->interval, ticker_timeout, ticker); |
3391 | 229 } |
230 | |
5170 | 231 void gtk_ticker_stop_scroll(GtkTicker *ticker) |
3391 | 232 { |
5170 | 233 g_return_if_fail (ticker != NULL); |
234 g_return_if_fail (GTK_IS_TICKER (ticker)); | |
3391 | 235 if ( ticker->timer == 0 ) |
236 return; | |
4168 | 237 g_source_remove(ticker->timer); |
3391 | 238 ticker->timer = 0; |
239 } | |
240 | |
5170 | 241 guint gtk_ticker_get_spacing (GtkTicker *ticker ) |
3391 | 242 { |
5170 | 243 g_return_val_if_fail (ticker != NULL, -1); |
244 g_return_val_if_fail (GTK_IS_TICKER (ticker), -1); | |
3391 | 245 |
5170 | 246 return ticker->spacing; |
3391 | 247 } |
248 | |
5170 | 249 static void gtk_ticker_map (GtkWidget *widget) |
3391 | 250 { |
5170 | 251 GtkTicker *ticker; |
252 GtkTickerChild *child; | |
253 GList *children; | |
3391 | 254 |
5170 | 255 g_return_if_fail (widget != NULL); |
256 g_return_if_fail (GTK_IS_TICKER (widget)); | |
3391 | 257 |
5170 | 258 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); |
259 ticker = GTK_TICKER (widget); | |
3391 | 260 |
5170 | 261 children = ticker->children; |
262 while (children) | |
263 { | |
264 child = children->data; | |
265 children = children->next; | |
3391 | 266 |
5170 | 267 if (GTK_WIDGET_VISIBLE (child->widget) && |
268 !GTK_WIDGET_MAPPED (child->widget)) | |
269 gtk_widget_map (child->widget); | |
270 } | |
3391 | 271 |
5170 | 272 gdk_window_show (widget->window); |
3391 | 273 } |
274 | |
5170 | 275 static void gtk_ticker_realize (GtkWidget *widget) |
3391 | 276 { |
5170 | 277 GdkWindowAttr attributes; |
278 gint attributes_mask; | |
3391 | 279 |
5170 | 280 g_return_if_fail (widget != NULL); |
281 g_return_if_fail (GTK_IS_TICKER (widget)); | |
3391 | 282 |
5170 | 283 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); |
3391 | 284 |
5170 | 285 attributes.window_type = GDK_WINDOW_CHILD; |
286 attributes.x = widget->allocation.x; | |
287 attributes.y = widget->allocation.y; | |
288 attributes.width = widget->allocation.width; | |
289 attributes.height = widget->allocation.height; | |
290 attributes.wclass = GDK_INPUT_OUTPUT; | |
291 attributes.visual = gtk_widget_get_visual (widget); | |
292 attributes.colormap = gtk_widget_get_colormap (widget); | |
293 attributes.event_mask = gtk_widget_get_events (widget); | |
294 attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK; | |
3391 | 295 |
5170 | 296 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; |
3391 | 297 |
5170 | 298 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), |
299 &attributes, attributes_mask); | |
300 gdk_window_set_user_data (widget->window, widget); | |
3391 | 301 |
5170 | 302 widget->style = gtk_style_attach (widget->style, widget->window); |
303 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); | |
3391 | 304 } |
305 | |
5170 | 306 static void gtk_ticker_size_request (GtkWidget *widget, GtkRequisition *requisition) |
3391 | 307 { |
5170 | 308 GtkTicker *ticker; |
309 GtkTickerChild *child; | |
310 GList *children; | |
311 GtkRequisition child_requisition; | |
3391 | 312 |
5170 | 313 g_return_if_fail (widget != NULL); |
314 g_return_if_fail (GTK_IS_TICKER (widget)); | |
315 g_return_if_fail (requisition != NULL); | |
3391 | 316 |
5170 | 317 ticker = GTK_TICKER (widget); |
318 requisition->width = 0; | |
319 requisition->height = 0; | |
3391 | 320 |
5170 | 321 children = ticker->children; |
322 while (children) | |
323 { | |
324 child = children->data; | |
325 children = children->next; | |
3391 | 326 |
5170 | 327 if (GTK_WIDGET_VISIBLE (child->widget)) |
328 { | |
329 gtk_widget_size_request (child->widget, &child_requisition); | |
3391 | 330 |
5170 | 331 requisition->height = MAX (requisition->height, |
332 child_requisition.height); | |
333 requisition->width += child_requisition.width + ticker->spacing; | |
334 } | |
3391 | 335 } |
5170 | 336 if ( requisition->width > ticker->spacing ) |
337 requisition->width -= ticker->spacing; | |
3391 | 338 |
5170 | 339 requisition->height += GTK_CONTAINER (ticker)->border_width * 2; |
340 requisition->width += GTK_CONTAINER (ticker)->border_width * 2; | |
3391 | 341 } |
342 | |
5170 | 343 static void gtk_ticker_compute_offsets (GtkTicker *ticker) |
3391 | 344 { |
5170 | 345 GtkTickerChild *child; |
346 GtkRequisition child_requisition; | |
347 GList *children; | |
348 guint16 border_width; | |
3391 | 349 |
5170 | 350 g_return_if_fail (ticker != NULL); |
351 g_return_if_fail (GTK_IS_TICKER(ticker)); | |
3391 | 352 |
5170 | 353 border_width = GTK_CONTAINER (ticker)->border_width; |
3391 | 354 |
5170 | 355 ticker->width = GTK_WIDGET(ticker)->allocation.width; |
356 ticker->total = 0; | |
357 children = ticker->children; | |
358 while (children) { | |
359 child = children->data; | |
360 | |
361 child->x = 0; | |
362 if (GTK_WIDGET_VISIBLE (child->widget)) { | |
363 gtk_widget_get_child_requisition (child->widget, &child_requisition); | |
364 child->offset = ticker->total; | |
365 ticker->total += | |
366 child_requisition.width + border_width + ticker->spacing; | |
367 } | |
368 children = children->next; | |
369 } | |
370 ticker->dirty = FALSE; | |
3391 | 371 } |
372 | |
5170 | 373 static void gtk_ticker_size_allocate (GtkWidget *widget, |
374 GtkAllocation *allocation) | |
3391 | 375 { |
5170 | 376 GtkTicker *ticker; |
377 GtkTickerChild *child; | |
378 GtkAllocation child_allocation; | |
379 GtkRequisition child_requisition; | |
380 GList *children; | |
381 guint16 border_width; | |
382 | |
383 g_return_if_fail (widget != NULL); | |
384 g_return_if_fail (GTK_IS_TICKER(widget)); | |
385 g_return_if_fail (allocation != NULL); | |
386 | |
387 ticker = GTK_TICKER (widget); | |
3391 | 388 |
5170 | 389 if ( GTK_WIDGET(ticker)->allocation.width != ticker->width ) |
390 ticker->dirty = TRUE; | |
3391 | 391 |
5170 | 392 if ( ticker->dirty == TRUE ) { |
393 gtk_ticker_compute_offsets( ticker ); | |
394 } | |
3391 | 395 |
5170 | 396 widget->allocation = *allocation; |
397 if (GTK_WIDGET_REALIZED (widget)) | |
398 gdk_window_move_resize (widget->window, | |
399 allocation->x, | |
400 allocation->y, | |
401 allocation->width, | |
402 allocation->height); | |
3391 | 403 |
5170 | 404 border_width = GTK_CONTAINER (ticker)->border_width; |
3391 | 405 |
5170 | 406 children = ticker->children; |
407 while (children) | |
408 { | |
409 child = children->data; | |
410 child->x -= ticker->scootch; | |
3391 | 411 |
5170 | 412 if (GTK_WIDGET_VISIBLE (child->widget)) { |
413 gtk_widget_get_child_requisition (child->widget, &child_requisition); | |
414 child_allocation.width = child_requisition.width; | |
415 child_allocation.x = child->offset + border_width + child->x; | |
416 if ( ( child_allocation.x + child_allocation.width ) < GTK_WIDGET(ticker)->allocation.x ) { | |
417 if ( ticker->total >= GTK_WIDGET(ticker)->allocation.width ) { | |
418 child->x += GTK_WIDGET(ticker)->allocation.x + GTK_WIDGET(ticker)->allocation.width + ( ticker->total - ( GTK_WIDGET(ticker)->allocation.x + GTK_WIDGET(ticker)->allocation.width ) ); | |
419 } | |
420 else { | |
421 child->x += GTK_WIDGET(ticker)->allocation.x + GTK_WIDGET(ticker)->allocation.width; | |
422 } | |
423 } | |
424 child_allocation.y = border_width; | |
425 child_allocation.height = child_requisition.height; | |
426 gtk_widget_size_allocate (child->widget, &child_allocation); | |
3391 | 427 } |
5170 | 428 children = children->next; |
429 } | |
430 } | |
431 | |
432 void gtk_ticker_add(GtkTicker *ticker, GtkWidget *widget) | |
433 { | |
434 gtk_ticker_add_real( GTK_CONTAINER( ticker ), widget ); | |
435 ticker->dirty = TRUE; | |
436 } | |
437 | |
438 void gtk_ticker_remove(GtkTicker *ticker, GtkWidget *widget) | |
439 { | |
440 gtk_ticker_remove_real( GTK_CONTAINER( ticker ), widget ); | |
441 ticker->dirty = TRUE; | |
3391 | 442 } |
443 | |
5170 | 444 static void gtk_ticker_add_real(GtkContainer *container, GtkWidget *widget) |
3391 | 445 { |
5170 | 446 g_return_if_fail (container != NULL); |
447 g_return_if_fail (GTK_IS_TICKER (container)); | |
448 g_return_if_fail (widget != NULL); | |
3391 | 449 |
5170 | 450 gtk_ticker_put(GTK_TICKER (container), widget); |
3391 | 451 } |
452 | |
5170 | 453 static void gtk_ticker_remove_real(GtkContainer *container, GtkWidget *widget) |
3391 | 454 { |
5170 | 455 GtkTicker *ticker; |
456 GtkTickerChild *child; | |
457 GList *children; | |
3391 | 458 |
5170 | 459 g_return_if_fail (container != NULL); |
460 g_return_if_fail (GTK_IS_TICKER (container)); | |
461 g_return_if_fail (widget != NULL); | |
3391 | 462 |
5170 | 463 ticker = GTK_TICKER (container); |
3391 | 464 |
5170 | 465 children = ticker->children; |
466 while (children) | |
467 { | |
468 child = children->data; | |
3391 | 469 |
5170 | 470 if (child->widget == widget) |
471 { | |
472 gboolean was_visible = GTK_WIDGET_VISIBLE (widget); | |
473 | |
474 gtk_widget_unparent (widget); | |
3391 | 475 |
5170 | 476 ticker->children = g_list_remove_link (ticker->children, children); |
477 g_list_free (children); | |
478 g_free (child); | |
3391 | 479 |
5170 | 480 if (was_visible && GTK_WIDGET_VISIBLE (container)) |
481 gtk_widget_queue_resize (GTK_WIDGET (container)); | |
3391 | 482 |
5170 | 483 break; |
484 } | |
3391 | 485 |
5170 | 486 children = children->next; |
487 } | |
3391 | 488 } |
489 | |
5170 | 490 static void gtk_ticker_forall (GtkContainer *container, |
491 gboolean include_internals, | |
492 GtkCallback callback, | |
493 gpointer callback_data) | |
3391 | 494 { |
5170 | 495 GtkTicker *ticker; |
496 GtkTickerChild *child; | |
497 GList *children; | |
498 | |
499 g_return_if_fail (container != NULL); | |
500 g_return_if_fail (GTK_IS_TICKER (container)); | |
501 g_return_if_fail (callback != NULL); | |
3391 | 502 |
5170 | 503 ticker = GTK_TICKER (container); |
3391 | 504 |
5170 | 505 children = ticker->children; |
506 while (children) | |
507 { | |
508 child = children->data; | |
509 children = children->next; | |
3391 | 510 |
5170 | 511 (* callback) (child->widget, callback_data); |
512 } | |
3391 | 513 } |
5170 | 514 |