gnome-shell-3.6.3.1/src/st/st-icon.c

Location Tool Test ID Function Issue
st/st-icon.c:372:6 gcc deprecated-declarations st_icon_update_shadow_material 'clutter_texture_get_base_size' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:69)
  1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2 /*
  3  * st-icon.c: icon widget
  4  *
  5  * Copyright 2009, 2010 Intel Corporation.
  6  * Copyright 2010 Red Hat, Inc.
  7  *
  8  * This program is free software; you can redistribute it and/or modify it
  9  * under the terms and conditions of the GNU Lesser General Public License,
 10  * version 2.1, as published by the Free Software Foundation.
 11  *
 12  * This program is distributed in the hope it will be useful, but WITHOUT ANY
 13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 14  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 15  * more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public License
 18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
 19  */
 20 
 21 /**
 22  * SECTION:st-icon
 23  * @short_description: a simple styled icon actor
 24  *
 25  * #StIcon is a simple styled texture actor that displays an image from
 26  * a stylesheet.
 27  */
 28 
 29 #include "st-enum-types.h"
 30 #include "st-icon.h"
 31 #include "st-texture-cache.h"
 32 #include "st-private.h"
 33 
 34 enum
 35 {
 36   PROP_0,
 37 
 38   PROP_GICON,
 39   PROP_ICON_NAME,
 40   PROP_ICON_SIZE
 41 };
 42 
 43 G_DEFINE_TYPE (StIcon, st_icon, ST_TYPE_WIDGET)
 44 
 45 #define ST_ICON_GET_PRIVATE(obj)    \
 46   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_ICON, StIconPrivate))
 47 
 48 struct _StIconPrivate
 49 {
 50   ClutterActor *icon_texture;
 51   ClutterActor *pending_texture;
 52   guint         opacity_handler_id;
 53 
 54   GIcon        *gicon;
 55   gint          prop_icon_size;  /* icon size set as property */
 56   gint          theme_icon_size; /* icon size from theme node */
 57   gint          icon_size;       /* icon size we are using */
 58 
 59   CoglHandle    shadow_material;
 60   float         shadow_width;
 61   float         shadow_height;
 62   StShadow     *shadow_spec;
 63 };
 64 
 65 static void st_icon_update               (StIcon *icon);
 66 static gboolean st_icon_update_icon_size (StIcon *icon);
 67 
 68 #define DEFAULT_ICON_SIZE 48
 69 
 70 static void
 71 st_icon_set_property (GObject      *gobject,
 72                       guint         prop_id,
 73                       const GValue *value,
 74                       GParamSpec   *pspec)
 75 {
 76   StIcon *icon = ST_ICON (gobject);
 77 
 78   switch (prop_id)
 79     {
 80     case PROP_GICON:
 81       st_icon_set_gicon (icon, g_value_get_object (value));
 82       break;
 83 
 84     case PROP_ICON_NAME:
 85       st_icon_set_icon_name (icon, g_value_get_string (value));
 86       break;
 87 
 88     case PROP_ICON_SIZE:
 89       st_icon_set_icon_size (icon, g_value_get_int (value));
 90       break;
 91 
 92     default:
 93       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
 94       break;
 95     }
 96 }
 97 
 98 static void
 99 st_icon_get_property (GObject    *gobject,
100                       guint       prop_id,
101                       GValue     *value,
102                       GParamSpec *pspec)
103 {
104   StIcon *icon = ST_ICON (gobject);
105 
106   switch (prop_id)
107     {
108     case PROP_GICON:
109       g_value_set_object (value, icon->priv->gicon);
110       break;
111 
112     case PROP_ICON_NAME:
113       g_value_set_string (value, st_icon_get_icon_name (icon));
114       break;
115 
116     case PROP_ICON_SIZE:
117       g_value_set_int (value, st_icon_get_icon_size (icon));
118       break;
119 
120     default:
121       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
122       break;
123     }
124 }
125 
126 static void
127 st_icon_dispose (GObject *gobject)
128 {
129   StIconPrivate *priv = ST_ICON (gobject)->priv;
130 
131   if (priv->icon_texture)
132     {
133       clutter_actor_destroy (priv->icon_texture);
134       priv->icon_texture = NULL;
135     }
136 
137   if (priv->pending_texture)
138     {
139       clutter_actor_destroy (priv->pending_texture);
140       g_object_unref (priv->pending_texture);
141       priv->pending_texture = NULL;
142     }
143 
144   if (priv->gicon)
145     {
146       g_object_unref (priv->gicon);
147       priv->gicon = NULL;
148     }
149 
150   if (priv->shadow_material)
151     {
152       cogl_handle_unref (priv->shadow_material);
153       priv->shadow_material = COGL_INVALID_HANDLE;
154     }
155 
156   if (priv->shadow_spec)
157     {
158       st_shadow_unref (priv->shadow_spec);
159       priv->shadow_spec = NULL;
160     }
161 
162   G_OBJECT_CLASS (st_icon_parent_class)->dispose (gobject);
163 }
164 
165 static void
166 st_icon_get_preferred_height (ClutterActor *actor,
167                               gfloat        for_width,
168                               gfloat       *min_height_p,
169                               gfloat       *nat_height_p)
170 {
171   StIconPrivate *priv = ST_ICON (actor)->priv;
172   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
173 
174   if (min_height_p)
175     *min_height_p = priv->icon_size;
176 
177   if (nat_height_p)
178     *nat_height_p = priv->icon_size;
179 
180   st_theme_node_adjust_preferred_height (theme_node, min_height_p, nat_height_p);
181 }
182 
183 static void
184 st_icon_get_preferred_width (ClutterActor *actor,
185                              gfloat        for_height,
186                              gfloat       *min_width_p,
187                              gfloat       *nat_width_p)
188 {
189   StIconPrivate *priv = ST_ICON (actor)->priv;
190   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
191 
192   if (min_width_p)
193     *min_width_p = priv->icon_size;
194 
195   if (nat_width_p)
196     *nat_width_p = priv->icon_size;
197 
198   st_theme_node_adjust_preferred_width (theme_node, min_width_p, nat_width_p);
199 }
200 
201 static void
202 st_icon_allocate (ClutterActor           *actor,
203                   const ClutterActorBox  *box,
204                   ClutterAllocationFlags  flags)
205 {
206   StIconPrivate *priv = ST_ICON (actor)->priv;
207   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
208 
209   clutter_actor_set_allocation (actor, box, flags);
210 
211   if (priv->icon_texture)
212     {
213       ClutterActorBox content_box;
214 
215       st_theme_node_get_content_box (theme_node, box, &content_box);
216 
217       /* Center the texture in the allocation; scaling up the icon from the size
218        * we loaded it at is just a bad idea and probably accidental. Main downside
219        * of doing this is that it may not be obvious that they have to turn off
220        * fill to align the icon non-centered in the parent container.
221        *
222        * We don't use clutter_actor_allocate_align_fill() for a bit of efficiency
223        * and because we expect to get rid of the child actor in favor of a
224        * CoglTexture in the future.
225        */
226       content_box.x1 = (int)(0.5 + content_box.x1 + (content_box.x2 - content_box.x1 - priv->icon_size) / 2.);
227       content_box.x2 = content_box.x1 + priv->icon_size;
228       content_box.y1 = (int)(0.5 + content_box.y1 + (content_box.y2 - content_box.y1 - priv->icon_size) / 2.);
229       content_box.y2 = content_box.y1 + priv->icon_size;
230 
231       clutter_actor_allocate (priv->icon_texture, &content_box, flags);
232     }
233 }
234 
235 static void
236 st_icon_paint (ClutterActor *actor)
237 {
238   StIconPrivate *priv = ST_ICON (actor)->priv;
239 
240   st_widget_paint_background (ST_WIDGET (actor));
241 
242   if (priv->icon_texture)
243     {
244       if (priv->shadow_material)
245         {
246           ClutterActorBox allocation;
247           float width, height;
248 
249           clutter_actor_get_allocation_box (priv->icon_texture, &allocation);
250           clutter_actor_box_get_size (&allocation, &width, &height);
251 
252           allocation.x1 = (width - priv->shadow_width) / 2;
253           allocation.y1 = (height - priv->shadow_height) / 2;
254           allocation.x2 = allocation.x1 + priv->shadow_width;
255           allocation.y2 = allocation.y1 + priv->shadow_height;
256 
257           _st_paint_shadow_with_opacity (priv->shadow_spec,
258                                          priv->shadow_material,
259                                          &allocation,
260                                          clutter_actor_get_paint_opacity (priv->icon_texture));
261         }
262 
263       clutter_actor_paint (priv->icon_texture);
264     }
265 }
266 
267 static void
268 st_icon_style_changed (StWidget *widget)
269 {
270   StIcon *self = ST_ICON (widget);
271   StThemeNode *theme_node = st_widget_get_theme_node (widget);
272   StIconPrivate *priv = self->priv;
273 
274   if (priv->shadow_spec)
275     {
276       st_shadow_unref (priv->shadow_spec);
277       priv->shadow_spec = NULL;
278     }
279 
280   if (priv->shadow_material)
281     {
282       cogl_handle_unref (priv->shadow_material);
283       priv->shadow_material = COGL_INVALID_HANDLE;
284     }
285 
286   priv->shadow_spec = st_theme_node_get_shadow (theme_node, "icon-shadow");
287 
288   if (priv->shadow_spec && priv->shadow_spec->inset)
289     {
290       g_warning ("The icon-shadow property does not support inset shadows");
291       st_shadow_unref (priv->shadow_spec);
292       priv->shadow_spec = NULL;
293     }
294 
295   priv->theme_icon_size = (int)(0.5 + st_theme_node_get_length (theme_node, "icon-size"));
296   st_icon_update_icon_size (self);
297   st_icon_update (self);
298 }
299 
300 static void
301 st_icon_class_init (StIconClass *klass)
302 {
303   GParamSpec *pspec;
304 
305   GObjectClass *object_class = G_OBJECT_CLASS (klass);
306   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
307   StWidgetClass *widget_class = ST_WIDGET_CLASS (klass);
308 
309   g_type_class_add_private (klass, sizeof (StIconPrivate));
310 
311   object_class->get_property = st_icon_get_property;
312   object_class->set_property = st_icon_set_property;
313   object_class->dispose = st_icon_dispose;
314 
315   actor_class->get_preferred_height = st_icon_get_preferred_height;
316   actor_class->get_preferred_width = st_icon_get_preferred_width;
317   actor_class->allocate = st_icon_allocate;
318   actor_class->paint = st_icon_paint;
319 
320   widget_class->style_changed = st_icon_style_changed;
321 
322   pspec = g_param_spec_object ("gicon",
323                                "GIcon",
324                                "The GIcon shown by this icon actor",
325                                G_TYPE_ICON,
326                                ST_PARAM_READWRITE);
327   g_object_class_install_property (object_class, PROP_GICON, pspec);
328 
329   pspec = g_param_spec_string ("icon-name",
330                                "Icon name",
331                                "An icon name",
332                                NULL, ST_PARAM_READWRITE | G_PARAM_DEPRECATED);
333   g_object_class_install_property (object_class, PROP_ICON_NAME, pspec);
334 
335   pspec = g_param_spec_int ("icon-size",
336                             "Icon size",
337                             "The size if the icon, if positive. Otherwise the size will be derived from the current style",
338                             -1, G_MAXINT, -1,
339                             ST_PARAM_READWRITE);
340   g_object_class_install_property (object_class, PROP_ICON_SIZE, pspec);
341 }
342 
343 static void
344 st_icon_init (StIcon *self)
345 {
346   self->priv = ST_ICON_GET_PRIVATE (self);
347 
348   self->priv->icon_size = DEFAULT_ICON_SIZE;
349   self->priv->prop_icon_size = -1;
350 
351   self->priv->shadow_material = COGL_INVALID_HANDLE;
352   self->priv->shadow_width = -1;
353   self->priv->shadow_height = -1;
354 }
355 
356 static void
357 st_icon_update_shadow_material (StIcon *icon)
358 {
359   StIconPrivate *priv = icon->priv;
360 
361   if (priv->shadow_material)
362     {
363       cogl_handle_unref (priv->shadow_material);
364       priv->shadow_material = COGL_INVALID_HANDLE;
365     }
366 
367   if (priv->shadow_spec)
368    {
369      CoglHandle material;
370      gint width, height;
371 
372      clutter_texture_get_base_size (CLUTTER_TEXTURE (priv->icon_texture),
'clutter_texture_get_base_size' is deprecated (declared at /usr/include/clutter-1.0/clutter/deprecated/clutter-texture.h:69)
(emitted by gcc)
373 &width, &height); 374 375 material = _st_create_shadow_material_from_actor (priv->shadow_spec, 376 priv->icon_texture); 377 priv->shadow_material = material; 378 priv->shadow_width = width; 379 priv->shadow_height = height; 380 } 381 } 382 383 static void 384 on_pixbuf_changed (ClutterTexture *texture, 385 StIcon *icon) 386 { 387 st_icon_update_shadow_material (icon); 388 } 389 390 static void 391 st_icon_finish_update (StIcon *icon) 392 { 393 StIconPrivate *priv = icon->priv; 394 395 if (priv->icon_texture) 396 { 397 clutter_actor_destroy (priv->icon_texture); 398 priv->icon_texture = NULL; 399 } 400 401 if (priv->pending_texture) 402 { 403 priv->icon_texture = priv->pending_texture; 404 priv->pending_texture = NULL; 405 clutter_actor_add_child (CLUTTER_ACTOR (icon), priv->icon_texture); 406 407 /* Remove the temporary ref we added */ 408 g_object_unref (priv->icon_texture); 409 410 st_icon_update_shadow_material (icon); 411 412 /* "pixbuf-change" is actually a misnomer for "texture-changed" */ 413 g_signal_connect (priv->icon_texture, "pixbuf-change", 414 G_CALLBACK (on_pixbuf_changed), icon); 415 } 416 } 417 418 static void 419 opacity_changed_cb (GObject *object, 420 GParamSpec *pspec, 421 gpointer user_data) 422 { 423 StIcon *icon = user_data; 424 StIconPrivate *priv = icon->priv; 425 426 g_signal_handler_disconnect (priv->pending_texture, priv->opacity_handler_id); 427 priv->opacity_handler_id = 0; 428 429 st_icon_finish_update (icon); 430 } 431 432 static void 433 st_icon_update (StIcon *icon) 434 { 435 StIconPrivate *priv = icon->priv; 436 StThemeNode *theme_node; 437 StTextureCache *cache; 438 439 if (priv->pending_texture) 440 { 441 clutter_actor_destroy (priv->pending_texture); 442 g_object_unref (priv->pending_texture); 443 priv->pending_texture = NULL; 444 priv->opacity_handler_id = 0; 445 } 446 447 theme_node = st_widget_peek_theme_node (ST_WIDGET (icon)); 448 if (theme_node == NULL) 449 return; 450 451 cache = st_texture_cache_get_default (); 452 if (priv->gicon) 453 { 454 priv->pending_texture = st_texture_cache_load_gicon (cache, 455 theme_node, 456 priv->gicon, 457 priv->icon_size); 458 } 459 460 if (priv->pending_texture) 461 { 462 g_object_ref_sink (priv->pending_texture); 463 464 if (clutter_actor_get_opacity (priv->pending_texture) != 0 || priv->icon_texture == NULL) 465 { 466 /* This icon is ready for showing, or nothing else is already showing */ 467 st_icon_finish_update (icon); 468 } 469 else 470 { 471 /* Will be shown when fully loaded */ 472 priv->opacity_handler_id = g_signal_connect (priv->pending_texture, "notify::opacity", G_CALLBACK (opacity_changed_cb), icon); 473 } 474 } 475 else if (priv->icon_texture) 476 { 477 clutter_actor_destroy (priv->icon_texture); 478 priv->icon_texture = NULL; 479 } 480 } 481 482 static gboolean 483 st_icon_update_icon_size (StIcon *icon) 484 { 485 StIconPrivate *priv = icon->priv; 486 int new_size; 487 488 if (priv->prop_icon_size > 0) 489 new_size = priv->prop_icon_size; 490 else if (priv->theme_icon_size > 0) 491 new_size = priv->theme_icon_size; 492 else 493 new_size = DEFAULT_ICON_SIZE; 494 495 if (new_size != priv->icon_size) 496 { 497 clutter_actor_queue_relayout (CLUTTER_ACTOR (icon)); 498 priv->icon_size = new_size; 499 return TRUE; 500 } 501 else 502 return FALSE; 503 } 504 505 /** 506 * st_icon_new: 507 * 508 * Create a newly allocated #StIcon 509 * 510 * Returns: A newly allocated #StIcon 511 */ 512 ClutterActor * 513 st_icon_new (void) 514 { 515 return g_object_new (ST_TYPE_ICON, NULL); 516 } 517 518 const gchar * 519 st_icon_get_icon_name (StIcon *icon) 520 { 521 StIconPrivate *priv; 522 523 g_return_val_if_fail (ST_IS_ICON (icon), NULL); 524 525 priv = icon->priv; 526 527 if (priv->gicon && G_IS_THEMED_ICON (priv->gicon)) 528 return g_themed_icon_get_names (G_THEMED_ICON (priv->gicon)) [0]; 529 else 530 return NULL; 531 } 532 533 void 534 st_icon_set_icon_name (StIcon *icon, 535 const gchar *icon_name) 536 { 537 StIconPrivate *priv; 538 539 g_return_if_fail (ST_IS_ICON (icon)); 540 541 priv = icon->priv; 542 543 if (priv->gicon) 544 g_object_unref (priv->gicon); 545 546 if (icon_name) 547 priv->gicon = g_themed_icon_new_with_default_fallbacks (icon_name); 548 else 549 priv->gicon = NULL; 550 551 g_object_notify (G_OBJECT (icon), "gicon"); 552 g_object_notify (G_OBJECT (icon), "icon-name"); 553 554 st_icon_update (icon); 555 } 556 557 /** 558 * st_icon_get_gicon: 559 * @icon: an icon 560 * 561 * Return value: (transfer none): the override GIcon, if set, or NULL 562 */ 563 GIcon * 564 st_icon_get_gicon (StIcon *icon) 565 { 566 g_return_val_if_fail (ST_IS_ICON (icon), NULL); 567 568 return icon->priv->gicon; 569 } 570 571 /** 572 * st_icon_set_gicon: 573 * @icon: an icon 574 * @gicon: (allow-none): a #GIcon to override :icon-name 575 */ 576 void 577 st_icon_set_gicon (StIcon *icon, GIcon *gicon) 578 { 579 g_return_if_fail (ST_IS_ICON (icon)); 580 g_return_if_fail (gicon == NULL || G_IS_ICON (gicon)); 581 582 if (icon->priv->gicon == gicon) /* do nothing */ 583 return; 584 585 if (icon->priv->gicon) 586 { 587 g_object_unref (icon->priv->gicon); 588 icon->priv->gicon = NULL; 589 } 590 591 if (gicon) 592 icon->priv->gicon = g_object_ref (gicon); 593 594 g_object_notify (G_OBJECT (icon), "gicon"); 595 596 st_icon_update (icon); 597 } 598 599 /** 600 * st_icon_get_icon_size: 601 * @icon: an icon 602 * 603 * Gets the size explicit size on the icon. This is not necesariily 604 * the size that the icon will actually be displayed at. 605 * 606 * Return value: the size explicitly set, or -1 if no size has been set 607 */ 608 gint 609 st_icon_get_icon_size (StIcon *icon) 610 { 611 g_return_val_if_fail (ST_IS_ICON (icon), -1); 612 613 return icon->priv->prop_icon_size; 614 } 615 616 /** 617 * st_icon_set_icon_size: 618 * @icon: an icon 619 * @size: if positive, the new size, otherwise the size will be 620 * derived from the current style 621 * 622 * Sets an explicit size for the icon. 623 */ 624 void 625 st_icon_set_icon_size (StIcon *icon, 626 gint size) 627 { 628 StIconPrivate *priv; 629 630 g_return_if_fail (ST_IS_ICON (icon)); 631 632 priv = icon->priv; 633 if (priv->prop_icon_size != size) 634 { 635 priv->prop_icon_size = size; 636 if (st_icon_update_icon_size (icon)) 637 st_icon_update (icon); 638 g_object_notify (G_OBJECT (icon), "icon-size"); 639 } 640 }