1 /*
2  * emblem-effect: Draws an emblem on top of an actor
3  *
4  * Copyright 2012-2020 Stephan Haller <nomad@froevel.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  *
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #define COGL_ENABLE_EXPERIMENTAL_API
29 #define CLUTTER_ENABLE_EXPERIMENTAL_API
30 
31 #include <libxfdashboard/emblem-effect.h>
32 
33 #include <glib/gi18n-lib.h>
34 #include <math.h>
35 #include <cogl/cogl.h>
36 
37 #include <libxfdashboard/image-content.h>
38 #include <libxfdashboard/enums.h>
39 #include <libxfdashboard/compat.h>
40 #include <libxfdashboard/debug.h>
41 
42 
43 /* Define this class in GObject system */
44 struct _XfdashboardEmblemEffectPrivate
45 {
46 	/* Properties related */
47 	gchar						*iconName;
48 	gint						iconSize;
49 	gfloat						padding;
50 	gfloat						xAlign;
51 	gfloat						yAlign;
52 	XfdashboardAnchorPoint		anchorPoint;
53 
54 	/* Instance related */
55 	ClutterContent				*icon;
56 	guint						loadSuccessSignalID;
57 	guint						loadFailedSignalID;
58 
59 	CoglPipeline				*pipeline;
60 };
61 
62 G_DEFINE_TYPE_WITH_PRIVATE(XfdashboardEmblemEffect,
63 							xfdashboard_emblem_effect,
64 							CLUTTER_TYPE_EFFECT)
65 
66 /* Properties */
67 enum
68 {
69 	PROP_0,
70 
71 	PROP_ICON_NAME,
72 	PROP_ICON_SIZE,
73 	PROP_PADDING,
74 	PROP_X_ALIGN,
75 	PROP_Y_ALIGN,
76 	PROP_ANCHOR_POINT,
77 
78 	PROP_LAST
79 };
80 
81 static GParamSpec* XfdashboardEmblemEffectProperties[PROP_LAST]={ 0, };
82 
83 /* IMPLEMENTATION: Private variables and methods */
84 static CoglPipeline		*_xfdashboard_emblem_effect_base_pipeline=NULL;
85 
86 /* Icon image was loaded */
_xfdashboard_emblem_effect_on_load_finished(XfdashboardEmblemEffect * self,gpointer inUserData)87 static void _xfdashboard_emblem_effect_on_load_finished(XfdashboardEmblemEffect *self, gpointer inUserData)
88 {
89 	XfdashboardEmblemEffectPrivate		*priv;
90 
91 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self));
92 
93 	priv=self->priv;
94 
95 	/* Disconnect signal handlers */
96 	if(priv->loadSuccessSignalID)
97 	{
98 		g_signal_handler_disconnect(priv->icon, priv->loadSuccessSignalID);
99 		priv->loadSuccessSignalID=0;
100 	}
101 
102 	if(priv->loadFailedSignalID)
103 	{
104 		g_signal_handler_disconnect(priv->icon, priv->loadFailedSignalID);
105 		priv->loadFailedSignalID=0;
106 	}
107 
108 	/* Set image at pipeline */
109 	cogl_pipeline_set_layer_texture(priv->pipeline,
110 									0,
111 									clutter_image_get_texture(CLUTTER_IMAGE(priv->icon)));
112 
113 	/* Invalidate effect to get it redrawn */
114 	clutter_effect_queue_repaint(CLUTTER_EFFECT(self));
115 }
116 
117 /* IMPLEMENTATION: ClutterEffect */
118 
119 /* Draw effect after actor was drawn */
_xfdashboard_emblem_effect_paint(ClutterEffect * inEffect,ClutterEffectPaintFlags inFlags)120 static void _xfdashboard_emblem_effect_paint(ClutterEffect *inEffect, ClutterEffectPaintFlags inFlags)
121 {
122 	XfdashboardEmblemEffect					*self;
123 	XfdashboardEmblemEffectPrivate			*priv;
124 	ClutterActor							*target;
125 	gfloat									actorWidth;
126 	gfloat									actorHeight;
127 	ClutterActorBox							actorBox;
128 	ClutterActorBox							rectangleBox;
129 	XfdashboardImageContentLoadingState		loadingState;
130 	gfloat									textureWidth;
131 	gfloat									textureHeight;
132 	ClutterActorBox							textureCoordBox;
133 	gfloat									offset;
134 	gfloat									oversize;
135 	CoglFramebuffer							*framebuffer;
136 
137 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(inEffect));
138 
139 	self=XFDASHBOARD_EMBLEM_EFFECT(inEffect);
140 	priv=self->priv;
141 
142 	/* Chain to the next item in the paint sequence */
143 	target=clutter_actor_meta_get_actor(CLUTTER_ACTOR_META(self));
144 	clutter_actor_continue_paint(target);
145 
146 	/* If no icon name is set do not apply this effect */
147 	if(!priv->iconName) return;
148 
149 	/* Load image if not done yet */
150 	if(!priv->icon)
151 	{
152 		/* Get image from cache */
153 		priv->icon=xfdashboard_image_content_new_for_icon_name(priv->iconName, priv->iconSize);
154 
155 		/* Ensure image is being loaded */
156 		loadingState=xfdashboard_image_content_get_state(XFDASHBOARD_IMAGE_CONTENT(priv->icon));
157 		if(loadingState==XFDASHBOARD_IMAGE_CONTENT_LOADING_STATE_NONE ||
158 			loadingState==XFDASHBOARD_IMAGE_CONTENT_LOADING_STATE_LOADING)
159 		{
160 			/* Connect signals just because we need to wait for image being loaded */
161 			priv->loadSuccessSignalID=g_signal_connect_swapped(priv->icon,
162 																"loaded",
163 																G_CALLBACK(_xfdashboard_emblem_effect_on_load_finished),
164 																self);
165 			priv->loadFailedSignalID=g_signal_connect_swapped(priv->icon,
166 																"loading-failed",
167 																G_CALLBACK(_xfdashboard_emblem_effect_on_load_finished),
168 																self);
169 
170 			/* If image is not being loaded currently enforce loading now */
171 			if(loadingState==XFDASHBOARD_IMAGE_CONTENT_LOADING_STATE_NONE)
172 			{
173 				xfdashboard_image_content_force_load(XFDASHBOARD_IMAGE_CONTENT(priv->icon));
174 			}
175 		}
176 			else
177 			{
178 				/* Image is already loaded so set image at pipeline */
179 				cogl_pipeline_set_layer_texture(priv->pipeline,
180 												0,
181 												clutter_image_get_texture(CLUTTER_IMAGE(priv->icon)));
182 			}
183 	}
184 
185 	/* Get actor size and apply padding. If actor width or height will drop
186 	 * to zero or below then the emblem could not be drawn and we return here.
187 	 */
188 	clutter_actor_get_content_box(target, &actorBox);
189 	actorBox.x1+=priv->padding;
190 	actorBox.x2-=priv->padding;
191 	actorBox.y1+=priv->padding;
192 	actorBox.y2-=priv->padding;
193 
194 	if(actorBox.x2<=actorBox.x1 ||
195 		actorBox.y2<=actorBox.y1)
196 	{
197 		XFDASHBOARD_DEBUG(self, ACTOR,
198 							"Will not draw emblem '%s' because width or height of actor is zero or below after padding was applied.",
199 							priv->iconName);
200 		return;
201 	}
202 
203 	actorWidth=actorBox.x2-actorBox.x1;
204 	actorHeight=actorBox.y2-actorBox.y1;
205 
206 	/* Get texture size */
207 	clutter_content_get_preferred_size(CLUTTER_CONTENT(priv->icon), &textureWidth, &textureHeight);
208 	clutter_actor_box_init(&textureCoordBox, 0.0f, 0.0f, 1.0f, 1.0f);
209 
210 	/* Get boundary in X axis depending on anchorPoint and scaled width */
211 	offset=(priv->xAlign*actorWidth);
212 	switch(priv->anchorPoint)
213 	{
214 		/* Align to left boundary.
215 		 * This is also the default if anchor point is none or undefined.
216 		 */
217 		default:
218 		case XFDASHBOARD_ANCHOR_POINT_NONE:
219 		case XFDASHBOARD_ANCHOR_POINT_WEST:
220 		case XFDASHBOARD_ANCHOR_POINT_NORTH_WEST:
221 		case XFDASHBOARD_ANCHOR_POINT_SOUTH_WEST:
222 			break;
223 
224 		/* Align to center of X axis */
225 		case XFDASHBOARD_ANCHOR_POINT_CENTER:
226 		case XFDASHBOARD_ANCHOR_POINT_NORTH:
227 		case XFDASHBOARD_ANCHOR_POINT_SOUTH:
228 			offset-=(textureWidth/2.0f);
229 			break;
230 
231 		/* Align to right boundary */
232 		case XFDASHBOARD_ANCHOR_POINT_EAST:
233 		case XFDASHBOARD_ANCHOR_POINT_NORTH_EAST:
234 		case XFDASHBOARD_ANCHOR_POINT_SOUTH_EAST:
235 			offset-=textureWidth;
236 			break;
237 	}
238 
239 	/* Set boundary in X axis */
240 	rectangleBox.x1=actorBox.x1+offset;
241 	rectangleBox.x2=rectangleBox.x1+textureWidth;
242 
243 	/* Clip texture in X axis if it does not fit into allocation */
244 	if(rectangleBox.x1<actorBox.x1)
245 	{
246 		oversize=actorBox.x1-rectangleBox.x1;
247 		textureCoordBox.x1=oversize/textureWidth;
248 		rectangleBox.x1=actorBox.x1;
249 	}
250 
251 	if(rectangleBox.x2>actorBox.x2)
252 	{
253 		oversize=rectangleBox.x2-actorBox.x2;
254 		textureCoordBox.x2=1.0f-(oversize/textureWidth);
255 		rectangleBox.x2=actorBox.x2;
256 	}
257 
258 	/* Get boundary in Y axis depending on anchorPoint and scaled width */
259 	offset=(priv->yAlign*actorHeight);
260 	switch(priv->anchorPoint)
261 	{
262 		/* Align to upper boundary.
263 		 * This is also the default if anchor point is none or undefined.
264 		 */
265 		default:
266 		case XFDASHBOARD_ANCHOR_POINT_NONE:
267 		case XFDASHBOARD_ANCHOR_POINT_NORTH:
268 		case XFDASHBOARD_ANCHOR_POINT_NORTH_WEST:
269 		case XFDASHBOARD_ANCHOR_POINT_NORTH_EAST:
270 			break;
271 
272 		/* Align to center of Y axis */
273 		case XFDASHBOARD_ANCHOR_POINT_CENTER:
274 		case XFDASHBOARD_ANCHOR_POINT_WEST:
275 		case XFDASHBOARD_ANCHOR_POINT_EAST:
276 			offset-=(textureHeight/2.0f);
277 			break;
278 
279 		/* Align to lower boundary */
280 		case XFDASHBOARD_ANCHOR_POINT_SOUTH:
281 		case XFDASHBOARD_ANCHOR_POINT_SOUTH_WEST:
282 		case XFDASHBOARD_ANCHOR_POINT_SOUTH_EAST:
283 			offset-=textureHeight;
284 			break;
285 	}
286 
287 	/* Set boundary in Y axis */
288 	rectangleBox.y1=actorBox.y1+offset;
289 	rectangleBox.y2=rectangleBox.y1+textureHeight;
290 
291 	/* Clip texture in Y axis if it does not fit into allocation */
292 	if(rectangleBox.y1<actorBox.y1)
293 	{
294 		oversize=actorBox.y1-rectangleBox.y1;
295 		textureCoordBox.y1=oversize/textureHeight;
296 		rectangleBox.y1=actorBox.y1;
297 	}
298 
299 	if(rectangleBox.y2>actorBox.y2)
300 	{
301 		oversize=rectangleBox.y2-actorBox.y2;
302 		textureCoordBox.y2=1.0f-(oversize/textureHeight);
303 		rectangleBox.y2=actorBox.y2;
304 	}
305 
306 	/* Draw icon if image was loaded */
307 	loadingState=xfdashboard_image_content_get_state(XFDASHBOARD_IMAGE_CONTENT(priv->icon));
308 	if(loadingState!=XFDASHBOARD_IMAGE_CONTENT_LOADING_STATE_LOADED_SUCCESSFULLY &&
309 		loadingState!=XFDASHBOARD_IMAGE_CONTENT_LOADING_STATE_LOADED_FAILED)
310 	{
311 		XFDASHBOARD_DEBUG(self, ACTOR,
312 							"Emblem image '%s' is still being loaded at %s",
313 							priv->iconName,
314 							G_OBJECT_TYPE_NAME(inEffect));
315 		return;
316 	}
317 
318 	framebuffer=cogl_get_draw_framebuffer();
319 	cogl_framebuffer_draw_textured_rectangle(framebuffer,
320 												priv->pipeline,
321 												rectangleBox.x1, rectangleBox.y1,
322 												rectangleBox.x2, rectangleBox.y2,
323 												textureCoordBox.x1, textureCoordBox.y1,
324 												textureCoordBox.x2, textureCoordBox.y2);
325 }
326 
327 /* IMPLEMENTATION: GObject */
328 
329 /* Dispose this object */
_xfdashboard_emblem_effect_dispose(GObject * inObject)330 static void _xfdashboard_emblem_effect_dispose(GObject *inObject)
331 {
332 	/* Release allocated variables */
333 	XfdashboardEmblemEffect			*self=XFDASHBOARD_EMBLEM_EFFECT(inObject);
334 	XfdashboardEmblemEffectPrivate	*priv=self->priv;
335 
336 	if(priv->pipeline)
337 	{
338 		cogl_object_unref(priv->pipeline);
339 		priv->pipeline=NULL;
340 	}
341 
342 	if(priv->icon)
343 	{
344 		/* Disconnect any connected signal handler */
345 		if(priv->loadSuccessSignalID)
346 		{
347 			g_signal_handler_disconnect(priv->icon, priv->loadSuccessSignalID);
348 			priv->loadSuccessSignalID=0;
349 		}
350 
351 		if(priv->loadFailedSignalID)
352 		{
353 			g_signal_handler_disconnect(priv->icon, priv->loadFailedSignalID);
354 			priv->loadFailedSignalID=0;
355 		}
356 
357 		/* Release image itself */
358 		g_object_unref(priv->icon);
359 		priv->icon=NULL;
360 	}
361 
362 	if(priv->iconName)
363 	{
364 		g_free(priv->iconName);
365 		priv->iconName=NULL;
366 	}
367 
368 	/* Call parent's class dispose method */
369 	G_OBJECT_CLASS(xfdashboard_emblem_effect_parent_class)->dispose(inObject);
370 }
371 
372 /* Set/get properties */
_xfdashboard_emblem_effect_set_property(GObject * inObject,guint inPropID,const GValue * inValue,GParamSpec * inSpec)373 static void _xfdashboard_emblem_effect_set_property(GObject *inObject,
374 														guint inPropID,
375 														const GValue *inValue,
376 														GParamSpec *inSpec)
377 {
378 	XfdashboardEmblemEffect			*self=XFDASHBOARD_EMBLEM_EFFECT(inObject);
379 
380 	switch(inPropID)
381 	{
382 		case PROP_ICON_NAME:
383 			xfdashboard_emblem_effect_set_icon_name(self, g_value_get_string(inValue));
384 			break;
385 
386 		case PROP_ICON_SIZE:
387 			xfdashboard_emblem_effect_set_icon_size(self, g_value_get_int(inValue));
388 			break;
389 
390 		case PROP_PADDING:
391 			xfdashboard_emblem_effect_set_padding(self, g_value_get_float(inValue));
392 			break;
393 
394 		case PROP_X_ALIGN:
395 			xfdashboard_emblem_effect_set_x_align(self, g_value_get_float(inValue));
396 			break;
397 
398 		case PROP_Y_ALIGN:
399 			xfdashboard_emblem_effect_set_y_align(self, g_value_get_float(inValue));
400 			break;
401 
402 		case PROP_ANCHOR_POINT:
403 			xfdashboard_emblem_effect_set_anchor_point(self, g_value_get_enum(inValue));
404 			break;
405 
406 		default:
407 			G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
408 			break;
409 	}
410 }
411 
_xfdashboard_emblem_effect_get_property(GObject * inObject,guint inPropID,GValue * outValue,GParamSpec * inSpec)412 static void _xfdashboard_emblem_effect_get_property(GObject *inObject,
413 														guint inPropID,
414 														GValue *outValue,
415 														GParamSpec *inSpec)
416 {
417 	XfdashboardEmblemEffect			*self=XFDASHBOARD_EMBLEM_EFFECT(inObject);
418 	XfdashboardEmblemEffectPrivate		*priv=self->priv;
419 
420 	switch(inPropID)
421 	{
422 		case PROP_ICON_NAME:
423 			g_value_set_string(outValue, priv->iconName);
424 			break;
425 
426 		case PROP_ICON_SIZE:
427 			g_value_set_int(outValue, priv->iconSize);
428 			break;
429 
430 		case PROP_PADDING:
431 			g_value_set_float(outValue, priv->padding);
432 			break;
433 
434 		case PROP_X_ALIGN:
435 			g_value_set_float(outValue, priv->xAlign);
436 			break;
437 
438 		case PROP_Y_ALIGN:
439 			g_value_set_float(outValue, priv->yAlign);
440 			break;
441 
442 		case PROP_ANCHOR_POINT:
443 			g_value_set_enum(outValue, priv->anchorPoint);
444 			break;
445 
446 		default:
447 			G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
448 			break;
449 	}
450 }
451 
452 /* Class initialization
453  * Override functions in parent classes and define properties
454  * and signals
455  */
xfdashboard_emblem_effect_class_init(XfdashboardEmblemEffectClass * klass)456 static void xfdashboard_emblem_effect_class_init(XfdashboardEmblemEffectClass *klass)
457 {
458 	ClutterEffectClass				*effectClass=CLUTTER_EFFECT_CLASS(klass);
459 	GObjectClass					*gobjectClass=G_OBJECT_CLASS(klass);
460 
461 	/* Override functions */
462 	gobjectClass->dispose=_xfdashboard_emblem_effect_dispose;
463 	gobjectClass->set_property=_xfdashboard_emblem_effect_set_property;
464 	gobjectClass->get_property=_xfdashboard_emblem_effect_get_property;
465 
466 	effectClass->paint=_xfdashboard_emblem_effect_paint;
467 
468 	/* Define properties */
469 	XfdashboardEmblemEffectProperties[PROP_ICON_NAME]=
470 		g_param_spec_string("icon-name",
471 							"Icon name",
472 							"Themed icon name or file name of icon",
473 							N_(""),
474 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
475 
476 	XfdashboardEmblemEffectProperties[PROP_ICON_SIZE]=
477 		g_param_spec_int("icon-size",
478 							"Icon size",
479 							"Size of icon",
480 							1, G_MAXINT,
481 							16,
482 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
483 
484 	XfdashboardEmblemEffectProperties[PROP_PADDING]=
485 		g_param_spec_float("padding",
486 							"Padding",
487 							"Padding around emblem",
488 							0.0f, G_MAXFLOAT,
489 							0.0f,
490 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
491 
492 	XfdashboardEmblemEffectProperties[PROP_X_ALIGN]=
493 		g_param_spec_float("x-align",
494 							"X align",
495 							"The alignment of emblem on the X axis within the allocation in normalized coordinate between 0 and 1",
496 							0.0f, 1.0f,
497 							0.0f,
498 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
499 
500 	XfdashboardEmblemEffectProperties[PROP_Y_ALIGN]=
501 		g_param_spec_float("y-align",
502 							"Y align",
503 							"The alignment of emblem on the Y axis within the allocation in normalized coordinate between 0 and 1",
504 							0.0f, 1.0f,
505 							0.0f,
506 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
507 
508 	XfdashboardEmblemEffectProperties[PROP_ANCHOR_POINT]=
509 		g_param_spec_enum("anchor-point",
510 							"Anchor point",
511 							"The anchor point of emblem",
512 							XFDASHBOARD_TYPE_ANCHOR_POINT,
513 							XFDASHBOARD_ANCHOR_POINT_NONE,
514 							G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
515 
516 	g_object_class_install_properties(gobjectClass, PROP_LAST, XfdashboardEmblemEffectProperties);
517 }
518 
519 /* Object initialization
520  * Create private structure and set up default values
521  */
xfdashboard_emblem_effect_init(XfdashboardEmblemEffect * self)522 static void xfdashboard_emblem_effect_init(XfdashboardEmblemEffect *self)
523 {
524 	XfdashboardEmblemEffectPrivate	*priv;
525 
526 	priv=self->priv=xfdashboard_emblem_effect_get_instance_private(self);
527 
528 	/* Set up default values */
529 	priv->iconName=NULL;
530 	priv->iconSize=16;
531 	priv->padding=0.0f;
532 	priv->xAlign=0.0f;
533 	priv->yAlign=0.0f;
534 	priv->anchorPoint=XFDASHBOARD_ANCHOR_POINT_NONE;
535 	priv->icon=NULL;
536 	priv->loadSuccessSignalID=0;
537 	priv->loadFailedSignalID=0;
538 
539 	/* Set up pipeline */
540 	if(G_UNLIKELY(!_xfdashboard_emblem_effect_base_pipeline))
541     {
542 		CoglContext					*context;
543 
544 		/* Get context to create base pipeline */
545 		context=clutter_backend_get_cogl_context(clutter_get_default_backend());
546 
547 		/* Create base pipeline */
548 		_xfdashboard_emblem_effect_base_pipeline=cogl_pipeline_new(context);
549 		cogl_pipeline_set_layer_null_texture(_xfdashboard_emblem_effect_base_pipeline,
550 												0, /* layer number */
551 												COGL_TEXTURE_TYPE_2D);
552 	}
553 
554 	priv->pipeline=cogl_pipeline_copy(_xfdashboard_emblem_effect_base_pipeline);
555 }
556 
557 /* IMPLEMENTATION: Public API */
558 
559 /* Create new actor */
xfdashboard_emblem_effect_new(void)560 ClutterEffect* xfdashboard_emblem_effect_new(void)
561 {
562 	return(g_object_new(XFDASHBOARD_TYPE_EMBLEM_EFFECT, NULL));
563 }
564 
565 /* Get/set icon name of emblem to draw */
xfdashboard_emblem_effect_get_icon_name(XfdashboardEmblemEffect * self)566 const gchar* xfdashboard_emblem_effect_get_icon_name(XfdashboardEmblemEffect *self)
567 {
568 	g_return_val_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self), NULL);
569 
570 	return(self->priv->iconName);
571 }
572 
xfdashboard_emblem_effect_set_icon_name(XfdashboardEmblemEffect * self,const gchar * inIconName)573 void xfdashboard_emblem_effect_set_icon_name(XfdashboardEmblemEffect *self, const gchar *inIconName)
574 {
575 	XfdashboardEmblemEffectPrivate	*priv;
576 
577 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self));
578 	g_return_if_fail(inIconName);
579 
580 	priv=self->priv;
581 
582 	/* Set value if changed */
583 	if(priv->icon || g_strcmp0(priv->iconName, inIconName)!=0)
584 	{
585 		/* Set value */
586 		if(priv->iconName) g_free(priv->iconName);
587 		priv->iconName=g_strdup(inIconName);
588 
589 		/* Dispose any icon image loaded */
590 		if(priv->icon)
591 		{
592 			g_object_unref(priv->icon);
593 			priv->icon=NULL;
594 		}
595 
596 		/* Invalidate effect to get it redrawn */
597 		clutter_effect_queue_repaint(CLUTTER_EFFECT(self));
598 
599 		/* Notify about property change */
600 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardEmblemEffectProperties[PROP_ICON_NAME]);
601 	}
602 }
603 
604 /* Get/set icon size of emblem to draw */
xfdashboard_emblem_effect_get_icon_size(XfdashboardEmblemEffect * self)605 gint xfdashboard_emblem_effect_get_icon_size(XfdashboardEmblemEffect *self)
606 {
607 	g_return_val_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self), 0);
608 
609 	return(self->priv->iconSize);
610 }
611 
xfdashboard_emblem_effect_set_icon_size(XfdashboardEmblemEffect * self,const gint inSize)612 void xfdashboard_emblem_effect_set_icon_size(XfdashboardEmblemEffect *self, const gint inSize)
613 {
614 	XfdashboardEmblemEffectPrivate	*priv;
615 
616 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self));
617 	g_return_if_fail(inSize>0);
618 
619 	priv=self->priv;
620 
621 	/* Set value if changed */
622 	if(priv->iconSize!=inSize)
623 	{
624 		/* Set value */
625 		priv->iconSize=inSize;
626 
627 		/* Dispose any icon image loaded */
628 		if(priv->icon)
629 		{
630 			g_object_unref(priv->icon);
631 			priv->icon=NULL;
632 		}
633 
634 		/* Invalidate effect to get it redrawn */
635 		clutter_effect_queue_repaint(CLUTTER_EFFECT(self));
636 
637 		/* Notify about property change */
638 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardEmblemEffectProperties[PROP_ICON_SIZE]);
639 	}
640 }
641 
642 /* Get/set x align of emblem */
xfdashboard_emblem_effect_get_padding(XfdashboardEmblemEffect * self)643 gfloat xfdashboard_emblem_effect_get_padding(XfdashboardEmblemEffect *self)
644 {
645 	g_return_val_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self), 0.0f);
646 
647 	return(self->priv->padding);
648 }
649 
xfdashboard_emblem_effect_set_padding(XfdashboardEmblemEffect * self,const gfloat inPadding)650 void xfdashboard_emblem_effect_set_padding(XfdashboardEmblemEffect *self, const gfloat inPadding)
651 {
652 	XfdashboardEmblemEffectPrivate		*priv;
653 
654 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self));
655 	g_return_if_fail(inPadding>=0.0f);
656 
657 	priv=self->priv;
658 
659 	/* Set value if changed */
660 	if(priv->padding!=inPadding)
661 	{
662 		/* Set value */
663 		priv->padding=inPadding;
664 
665 		/* Invalidate effect to get it redrawn */
666 		clutter_effect_queue_repaint(CLUTTER_EFFECT(self));
667 
668 		/* Notify about property change */
669 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardEmblemEffectProperties[PROP_PADDING]);
670 	}
671 }
672 
673 /* Get/set x align of emblem */
xfdashboard_emblem_effect_get_x_align(XfdashboardEmblemEffect * self)674 gfloat xfdashboard_emblem_effect_get_x_align(XfdashboardEmblemEffect *self)
675 {
676 	g_return_val_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self), 0.0f);
677 
678 	return(self->priv->xAlign);
679 }
680 
xfdashboard_emblem_effect_set_x_align(XfdashboardEmblemEffect * self,const gfloat inAlign)681 void xfdashboard_emblem_effect_set_x_align(XfdashboardEmblemEffect *self, const gfloat inAlign)
682 {
683 	XfdashboardEmblemEffectPrivate		*priv;
684 
685 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self));
686 	g_return_if_fail(inAlign>=0.0f && inAlign<=1.0f);
687 
688 	priv=self->priv;
689 
690 	/* Set value if changed */
691 	if(priv->xAlign!=inAlign)
692 	{
693 		/* Set value */
694 		priv->xAlign=inAlign;
695 
696 		/* Invalidate effect to get it redrawn */
697 		clutter_effect_queue_repaint(CLUTTER_EFFECT(self));
698 
699 		/* Notify about property change */
700 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardEmblemEffectProperties[PROP_X_ALIGN]);
701 	}
702 }
703 
704 /* Get/set y align of emblem */
xfdashboard_emblem_effect_get_y_align(XfdashboardEmblemEffect * self)705 gfloat xfdashboard_emblem_effect_get_y_align(XfdashboardEmblemEffect *self)
706 {
707 	g_return_val_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self), 0.0f);
708 
709 	return(self->priv->xAlign);
710 }
711 
xfdashboard_emblem_effect_set_y_align(XfdashboardEmblemEffect * self,const gfloat inAlign)712 void xfdashboard_emblem_effect_set_y_align(XfdashboardEmblemEffect *self, const gfloat inAlign)
713 {
714 	XfdashboardEmblemEffectPrivate		*priv;
715 
716 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self));
717 	g_return_if_fail(inAlign>=0.0f && inAlign<=1.0f);
718 
719 	priv=self->priv;
720 
721 	/* Set value if changed */
722 	if(priv->yAlign!=inAlign)
723 	{
724 		/* Set value */
725 		priv->yAlign=inAlign;
726 
727 		/* Invalidate effect to get it redrawn */
728 		clutter_effect_queue_repaint(CLUTTER_EFFECT(self));
729 
730 		/* Notify about property change */
731 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardEmblemEffectProperties[PROP_Y_ALIGN]);
732 	}
733 }
734 
735 /* Get/set anchor point of emblem */
xfdashboard_emblem_effect_get_anchor_point(XfdashboardEmblemEffect * self)736 XfdashboardAnchorPoint xfdashboard_emblem_effect_get_anchor_point(XfdashboardEmblemEffect *self)
737 {
738 	g_return_val_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self), XFDASHBOARD_ANCHOR_POINT_NORTH_WEST);
739 
740 	return(self->priv->anchorPoint);
741 }
742 
xfdashboard_emblem_effect_set_anchor_point(XfdashboardEmblemEffect * self,const XfdashboardAnchorPoint inAnchorPoint)743 void xfdashboard_emblem_effect_set_anchor_point(XfdashboardEmblemEffect *self, const XfdashboardAnchorPoint inAnchorPoint)
744 {
745 	XfdashboardEmblemEffectPrivate		*priv;
746 
747 	g_return_if_fail(XFDASHBOARD_IS_EMBLEM_EFFECT(self));
748 	g_return_if_fail(inAnchorPoint>=XFDASHBOARD_ANCHOR_POINT_NONE);
749 	g_return_if_fail(inAnchorPoint<=XFDASHBOARD_ANCHOR_POINT_CENTER);
750 
751 	priv=self->priv;
752 
753 	/* Set value if changed */
754 	if(priv->anchorPoint!=inAnchorPoint)
755 	{
756 		/* Set value */
757 		priv->anchorPoint=inAnchorPoint;
758 
759 		/* Invalidate effect to get it redrawn */
760 		clutter_effect_queue_repaint(CLUTTER_EFFECT(self));
761 
762 		/* Notify about property change */
763 		g_object_notify_by_pspec(G_OBJECT(self), XfdashboardEmblemEffectProperties[PROP_ANCHOR_POINT]);
764 	}
765 }
766