1 /*
2 * textbox: An actor representing an editable or read-only text-box
3 * with optional icons
4 *
5 * Copyright 2012-2020 Stephan Haller <nomad@froevel.de>
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., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
21 *
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <libxfdashboard/text-box.h>
30
31 #include <glib/gi18n-lib.h>
32 #include <math.h>
33
34 #include <libxfdashboard/enums.h>
35 #include <libxfdashboard/button.h>
36 #include <libxfdashboard/stylable.h>
37 #include <libxfdashboard/focusable.h>
38 #include <libxfdashboard/focus-manager.h>
39 #include <libxfdashboard/compat.h>
40
41
42 /* Define this class in GObject system */
43 static void _xfdashboard_text_box_focusable_iface_init(XfdashboardFocusableInterface *iface);
44
45 struct _XfdashboardTextBoxPrivate
46 {
47 /* Properties related */
48 gfloat padding;
49 gfloat spacing;
50
51 gboolean isEditable;
52
53 gchar *primaryIconName;
54 gchar *secondaryIconName;
55
56 gchar *textFont;
57 ClutterColor *textColor;
58 ClutterColor *selectionTextColor;
59 ClutterColor *selectionBackgroundColor;
60
61 gboolean hintTextSet;
62 gchar *hintTextFont;
63 ClutterColor *hintTextColor;
64
65 /* Instance related */
66 ClutterActor *actorTextBox;
67 ClutterActor *actorHintLabel;
68
69 gboolean showPrimaryIcon;
70 ClutterActor *actorPrimaryIcon;
71
72 gboolean showSecondaryIcon;
73 ClutterActor *actorSecondaryIcon;
74
75 gboolean selectionColorSet;
76 };
77
78 G_DEFINE_TYPE_WITH_CODE(XfdashboardTextBox,
79 xfdashboard_text_box,
80 XFDASHBOARD_TYPE_BACKGROUND,
81 G_ADD_PRIVATE(XfdashboardTextBox)
82 G_IMPLEMENT_INTERFACE(XFDASHBOARD_TYPE_FOCUSABLE, _xfdashboard_text_box_focusable_iface_init))
83
84 /* Properties */
85 enum
86 {
87 PROP_0,
88
89 PROP_PADDING,
90 PROP_SPACING,
91
92 PROP_EDITABLE,
93
94 PROP_PRIMARY_ICON_NAME,
95 PROP_SECONDARY_ICON_NAME,
96
97 PROP_TEXT,
98 PROP_TEXT_FONT,
99 PROP_TEXT_COLOR,
100 PROP_SELECTION_TEXT_COLOR,
101 PROP_SELECTION_BACKGROUND_COLOR,
102
103 PROP_HINT_TEXT,
104 PROP_HINT_TEXT_FONT,
105 PROP_HINT_TEXT_COLOR,
106 PROP_HINT_TEXT_SET,
107
108 PROP_LAST
109 };
110
111 static GParamSpec* XfdashboardTextBoxProperties[PROP_LAST]={ 0, };
112
113 /* Signals */
114 enum
115 {
116 SIGNAL_TEXT_CHANGED,
117
118 SIGNAL_PRIMARY_ICON_CLICKED,
119 SIGNAL_SECONDARY_ICON_CLICKED,
120
121 SIGNAL_LAST
122 };
123
124 static guint XfdashboardTextBoxSignals[SIGNAL_LAST]={ 0, };
125
126 /* IMPLEMENTATION: Private variables and methods */
127
128 /* Text of editable text box has changed */
_xfdashboard_text_box_on_text_changed(XfdashboardTextBox * self,gpointer inUserData)129 static void _xfdashboard_text_box_on_text_changed(XfdashboardTextBox *self, gpointer inUserData)
130 {
131 XfdashboardTextBoxPrivate *priv;
132 ClutterText *actorText;
133
134 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
135 g_return_if_fail(CLUTTER_IS_TEXT(inUserData));
136
137 priv=self->priv;
138 actorText=CLUTTER_TEXT(inUserData);
139
140 /* Show hint label depending if text box is empty or not */
141 if(xfdashboard_text_box_is_empty(self) && priv->isEditable)
142 {
143 clutter_actor_show(priv->actorHintLabel);
144 }
145 else
146 {
147 clutter_actor_hide(priv->actorHintLabel);
148 }
149
150 /* Emit signal for text changed */
151 g_signal_emit(self, XfdashboardTextBoxSignals[SIGNAL_TEXT_CHANGED], 0, clutter_text_get_text(actorText));
152 }
153
154 /* Primary icon was clicked */
_xfdashboard_text_box_on_primary_icon_clicked(XfdashboardTextBox * self,gpointer inUserData)155 static void _xfdashboard_text_box_on_primary_icon_clicked(XfdashboardTextBox *self,
156 gpointer inUserData)
157 {
158 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
159
160 /* Emit signal for clicking primary icon */
161 g_signal_emit(self, XfdashboardTextBoxSignals[SIGNAL_PRIMARY_ICON_CLICKED], 0);
162 }
163
164 /* Secondary icon was clicked */
_xfdashboard_text_box_on_secondary_icon_clicked(XfdashboardTextBox * self,gpointer inUserData)165 static void _xfdashboard_text_box_on_secondary_icon_clicked(XfdashboardTextBox *self,
166 gpointer inUserData)
167 {
168 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
169
170 /* Emit signal for clicking secondary icon */
171 g_signal_emit(self, XfdashboardTextBoxSignals[SIGNAL_SECONDARY_ICON_CLICKED], 0);
172 }
173
174 /* A key was pressed */
_xfdashboard_text_box_on_key_press_event(ClutterActor * inActor,ClutterEvent * inEvent,gpointer inUserData)175 static gboolean _xfdashboard_text_box_on_key_press_event(ClutterActor *inActor,
176 ClutterEvent *inEvent,
177 gpointer inUserData)
178 {
179 XfdashboardTextBox *self;
180 XfdashboardTextBoxPrivate *priv;
181 gboolean result;
182
183 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(inActor), CLUTTER_EVENT_PROPAGATE);
184
185 self=XFDASHBOARD_TEXT_BOX(inActor);
186 priv=self->priv;
187 result=CLUTTER_EVENT_PROPAGATE;
188
189 /* Push event to real text box if available */
190 if(priv->actorTextBox)
191 {
192 result=clutter_actor_event(priv->actorTextBox, inEvent, FALSE);
193 }
194
195 /* Return event handling result */
196 return(result);
197 }
198
199 /* A key was released */
_xfdashboard_text_box_on_key_release_event(ClutterActor * inActor,ClutterEvent * inEvent,gpointer inUserData)200 static gboolean _xfdashboard_text_box_on_key_release_event(ClutterActor *inActor,
201 ClutterEvent *inEvent,
202 gpointer inUserData)
203 {
204 XfdashboardTextBox *self;
205 XfdashboardTextBoxPrivate *priv;
206 gboolean result;
207
208 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(inActor), CLUTTER_EVENT_PROPAGATE);
209
210 self=XFDASHBOARD_TEXT_BOX(inActor);
211 priv=self->priv;
212 result=CLUTTER_EVENT_PROPAGATE;
213
214 /* Push event to real text box if available */
215 if(priv->actorTextBox)
216 {
217 result=clutter_actor_event(priv->actorTextBox, inEvent, FALSE);
218 }
219
220 /* Return event handling result */
221 return(result);
222 }
223
224
225 /* IMPLEMENTATION: ClutterActor */
226
227 /* Actor got key focus */
_xfdashboard_text_box_key_focus_in(ClutterActor * inActor)228 static void _xfdashboard_text_box_key_focus_in(ClutterActor *inActor)
229 {
230 XfdashboardTextBox *self=XFDASHBOARD_TEXT_BOX(inActor);
231 XfdashboardTextBoxPrivate *priv=self->priv;
232 ClutterStage *stage;
233 XfdashboardFocusManager *focusManager;
234
235 /* Push key focus forward to text box */
236 stage=CLUTTER_STAGE(clutter_actor_get_stage(inActor));
237 clutter_stage_set_key_focus(stage, priv->actorTextBox);
238
239 /* Update focus in focus manager */
240 focusManager=xfdashboard_focus_manager_get_default();
241 xfdashboard_focus_manager_set_focus(focusManager, XFDASHBOARD_FOCUSABLE(self));
242 g_object_unref(focusManager);
243 }
244
245 /* Show all children of this one */
_xfdashboard_text_box_show(ClutterActor * inActor)246 static void _xfdashboard_text_box_show(ClutterActor *inActor)
247 {
248 XfdashboardTextBox *self=XFDASHBOARD_TEXT_BOX(inActor);
249 XfdashboardTextBoxPrivate *priv=self->priv;
250
251 /* Show icons */
252 if(priv->showPrimaryIcon!=FALSE)
253 {
254 clutter_actor_show(CLUTTER_ACTOR(priv->actorPrimaryIcon));
255 }
256
257 if(priv->showSecondaryIcon!=FALSE)
258 {
259 clutter_actor_show(CLUTTER_ACTOR(priv->actorSecondaryIcon));
260 }
261
262 /* Show hint label depending if text box is empty or not */
263 if(xfdashboard_text_box_is_empty(self) && priv->isEditable)
264 {
265 clutter_actor_show(priv->actorHintLabel);
266 }
267 else
268 {
269 clutter_actor_hide(priv->actorHintLabel);
270 }
271
272 clutter_actor_show(CLUTTER_ACTOR(self));
273 }
274
275 /* Get preferred width/height */
_xfdashboard_text_box_get_preferred_height(ClutterActor * self,gfloat inForWidth,gfloat * outMinHeight,gfloat * outNaturalHeight)276 static void _xfdashboard_text_box_get_preferred_height(ClutterActor *self,
277 gfloat inForWidth,
278 gfloat *outMinHeight,
279 gfloat *outNaturalHeight)
280 {
281 XfdashboardTextBoxPrivate *priv=XFDASHBOARD_TEXT_BOX(self)->priv;
282 gfloat minHeight, naturalHeight;
283 gfloat childMinHeight, childNaturalHeight;
284
285 minHeight=naturalHeight=0.0f;
286
287 /* Regardless if text or hint label is visible or not. Both actors' height
288 * will be requested and the larger one used */
289 clutter_actor_get_preferred_height(CLUTTER_ACTOR(priv->actorTextBox),
290 inForWidth,
291 &minHeight, &naturalHeight);
292
293 clutter_actor_get_preferred_height(CLUTTER_ACTOR(priv->actorHintLabel),
294 inForWidth,
295 &childMinHeight, &childNaturalHeight);
296
297 if(childMinHeight>minHeight) minHeight=childMinHeight;
298 if(childNaturalHeight>naturalHeight) naturalHeight=childNaturalHeight;
299
300 // Add padding
301 minHeight+=2*priv->padding;
302 naturalHeight+=2*priv->padding;
303
304 /* Store sizes computed */
305 if(outMinHeight) *outMinHeight=minHeight;
306 if(outNaturalHeight) *outNaturalHeight=naturalHeight;
307 }
308
_xfdashboard_text_box_get_preferred_width(ClutterActor * self,gfloat inForHeight,gfloat * outMinWidth,gfloat * outNaturalWidth)309 static void _xfdashboard_text_box_get_preferred_width(ClutterActor *self,
310 gfloat inForHeight,
311 gfloat *outMinWidth,
312 gfloat *outNaturalWidth)
313 {
314 XfdashboardTextBoxPrivate *priv=XFDASHBOARD_TEXT_BOX(self)->priv;
315 gfloat minWidth, naturalWidth;
316 gfloat childMinWidth, childNaturalWidth;
317 gint numberChildren=0;
318
319 minWidth=naturalWidth=0.0f;
320
321 /* Determine size of primary icon if visible */
322 if(clutter_actor_is_visible(priv->actorPrimaryIcon))
323 {
324 clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorPrimaryIcon),
325 inForHeight,
326 &childMinWidth, &childNaturalWidth);
327
328 minWidth+=childMinWidth;
329 naturalWidth+=childNaturalWidth;
330 numberChildren++;
331 }
332
333 /* Determine size of editable text box if visible */
334 if(clutter_actor_is_visible(priv->actorTextBox))
335 {
336 clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorTextBox),
337 inForHeight,
338 &childMinWidth, &childNaturalWidth);
339
340 minWidth+=childMinWidth;
341 naturalWidth+=childNaturalWidth;
342 numberChildren++;
343 }
344
345 /* Determine size of hint label if visible */
346 if(clutter_actor_is_visible(priv->actorHintLabel))
347 {
348 clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorHintLabel),
349 inForHeight,
350 &childMinWidth, &childNaturalWidth);
351
352 minWidth+=childMinWidth;
353 naturalWidth+=childNaturalWidth;
354 numberChildren++;
355 }
356
357 /* Determine size of secondary icon if visible */
358 if(clutter_actor_is_visible(priv->actorSecondaryIcon))
359 {
360 clutter_actor_get_preferred_width(CLUTTER_ACTOR(priv->actorSecondaryIcon),
361 inForHeight,
362 &childMinWidth, &childNaturalWidth);
363
364 minWidth+=childMinWidth;
365 naturalWidth+=childNaturalWidth;
366 }
367
368 /* Add spacing for each child except the last one */
369 if(numberChildren>1)
370 {
371 numberChildren--;
372 minWidth+=(numberChildren*priv->spacing);
373 naturalWidth+=(numberChildren*priv->spacing);
374 }
375
376 // Add padding
377 minWidth+=2*priv->padding;
378 naturalWidth+=2*priv->padding;
379
380 /* Store sizes computed */
381 if(outMinWidth) *outMinWidth=minWidth;
382 if(outNaturalWidth) *outNaturalWidth=naturalWidth;
383 }
384
385 /* Allocate position and size of actor and its children */
_xfdashboard_text_box_allocate(ClutterActor * self,const ClutterActorBox * inBox,ClutterAllocationFlags inFlags)386 static void _xfdashboard_text_box_allocate(ClutterActor *self,
387 const ClutterActorBox *inBox,
388 ClutterAllocationFlags inFlags)
389 {
390 XfdashboardTextBoxPrivate *priv=XFDASHBOARD_TEXT_BOX(self)->priv;
391 ClutterActorBox *box=NULL;
392 gfloat left, right, top, bottom;
393 gfloat iconWidth, iconHeight;
394
395 /* Chain up to store the allocation of the actor */
396 CLUTTER_ACTOR_CLASS(xfdashboard_text_box_parent_class)->allocate(self, inBox, inFlags);
397
398 /* Initialize bounding box of allocation used in actors */
399 left=top=priv->padding;
400 right=clutter_actor_box_get_width(inBox)-priv->padding;
401 bottom=clutter_actor_box_get_height(inBox)-priv->padding;
402
403 /* Set allocation of primary icon if visible */
404 if(clutter_actor_is_visible(priv->actorPrimaryIcon))
405 {
406 gfloat childRight;
407
408 /* Get scale size of primary icon */
409 iconWidth=iconHeight=0.0f;
410 clutter_actor_get_size(priv->actorPrimaryIcon, &iconWidth, &iconHeight);
411 if(iconHeight>0.0f) iconWidth=(bottom-top)*(iconWidth/iconHeight);
412
413 /* Set allocation */
414 childRight=left+iconWidth;
415
416 box=clutter_actor_box_new(floor(left), floor(top), floor(childRight), floor(bottom));
417 clutter_actor_allocate(CLUTTER_ACTOR(priv->actorPrimaryIcon), box, inFlags);
418 clutter_actor_box_free(box);
419
420 /* Adjust bounding box for next actor */
421 left=childRight+priv->spacing;
422 }
423
424 /* Set allocation of secondary icon if visible */
425 if(clutter_actor_is_visible(priv->actorSecondaryIcon))
426 {
427 gfloat childLeft;
428
429 /* Get scale size of secondary icon */
430 iconWidth=0.0f;
431 clutter_actor_get_size(priv->actorSecondaryIcon, &iconWidth, &iconHeight);
432 if(iconHeight>0.0f) iconWidth=(bottom-top)*(iconWidth/iconHeight);
433
434 /* Set allocation */
435 childLeft=right-iconWidth;
436
437 box=clutter_actor_box_new(floor(childLeft), floor(top), floor(right), floor(bottom));
438 clutter_actor_allocate(CLUTTER_ACTOR(priv->actorSecondaryIcon), box, inFlags);
439 clutter_actor_box_free(box);
440
441 /* Adjust bounding box for next actor */
442 right=childLeft-priv->spacing;
443 }
444
445 /* Set allocation of editable text box if visible */
446 if(clutter_actor_is_visible(priv->actorTextBox))
447 {
448 gfloat textHeight;
449
450 /* Get height of text */
451 clutter_actor_get_preferred_size(CLUTTER_ACTOR(priv->actorTextBox),
452 NULL, NULL,
453 NULL, &textHeight);
454
455 /* Set allocation */
456 box=clutter_actor_box_new(floor(left), floor(bottom-textHeight), floor(right), floor(bottom));
457 clutter_actor_allocate(CLUTTER_ACTOR(priv->actorTextBox), box, inFlags);
458 clutter_actor_box_free(box);
459 }
460
461 /* Set allocation of hint label if visible */
462 if(clutter_actor_is_visible(priv->actorHintLabel))
463 {
464 gfloat textHeight;
465
466 /* Get height of label */
467 clutter_actor_get_preferred_size(CLUTTER_ACTOR(priv->actorHintLabel),
468 NULL, NULL,
469 NULL, &textHeight);
470
471 /* Set allocation */
472 box=clutter_actor_box_new(floor(left), floor(bottom-textHeight), floor(right), floor(bottom));
473 clutter_actor_allocate(CLUTTER_ACTOR(priv->actorHintLabel), box, inFlags);
474 clutter_actor_box_free(box);
475 }
476 }
477
478 /* Destroy this actor */
_xfdashboard_text_box_destroy(ClutterActor * self)479 static void _xfdashboard_text_box_destroy(ClutterActor *self)
480 {
481 /* Destroy each child actor when this actor is destroyed */
482 XfdashboardTextBoxPrivate *priv=XFDASHBOARD_TEXT_BOX(self)->priv;
483
484 if(priv->actorTextBox)
485 {
486 clutter_actor_destroy(CLUTTER_ACTOR(priv->actorTextBox));
487 priv->actorTextBox=NULL;
488 }
489
490 if(priv->actorHintLabel)
491 {
492 clutter_actor_destroy(CLUTTER_ACTOR(priv->actorHintLabel));
493 priv->actorHintLabel=NULL;
494 }
495
496 if(priv->actorPrimaryIcon)
497 {
498 clutter_actor_destroy(CLUTTER_ACTOR(priv->actorPrimaryIcon));
499 priv->actorPrimaryIcon=NULL;
500 }
501
502 if(priv->actorSecondaryIcon)
503 {
504 clutter_actor_destroy(CLUTTER_ACTOR(priv->actorSecondaryIcon));
505 priv->actorSecondaryIcon=NULL;
506 }
507
508 /* Call parent's class destroy method */
509 CLUTTER_ACTOR_CLASS(xfdashboard_text_box_parent_class)->destroy(self);
510 }
511
512 /* IMPLEMENTATION: Interface XfdashboardFocusable */
513
514 /* Determine if actor can get the focus */
_xfdashboard_text_box_focusable_can_focus(XfdashboardFocusable * inFocusable)515 static gboolean _xfdashboard_text_box_focusable_can_focus(XfdashboardFocusable *inFocusable)
516 {
517 XfdashboardTextBox *self;
518 XfdashboardTextBoxPrivate *priv;
519 XfdashboardFocusableInterface *selfIface;
520 XfdashboardFocusableInterface *parentIface;
521
522 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(inFocusable), CLUTTER_EVENT_PROPAGATE);
523
524 self=XFDASHBOARD_TEXT_BOX(inFocusable);
525 priv=self->priv;
526
527 /* Check if actor could be focused at all ... */
528 selfIface=XFDASHBOARD_FOCUSABLE_GET_IFACE(inFocusable);
529 parentIface=g_type_interface_peek_parent(selfIface);
530
531 if(parentIface && parentIface->can_focus)
532 {
533 if(!parentIface->can_focus(inFocusable)) return(FALSE);
534 }
535
536 /* ... then only an editable text box can be focused */
537 if(priv->isEditable) return(TRUE);
538
539 /* If we get here this actor cannot be focused */
540 return(FALSE);
541 }
542
543 /* Interface initialization
544 * Set up default functions
545 */
_xfdashboard_text_box_focusable_iface_init(XfdashboardFocusableInterface * iface)546 void _xfdashboard_text_box_focusable_iface_init(XfdashboardFocusableInterface *iface)
547 {
548 iface->can_focus=_xfdashboard_text_box_focusable_can_focus;
549 }
550
551 /* IMPLEMENTATION: GObject */
552
553 /* Dispose this object */
_xfdashboard_text_box_dispose(GObject * inObject)554 static void _xfdashboard_text_box_dispose(GObject *inObject)
555 {
556 XfdashboardTextBox *self=XFDASHBOARD_TEXT_BOX(inObject);
557 XfdashboardTextBoxPrivate *priv=self->priv;
558
559 /* Release our allocated variables */
560 if(priv->primaryIconName)
561 {
562 g_free(priv->primaryIconName);
563 priv->primaryIconName=NULL;
564 }
565
566 if(priv->secondaryIconName)
567 {
568 g_free(priv->secondaryIconName);
569 priv->secondaryIconName=NULL;
570 }
571
572 if(priv->textFont)
573 {
574 g_free(priv->textFont);
575 priv->textFont=NULL;
576 }
577
578 if(priv->textColor)
579 {
580 clutter_color_free(priv->textColor);
581 priv->textColor=NULL;
582 }
583
584 if(priv->selectionTextColor)
585 {
586 clutter_color_free(priv->selectionTextColor);
587 priv->selectionTextColor=NULL;
588 }
589
590 if(priv->selectionBackgroundColor)
591 {
592 clutter_color_free(priv->selectionBackgroundColor);
593 priv->selectionBackgroundColor=NULL;
594 }
595
596 if(priv->hintTextFont)
597 {
598 g_free(priv->hintTextFont);
599 priv->hintTextFont=NULL;
600 }
601
602 if(priv->hintTextColor)
603 {
604 clutter_color_free(priv->hintTextColor);
605 priv->hintTextColor=NULL;
606 }
607
608 /* Call parent's class dispose method */
609 G_OBJECT_CLASS(xfdashboard_text_box_parent_class)->dispose(inObject);
610 }
611
612 /* Set/get properties */
_xfdashboard_text_box_set_property(GObject * inObject,guint inPropID,const GValue * inValue,GParamSpec * inSpec)613 static void _xfdashboard_text_box_set_property(GObject *inObject,
614 guint inPropID,
615 const GValue *inValue,
616 GParamSpec *inSpec)
617 {
618 XfdashboardTextBox *self=XFDASHBOARD_TEXT_BOX(inObject);
619
620 switch(inPropID)
621 {
622 case PROP_PADDING:
623 xfdashboard_text_box_set_padding(self, g_value_get_float(inValue));
624 break;
625
626 case PROP_SPACING:
627 xfdashboard_text_box_set_spacing(self, g_value_get_float(inValue));
628 break;
629
630 case PROP_EDITABLE:
631 xfdashboard_text_box_set_editable(self, g_value_get_boolean(inValue));
632 break;
633
634 case PROP_PRIMARY_ICON_NAME:
635 xfdashboard_text_box_set_primary_icon(self, g_value_get_string(inValue));
636 break;
637
638 case PROP_SECONDARY_ICON_NAME:
639 xfdashboard_text_box_set_secondary_icon(self, g_value_get_string(inValue));
640 break;
641
642 case PROP_TEXT:
643 xfdashboard_text_box_set_text(self, g_value_get_string(inValue));
644 break;
645
646 case PROP_TEXT_FONT:
647 xfdashboard_text_box_set_text_font(self, g_value_get_string(inValue));
648 break;
649
650 case PROP_TEXT_COLOR:
651 xfdashboard_text_box_set_text_color(self, clutter_value_get_color(inValue));
652 break;
653
654 case PROP_SELECTION_TEXT_COLOR:
655 xfdashboard_text_box_set_selection_text_color(self, clutter_value_get_color(inValue));
656 break;
657
658 case PROP_SELECTION_BACKGROUND_COLOR:
659 xfdashboard_text_box_set_selection_background_color(self, clutter_value_get_color(inValue));
660 break;
661
662 case PROP_HINT_TEXT:
663 xfdashboard_text_box_set_hint_text(self, g_value_get_string(inValue));
664 break;
665
666 case PROP_HINT_TEXT_FONT:
667 xfdashboard_text_box_set_hint_text_font(self, g_value_get_string(inValue));
668 break;
669
670 case PROP_HINT_TEXT_COLOR:
671 xfdashboard_text_box_set_hint_text_color(self, clutter_value_get_color(inValue));
672 break;
673
674 default:
675 G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
676 break;
677 }
678 }
679
_xfdashboard_text_box_get_property(GObject * inObject,guint inPropID,GValue * outValue,GParamSpec * inSpec)680 static void _xfdashboard_text_box_get_property(GObject *inObject,
681 guint inPropID,
682 GValue *outValue,
683 GParamSpec *inSpec)
684 {
685 XfdashboardTextBox *self=XFDASHBOARD_TEXT_BOX(inObject);
686 XfdashboardTextBoxPrivate *priv=self->priv;
687
688 switch(inPropID)
689 {
690 case PROP_PADDING:
691 g_value_set_float(outValue, priv->padding);
692 break;
693
694 case PROP_SPACING:
695 g_value_set_float(outValue, priv->spacing);
696 break;
697
698 case PROP_EDITABLE:
699 g_value_set_boolean(outValue, priv->isEditable);
700 break;
701
702 case PROP_PRIMARY_ICON_NAME:
703 g_value_set_string(outValue, priv->primaryIconName);
704 break;
705
706 case PROP_SECONDARY_ICON_NAME:
707 g_value_set_string(outValue, priv->secondaryIconName);
708 break;
709
710 case PROP_TEXT:
711 g_value_set_string(outValue, clutter_text_get_text(CLUTTER_TEXT(priv->actorTextBox)));
712 break;
713
714 case PROP_TEXT_FONT:
715 g_value_set_string(outValue, priv->textFont);
716 break;
717
718 case PROP_TEXT_COLOR:
719 clutter_value_set_color(outValue, priv->textColor);
720 break;
721
722 case PROP_SELECTION_TEXT_COLOR:
723 clutter_value_set_color(outValue, priv->selectionTextColor);
724 break;
725
726 case PROP_SELECTION_BACKGROUND_COLOR:
727 clutter_value_set_color(outValue, priv->selectionBackgroundColor);
728 break;
729
730 case PROP_HINT_TEXT:
731 g_value_set_string(outValue, clutter_text_get_text(CLUTTER_TEXT(priv->actorHintLabel)));
732 break;
733
734 case PROP_HINT_TEXT_FONT:
735 g_value_set_string(outValue, priv->hintTextFont);
736 break;
737
738 case PROP_HINT_TEXT_COLOR:
739 clutter_value_set_color(outValue, priv->hintTextColor);
740 break;
741
742 case PROP_HINT_TEXT_SET:
743 g_value_set_boolean(outValue, priv->hintTextSet);
744 break;
745
746 default:
747 G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec);
748 break;
749 }
750 }
751
752 /* Class initialization
753 * Override functions in parent classes and define properties
754 * and signals
755 */
xfdashboard_text_box_class_init(XfdashboardTextBoxClass * klass)756 static void xfdashboard_text_box_class_init(XfdashboardTextBoxClass *klass)
757 {
758 XfdashboardActorClass *actorClass=XFDASHBOARD_ACTOR_CLASS(klass);
759 ClutterActorClass *clutterActorClass=CLUTTER_ACTOR_CLASS(klass);
760 GObjectClass *gobjectClass=G_OBJECT_CLASS(klass);
761
762 /* Override functions */
763 gobjectClass->dispose=_xfdashboard_text_box_dispose;
764 gobjectClass->set_property=_xfdashboard_text_box_set_property;
765 gobjectClass->get_property=_xfdashboard_text_box_get_property;
766
767 clutterActorClass->show_all=_xfdashboard_text_box_show;
768 clutterActorClass->get_preferred_width=_xfdashboard_text_box_get_preferred_width;
769 clutterActorClass->get_preferred_height=_xfdashboard_text_box_get_preferred_height;
770 clutterActorClass->allocate=_xfdashboard_text_box_allocate;
771 clutterActorClass->destroy=_xfdashboard_text_box_destroy;
772 clutterActorClass->key_focus_in=_xfdashboard_text_box_key_focus_in;
773
774 /* Define properties */
775 XfdashboardTextBoxProperties[PROP_PADDING]=
776 g_param_spec_float("padding",
777 "Padding",
778 "Padding between background and elements",
779 0.0f, G_MAXFLOAT,
780 0.0f,
781 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
782
783 XfdashboardTextBoxProperties[PROP_SPACING]=
784 g_param_spec_float("spacing",
785 "Spacing",
786 "Spacing between text and icon",
787 0.0f, G_MAXFLOAT,
788 0.0f,
789 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
790
791 XfdashboardTextBoxProperties[PROP_EDITABLE]=
792 g_param_spec_boolean("editable",
793 "Editable",
794 "Flag to set if text is editable",
795 FALSE,
796 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
797
798 XfdashboardTextBoxProperties[PROP_PRIMARY_ICON_NAME]=
799 g_param_spec_string("primary-icon-name",
800 "Primary icon name",
801 "Themed icon name or file name of primary icon shown left of text box",
802 NULL,
803 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
804
805 XfdashboardTextBoxProperties[PROP_SECONDARY_ICON_NAME]=
806 g_param_spec_string("secondary-icon-name",
807 "Secondary icon name",
808 "Themed icon name or file name of secondary icon shown right of text box",
809 NULL,
810 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
811
812 XfdashboardTextBoxProperties[PROP_TEXT]=
813 g_param_spec_string("text",
814 "Text",
815 "Text of editable text box",
816 N_(""),
817 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
818
819 XfdashboardTextBoxProperties[PROP_TEXT_FONT]=
820 g_param_spec_string("text-font",
821 "Text font",
822 "Font of editable text box",
823 NULL,
824 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
825
826 XfdashboardTextBoxProperties[PROP_TEXT_COLOR]=
827 clutter_param_spec_color("text-color",
828 "Text color",
829 "Color of text in editable text box",
830 NULL,
831 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
832
833
834 XfdashboardTextBoxProperties[PROP_SELECTION_TEXT_COLOR]=
835 clutter_param_spec_color("selection-text-color",
836 "Selection text color",
837 "Color of text of selected text",
838 NULL,
839 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
840
841 XfdashboardTextBoxProperties[PROP_SELECTION_BACKGROUND_COLOR]=
842 clutter_param_spec_color("selection-background-color",
843 "Selection background color",
844 "Color of background of selected text",
845 NULL,
846 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
847
848 XfdashboardTextBoxProperties[PROP_HINT_TEXT]=
849 g_param_spec_string("hint-text",
850 "Hint text",
851 "Hint text shown if editable text box is empty",
852 NULL,
853 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
854
855 XfdashboardTextBoxProperties[PROP_HINT_TEXT_FONT]=
856 g_param_spec_string("hint-text-font",
857 "Hint text font",
858 "Font of hint text shown if editable text box is empty",
859 NULL,
860 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
861
862 XfdashboardTextBoxProperties[PROP_HINT_TEXT_COLOR]=
863 clutter_param_spec_color("hint-text-color",
864 "Hint text color",
865 "Color of hint text shown if editable text box is empty",
866 NULL,
867 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
868
869 XfdashboardTextBoxProperties[PROP_HINT_TEXT_SET]=
870 g_param_spec_boolean("hint-text-set",
871 "Hint text set",
872 "Flag indicating if a hint text was set",
873 FALSE,
874 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
875
876 g_object_class_install_properties(gobjectClass, PROP_LAST, XfdashboardTextBoxProperties);
877
878 /* Define stylable properties */
879 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_PADDING]);
880 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_SPACING]);
881 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_PRIMARY_ICON_NAME]);
882 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_SECONDARY_ICON_NAME]);
883 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_TEXT_FONT]);
884 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_TEXT_COLOR]);
885 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_SELECTION_BACKGROUND_COLOR]);
886 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_HINT_TEXT_FONT]);
887 xfdashboard_actor_install_stylable_property(actorClass, XfdashboardTextBoxProperties[PROP_HINT_TEXT_COLOR]);
888
889 /* Define signals */
890 XfdashboardTextBoxSignals[SIGNAL_TEXT_CHANGED]=
891 g_signal_new("text-changed",
892 G_TYPE_FROM_CLASS(klass),
893 G_SIGNAL_RUN_LAST,
894 G_STRUCT_OFFSET(XfdashboardTextBoxClass, text_changed),
895 NULL,
896 NULL,
897 g_cclosure_marshal_VOID__STRING,
898 G_TYPE_NONE,
899 1,
900 G_TYPE_STRING);
901
902 XfdashboardTextBoxSignals[SIGNAL_PRIMARY_ICON_CLICKED]=
903 g_signal_new("primary-icon-clicked",
904 G_TYPE_FROM_CLASS(klass),
905 G_SIGNAL_RUN_LAST,
906 G_STRUCT_OFFSET(XfdashboardTextBoxClass, primary_icon_clicked),
907 NULL,
908 NULL,
909 g_cclosure_marshal_VOID__VOID,
910 G_TYPE_NONE,
911 0);
912
913 XfdashboardTextBoxSignals[SIGNAL_SECONDARY_ICON_CLICKED]=
914 g_signal_new("secondary-icon-clicked",
915 G_TYPE_FROM_CLASS(klass),
916 G_SIGNAL_RUN_LAST,
917 G_STRUCT_OFFSET(XfdashboardTextBoxClass, secondary_icon_clicked),
918 NULL,
919 NULL,
920 g_cclosure_marshal_VOID__VOID,
921 G_TYPE_NONE,
922 0);
923 }
924
925 /* Object initialization
926 * Create private structure and set up default values
927 */
xfdashboard_text_box_init(XfdashboardTextBox * self)928 static void xfdashboard_text_box_init(XfdashboardTextBox *self)
929 {
930 XfdashboardTextBoxPrivate *priv;
931
932 priv=self->priv=xfdashboard_text_box_get_instance_private(self);
933
934 /* This actor is react on events */
935 clutter_actor_set_reactive(CLUTTER_ACTOR(self), TRUE);
936
937 /* Set up default values */
938 priv->padding=0.0f;
939 priv->spacing=0.0f;
940 priv->isEditable=FALSE;
941 priv->primaryIconName=NULL;
942 priv->secondaryIconName=NULL;
943 priv->textFont=NULL;
944 priv->textColor=NULL;
945 priv->selectionTextColor=NULL;
946 priv->selectionBackgroundColor=NULL;
947 priv->hintTextFont=NULL;
948 priv->hintTextColor=NULL;
949 priv->showPrimaryIcon=FALSE;
950 priv->showSecondaryIcon=FALSE;
951 priv->selectionColorSet=FALSE;
952 priv->hintTextSet=FALSE;
953
954 /* Create actors */
955 g_signal_connect(self, "key-press-event", G_CALLBACK(_xfdashboard_text_box_on_key_press_event), NULL);
956 g_signal_connect(self, "key-release-event", G_CALLBACK(_xfdashboard_text_box_on_key_release_event), NULL);
957
958 priv->actorPrimaryIcon=xfdashboard_button_new();
959 xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->actorPrimaryIcon), "primary-icon");
960 clutter_actor_set_reactive(priv->actorPrimaryIcon, TRUE);
961 clutter_actor_hide(priv->actorPrimaryIcon);
962 clutter_actor_add_child(CLUTTER_ACTOR(self), priv->actorPrimaryIcon);
963 g_signal_connect_swapped(priv->actorPrimaryIcon, "clicked", G_CALLBACK(_xfdashboard_text_box_on_primary_icon_clicked), self);
964
965 priv->actorSecondaryIcon=xfdashboard_button_new();
966 xfdashboard_stylable_add_class(XFDASHBOARD_STYLABLE(priv->actorSecondaryIcon), "secondary-icon");
967 clutter_actor_set_reactive(priv->actorSecondaryIcon, TRUE);
968 clutter_actor_hide(priv->actorSecondaryIcon);
969 clutter_actor_add_child(CLUTTER_ACTOR(self), priv->actorSecondaryIcon);
970 g_signal_connect_swapped(priv->actorSecondaryIcon, "clicked", G_CALLBACK(_xfdashboard_text_box_on_secondary_icon_clicked), self);
971
972 priv->actorTextBox=clutter_text_new();
973 clutter_actor_add_child(CLUTTER_ACTOR(self), priv->actorTextBox);
974 clutter_actor_set_reactive(priv->actorTextBox, TRUE);
975 clutter_text_set_selectable(CLUTTER_TEXT(priv->actorTextBox), FALSE);
976 clutter_text_set_editable(CLUTTER_TEXT(priv->actorTextBox), FALSE);
977 clutter_text_set_single_line_mode(CLUTTER_TEXT(priv->actorTextBox), TRUE);
978 g_signal_connect_swapped(priv->actorTextBox, "text-changed", G_CALLBACK(_xfdashboard_text_box_on_text_changed), self);
979
980 priv->actorHintLabel=clutter_text_new();
981 clutter_actor_add_child(CLUTTER_ACTOR(self), priv->actorHintLabel);
982 clutter_actor_set_reactive(priv->actorHintLabel, FALSE);
983 clutter_text_set_selectable(CLUTTER_TEXT(priv->actorHintLabel), FALSE);
984 clutter_text_set_editable(CLUTTER_TEXT(priv->actorHintLabel), FALSE);
985 clutter_text_set_single_line_mode(CLUTTER_TEXT(priv->actorHintLabel), TRUE);
986 clutter_actor_hide(priv->actorHintLabel);
987 }
988
989 /* IMPLEMENTATION: Public API */
990
991 /* Create new actor */
xfdashboard_text_box_new(void)992 ClutterActor* xfdashboard_text_box_new(void)
993 {
994 return(g_object_new(XFDASHBOARD_TYPE_TEXT_BOX, NULL));
995 }
996
997 /* Get/set padding of background to text and icon actors */
xfdashboard_text_box_get_padding(XfdashboardTextBox * self)998 gfloat xfdashboard_text_box_get_padding(XfdashboardTextBox *self)
999 {
1000 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), 0);
1001
1002 return(self->priv->padding);
1003 }
1004
xfdashboard_text_box_set_padding(XfdashboardTextBox * self,gfloat inPadding)1005 void xfdashboard_text_box_set_padding(XfdashboardTextBox *self, gfloat inPadding)
1006 {
1007 XfdashboardTextBoxPrivate *priv;
1008
1009 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1010 g_return_if_fail(inPadding>=0.0f);
1011
1012 priv=self->priv;
1013
1014 /* Set value if changed */
1015 if(priv->padding!=inPadding)
1016 {
1017 priv->padding=inPadding;
1018 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1019
1020 /* Notify about property change */
1021 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_PADDING]);
1022 }
1023 }
1024
1025 /* Get/set spacing between text and icon actors */
xfdashboard_text_box_get_spacing(XfdashboardTextBox * self)1026 gfloat xfdashboard_text_box_get_spacing(XfdashboardTextBox *self)
1027 {
1028 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), 0);
1029
1030 return(self->priv->spacing);
1031 }
1032
xfdashboard_text_box_set_spacing(XfdashboardTextBox * self,gfloat inSpacing)1033 void xfdashboard_text_box_set_spacing(XfdashboardTextBox *self, gfloat inSpacing)
1034 {
1035 XfdashboardTextBoxPrivate *priv;
1036
1037 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1038 g_return_if_fail(inSpacing>=0.0f);
1039
1040 priv=self->priv;
1041
1042 /* Set value if changed */
1043 if(priv->spacing!=inSpacing)
1044 {
1045 priv->spacing=inSpacing;
1046 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1047
1048 /* Notify about property change */
1049 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_SPACING]);
1050 }
1051 }
1052
1053 /* Get/set flag to mark text editable */
xfdashboard_text_box_get_editable(XfdashboardTextBox * self)1054 gboolean xfdashboard_text_box_get_editable(XfdashboardTextBox *self)
1055 {
1056 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), FALSE);
1057
1058 return(self->priv->isEditable);
1059 }
1060
xfdashboard_text_box_set_editable(XfdashboardTextBox * self,gboolean isEditable)1061 void xfdashboard_text_box_set_editable(XfdashboardTextBox *self, gboolean isEditable)
1062 {
1063 XfdashboardTextBoxPrivate *priv;
1064 const gchar *text;
1065
1066 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1067
1068 priv=self->priv;
1069
1070 /* Set value if changed */
1071 if(priv->isEditable!=isEditable)
1072 {
1073 priv->isEditable=isEditable;
1074 if(priv->isEditable) xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "editable");
1075 else xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(self), "editable");
1076
1077 /* Set up actors */
1078 clutter_text_set_selectable(CLUTTER_TEXT(priv->actorTextBox), priv->isEditable);
1079 clutter_text_set_editable(CLUTTER_TEXT(priv->actorTextBox), priv->isEditable);
1080
1081 text=clutter_text_get_text(CLUTTER_TEXT(priv->actorTextBox));
1082 if((text==NULL || *text==0) && priv->isEditable)
1083 {
1084 clutter_actor_show(priv->actorHintLabel);
1085 }
1086 else
1087 {
1088 clutter_actor_hide(priv->actorHintLabel);
1089 }
1090
1091 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1092
1093 /* Notify about property change */
1094 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_EDITABLE]);
1095 }
1096 }
1097
1098 /* Get/set text of editable text box */
xfdashboard_text_box_is_empty(XfdashboardTextBox * self)1099 gboolean xfdashboard_text_box_is_empty(XfdashboardTextBox *self)
1100 {
1101 const gchar *text;
1102
1103 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), TRUE);
1104
1105 text=clutter_text_get_text(CLUTTER_TEXT(self->priv->actorTextBox));
1106
1107 return(text==NULL || *text==0);
1108 }
1109
xfdashboard_text_box_get_length(XfdashboardTextBox * self)1110 gint xfdashboard_text_box_get_length(XfdashboardTextBox *self)
1111 {
1112 const gchar *text;
1113 gint textLength=0;
1114
1115 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), 0);
1116
1117 text=clutter_text_get_text(CLUTTER_TEXT(self->priv->actorTextBox));
1118 if(text) textLength=strlen(text);
1119
1120 return(textLength);
1121 }
1122
xfdashboard_text_box_get_text(XfdashboardTextBox * self)1123 const gchar* xfdashboard_text_box_get_text(XfdashboardTextBox *self)
1124 {
1125 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1126
1127 return(clutter_text_get_text(CLUTTER_TEXT(self->priv->actorTextBox)));
1128 }
1129
xfdashboard_text_box_set_text(XfdashboardTextBox * self,const gchar * inMarkupText)1130 void xfdashboard_text_box_set_text(XfdashboardTextBox *self, const gchar *inMarkupText)
1131 {
1132 XfdashboardTextBoxPrivate *priv;
1133 const gchar *text;
1134
1135 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1136
1137 priv=self->priv;
1138
1139 /* Set value if changed */
1140 if(g_strcmp0(clutter_text_get_text(CLUTTER_TEXT(priv->actorTextBox)), inMarkupText)!=0)
1141 {
1142 clutter_text_set_markup(CLUTTER_TEXT(priv->actorTextBox), inMarkupText);
1143
1144 text=clutter_text_get_text(CLUTTER_TEXT(priv->actorTextBox));
1145 if((text==NULL || *text==0) && priv->isEditable)
1146 {
1147 clutter_actor_show(priv->actorHintLabel);
1148 }
1149 else
1150 {
1151 clutter_actor_hide(priv->actorHintLabel);
1152 }
1153
1154 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1155
1156 /* Notify about property change */
1157 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_TEXT]);
1158 }
1159 }
1160
xfdashboard_text_box_set_text_va(XfdashboardTextBox * self,const gchar * inFormat,...)1161 void xfdashboard_text_box_set_text_va(XfdashboardTextBox *self, const gchar *inFormat, ...)
1162 {
1163 gchar *text;
1164 va_list args;
1165
1166 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1167
1168 /* Build formatted text to set */
1169 va_start(args, inFormat);
1170 text=g_strdup_vprintf(inFormat, args);
1171 va_end(args);
1172
1173 /* Set formatted text */
1174 xfdashboard_text_box_set_text(self, text);
1175
1176 /* Release allocated resources */
1177 g_free(text);
1178 }
1179
1180 /* Get/set font of editable text box */
xfdashboard_text_box_get_text_font(XfdashboardTextBox * self)1181 const gchar* xfdashboard_text_box_get_text_font(XfdashboardTextBox *self)
1182 {
1183 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1184
1185 return(self->priv->actorTextBox!=NULL ? self->priv->textFont : NULL);
1186 }
1187
xfdashboard_text_box_set_text_font(XfdashboardTextBox * self,const gchar * inFont)1188 void xfdashboard_text_box_set_text_font(XfdashboardTextBox *self, const gchar *inFont)
1189 {
1190 XfdashboardTextBoxPrivate *priv;
1191
1192 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1193
1194 priv=self->priv;
1195
1196 /* Set value if changed */
1197 if(g_strcmp0(priv->textFont, inFont)!=0)
1198 {
1199 if(priv->textFont) g_free(priv->textFont);
1200 priv->textFont=g_strdup(inFont);
1201
1202 clutter_text_set_font_name(CLUTTER_TEXT(priv->actorTextBox), priv->textFont);
1203 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1204
1205 /* Notify about property change */
1206 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_TEXT_FONT]);
1207 }
1208 }
1209
1210 /* Get/set color of text in editable text box */
xfdashboard_text_box_get_text_color(XfdashboardTextBox * self)1211 const ClutterColor* xfdashboard_text_box_get_text_color(XfdashboardTextBox *self)
1212 {
1213 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1214
1215 return(self->priv->textColor);
1216 }
1217
xfdashboard_text_box_set_text_color(XfdashboardTextBox * self,const ClutterColor * inColor)1218 void xfdashboard_text_box_set_text_color(XfdashboardTextBox *self, const ClutterColor *inColor)
1219 {
1220 XfdashboardTextBoxPrivate *priv;
1221 ClutterColor selectionColor;
1222
1223 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1224 g_return_if_fail(inColor);
1225
1226 priv=self->priv;
1227
1228 /* Set value if changed */
1229 if(!priv->textColor || !clutter_color_equal(inColor, priv->textColor))
1230 {
1231 if(priv->textColor) clutter_color_free(priv->textColor);
1232 priv->textColor=clutter_color_copy(inColor);
1233
1234 clutter_text_set_color(CLUTTER_TEXT(priv->actorTextBox), priv->textColor);
1235
1236 /* Selection text and background color is inverted text color if not set */
1237 if(!priv->selectionColorSet)
1238 {
1239 selectionColor.red=0xff-priv->textColor->red;
1240 selectionColor.green=0xff-priv->textColor->green;
1241 selectionColor.blue=0xff-priv->textColor->blue;
1242 selectionColor.alpha=priv->textColor->alpha;
1243 clutter_text_set_selected_text_color(CLUTTER_TEXT(priv->actorTextBox), &selectionColor);
1244
1245 /* Selection color is the same as text color */
1246 clutter_text_set_selection_color(CLUTTER_TEXT(priv->actorTextBox), priv->textColor);
1247 }
1248
1249 /* Redraw actor in new color */
1250 clutter_actor_queue_redraw(CLUTTER_ACTOR(self));
1251
1252 /* Notify about property change */
1253 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_TEXT_COLOR]);
1254 }
1255 }
1256
1257 /* Get/set color of text of selected text */
xfdashboard_text_box_get_selection_text_color(XfdashboardTextBox * self)1258 const ClutterColor* xfdashboard_text_box_get_selection_text_color(XfdashboardTextBox *self)
1259 {
1260 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1261
1262 return(self->priv->selectionTextColor);
1263 }
1264
xfdashboard_text_box_set_selection_text_color(XfdashboardTextBox * self,const ClutterColor * inColor)1265 void xfdashboard_text_box_set_selection_text_color(XfdashboardTextBox *self, const ClutterColor *inColor)
1266 {
1267 XfdashboardTextBoxPrivate *priv;
1268 ClutterColor selectionColor;
1269
1270 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1271
1272 priv=self->priv;
1273
1274 /* Set value if changed */
1275 if(priv->selectionTextColor!=inColor ||
1276 (priv->selectionTextColor &&
1277 inColor &&
1278 !clutter_color_equal(inColor, priv->selectionTextColor)))
1279 {
1280 /* Freeze notifications and collect them */
1281 g_object_freeze_notify(G_OBJECT(self));
1282
1283 /* Release old color */
1284 if(priv->selectionTextColor)
1285 {
1286 clutter_color_free(priv->selectionTextColor);
1287 priv->selectionTextColor=NULL;
1288
1289 /* Check if any selection color is set */
1290 priv->selectionColorSet=((priv->selectionTextColor && priv->selectionBackgroundColor) ? TRUE : FALSE);
1291
1292 /* Notify about property change */
1293 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_SELECTION_TEXT_COLOR]);
1294 }
1295
1296 /* Set new color if available */
1297 if(inColor)
1298 {
1299 priv->selectionTextColor=clutter_color_copy(inColor);
1300 clutter_text_set_selected_text_color(CLUTTER_TEXT(priv->actorTextBox), priv->selectionTextColor);
1301
1302 /* Any selection color was set */
1303 priv->selectionColorSet=TRUE;
1304
1305 /* Notify about property change */
1306 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_SELECTION_TEXT_COLOR]);
1307 }
1308
1309 /* Selection text and background color is inverted text color if not set */
1310 if(!priv->selectionColorSet)
1311 {
1312 selectionColor.red=0xff-priv->textColor->red;
1313 selectionColor.green=0xff-priv->textColor->green;
1314 selectionColor.blue=0xff-priv->textColor->blue;
1315 selectionColor.alpha=priv->textColor->alpha;
1316 clutter_text_set_selected_text_color(CLUTTER_TEXT(priv->actorTextBox), &selectionColor);
1317
1318 /* Selection color is the same as text color */
1319 clutter_text_set_selection_color(CLUTTER_TEXT(priv->actorTextBox), priv->textColor);
1320 }
1321
1322 /* Redraw actor in new color */
1323 clutter_actor_queue_redraw(CLUTTER_ACTOR(self));
1324
1325 /* Thaw notifications and send them now */
1326 g_object_thaw_notify(G_OBJECT(self));
1327 }
1328 }
1329
1330 /* Get/set color of background of selected text */
xfdashboard_text_box_get_selection_background_color(XfdashboardTextBox * self)1331 const ClutterColor* xfdashboard_text_box_get_selection_background_color(XfdashboardTextBox *self)
1332 {
1333 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1334
1335 return(self->priv->selectionBackgroundColor);
1336 }
1337
xfdashboard_text_box_set_selection_background_color(XfdashboardTextBox * self,const ClutterColor * inColor)1338 void xfdashboard_text_box_set_selection_background_color(XfdashboardTextBox *self, const ClutterColor *inColor)
1339 {
1340 XfdashboardTextBoxPrivate *priv;
1341 ClutterColor selectionColor;
1342
1343 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1344
1345 priv=self->priv;
1346
1347 /* Set value if changed */
1348 if(priv->selectionBackgroundColor!=inColor ||
1349 (priv->selectionBackgroundColor &&
1350 inColor &&
1351 !clutter_color_equal(inColor, priv->selectionBackgroundColor)))
1352 {
1353 /* Freeze notifications and collect them */
1354 g_object_freeze_notify(G_OBJECT(self));
1355
1356 /* Release old color */
1357 if(priv->selectionBackgroundColor)
1358 {
1359 clutter_color_free(priv->selectionBackgroundColor);
1360 priv->selectionBackgroundColor=NULL;
1361
1362 /* Check if any selection color is set */
1363 priv->selectionColorSet=((priv->selectionTextColor && priv->selectionBackgroundColor) ? TRUE : FALSE);
1364
1365 /* Notify about property change */
1366 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_SELECTION_BACKGROUND_COLOR]);
1367 }
1368
1369 /* Set new color if available */
1370 if(inColor)
1371 {
1372 priv->selectionBackgroundColor=clutter_color_copy(inColor);
1373 clutter_text_set_selection_color(CLUTTER_TEXT(priv->actorTextBox), priv->selectionBackgroundColor);
1374
1375 /* Any selection color was set */
1376 priv->selectionColorSet=TRUE;
1377
1378 /* Notify about property change */
1379 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_SELECTION_BACKGROUND_COLOR]);
1380 }
1381
1382 /* Selection text and background color is inverted text color if not set */
1383 if(!priv->selectionColorSet)
1384 {
1385 selectionColor.red=0xff-priv->textColor->red;
1386 selectionColor.green=0xff-priv->textColor->green;
1387 selectionColor.blue=0xff-priv->textColor->blue;
1388 selectionColor.alpha=priv->textColor->alpha;
1389 clutter_text_set_selected_text_color(CLUTTER_TEXT(priv->actorTextBox), &selectionColor);
1390
1391 /* Selection color is the same as text color */
1392 clutter_text_set_selection_color(CLUTTER_TEXT(priv->actorTextBox), priv->textColor);
1393 }
1394
1395 /* Redraw actor in new color */
1396 clutter_actor_queue_redraw(CLUTTER_ACTOR(self));
1397
1398 /* Thaw notifications and send them now */
1399 g_object_thaw_notify(G_OBJECT(self));
1400 }
1401 }
1402
1403 /* Determine if a hint label was set */
xfdashboard_text_box_is_hint_text_set(XfdashboardTextBox * self)1404 gboolean xfdashboard_text_box_is_hint_text_set(XfdashboardTextBox *self)
1405 {
1406 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), FALSE);
1407
1408 return(self->priv->hintTextSet);
1409 }
1410
1411 /* Get/set text of hint label */
xfdashboard_text_box_get_hint_text(XfdashboardTextBox * self)1412 const gchar* xfdashboard_text_box_get_hint_text(XfdashboardTextBox *self)
1413 {
1414 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1415
1416 return(clutter_text_get_text(CLUTTER_TEXT(self->priv->actorHintLabel)));
1417 }
1418
xfdashboard_text_box_set_hint_text(XfdashboardTextBox * self,const gchar * inMarkupText)1419 void xfdashboard_text_box_set_hint_text(XfdashboardTextBox *self, const gchar *inMarkupText)
1420 {
1421 XfdashboardTextBoxPrivate *priv;
1422 gboolean newHintTextSet;
1423
1424 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1425
1426 priv=self->priv;
1427 newHintTextSet=FALSE;
1428
1429 /* Freeze notification */
1430 g_object_freeze_notify(G_OBJECT(self));
1431
1432 /* Set value if changed */
1433 if(g_strcmp0(clutter_text_get_text(CLUTTER_TEXT(priv->actorHintLabel)), inMarkupText)!=0)
1434 {
1435 /* Set value */
1436 clutter_text_set_markup(CLUTTER_TEXT(priv->actorHintLabel), inMarkupText);
1437 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1438
1439 /* Notify about property change */
1440 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_HINT_TEXT]);
1441 }
1442
1443 /* Check if a hint text was set and if read-only property changes.
1444 * Note: NULL string will unset "hint-text-set" property (set to FALSE)
1445 */
1446 if(inMarkupText) newHintTextSet=TRUE;
1447 if(newHintTextSet!=priv->hintTextSet)
1448 {
1449 /* Set flag */
1450 priv->hintTextSet=newHintTextSet;
1451
1452 /* Notify about property change */
1453 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_HINT_TEXT_SET]);
1454 }
1455
1456 /* Thaw notification */
1457 g_object_thaw_notify(G_OBJECT(self));
1458 }
1459
xfdashboard_text_box_set_hint_text_va(XfdashboardTextBox * self,const gchar * inFormat,...)1460 void xfdashboard_text_box_set_hint_text_va(XfdashboardTextBox *self, const gchar *inFormat, ...)
1461 {
1462 gchar *text;
1463 va_list args;
1464
1465 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1466
1467 /* Build formatted text to set */
1468 va_start(args, inFormat);
1469 text=g_strdup_vprintf(inFormat, args);
1470 va_end(args);
1471
1472 /* Set formatted text */
1473 xfdashboard_text_box_set_hint_text(self, text);
1474
1475 /* Release allocated resources */
1476 g_free(text);
1477 }
1478
1479 /* Get/set font of hint label */
xfdashboard_text_box_get_hint_text_font(XfdashboardTextBox * self)1480 const gchar* xfdashboard_text_box_get_hint_text_font(XfdashboardTextBox *self)
1481 {
1482 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1483
1484 return(self->priv->hintTextFont);
1485 }
1486
xfdashboard_text_box_set_hint_text_font(XfdashboardTextBox * self,const gchar * inFont)1487 void xfdashboard_text_box_set_hint_text_font(XfdashboardTextBox *self, const gchar *inFont)
1488 {
1489 XfdashboardTextBoxPrivate *priv;
1490
1491 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1492
1493 priv=self->priv;
1494
1495 /* Set value if changed */
1496 if(g_strcmp0(priv->hintTextFont, inFont)!=0)
1497 {
1498 if(priv->hintTextFont) g_free(priv->hintTextFont);
1499 priv->hintTextFont=g_strdup(inFont);
1500
1501 clutter_text_set_font_name(CLUTTER_TEXT(priv->actorHintLabel), priv->hintTextFont);
1502 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1503
1504 /* Notify about property change */
1505 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_HINT_TEXT_FONT]);
1506 }
1507 }
1508
1509 /* Get/set color of text in hint label */
xfdashboard_text_box_get_hint_text_color(XfdashboardTextBox * self)1510 const ClutterColor* xfdashboard_text_box_get_hint_text_color(XfdashboardTextBox *self)
1511 {
1512 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1513
1514 return(self->priv->hintTextColor);
1515 }
1516
xfdashboard_text_box_set_hint_text_color(XfdashboardTextBox * self,const ClutterColor * inColor)1517 void xfdashboard_text_box_set_hint_text_color(XfdashboardTextBox *self, const ClutterColor *inColor)
1518 {
1519 XfdashboardTextBoxPrivate *priv;
1520
1521 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1522 g_return_if_fail(inColor);
1523
1524 priv=self->priv;
1525
1526 /* Set value if changed */
1527 if(!priv->hintTextColor || !clutter_color_equal(inColor, priv->hintTextColor))
1528 {
1529 if(priv->hintTextColor) clutter_color_free(priv->hintTextColor);
1530 priv->hintTextColor=clutter_color_copy(inColor);
1531
1532 clutter_text_set_color(CLUTTER_TEXT(priv->actorHintLabel), priv->hintTextColor);
1533 clutter_actor_queue_redraw(CLUTTER_ACTOR(self));
1534
1535 /* Notify about property change */
1536 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_HINT_TEXT_COLOR]);
1537 }
1538 }
1539
1540 /* Get/set primary icon */
xfdashboard_text_box_get_primary_icon(XfdashboardTextBox * self)1541 const gchar* xfdashboard_text_box_get_primary_icon(XfdashboardTextBox *self)
1542 {
1543 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1544
1545 return(self->priv->primaryIconName);
1546 }
1547
xfdashboard_text_box_set_primary_icon(XfdashboardTextBox * self,const gchar * inIconName)1548 void xfdashboard_text_box_set_primary_icon(XfdashboardTextBox *self, const gchar *inIconName)
1549 {
1550 XfdashboardTextBoxPrivate *priv;
1551
1552 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1553 g_return_if_fail(!inIconName || strlen(inIconName)>0);
1554
1555 priv=self->priv;
1556
1557 /* Set themed icon name or icon file name for primary icon */
1558 if(g_strcmp0(priv->primaryIconName, inIconName)!=0)
1559 {
1560 /* Set new primary icon name */
1561 if(priv->primaryIconName)
1562 {
1563 g_free(priv->primaryIconName);
1564 priv->primaryIconName=NULL;
1565 }
1566
1567 if(inIconName)
1568 {
1569 /* Load and set new icon */
1570 priv->primaryIconName=g_strdup(inIconName);
1571 xfdashboard_label_set_icon_name(XFDASHBOARD_LABEL(priv->actorPrimaryIcon), priv->primaryIconName);
1572
1573 /* Show icon */
1574 priv->showPrimaryIcon=TRUE;
1575 clutter_actor_show(priv->actorPrimaryIcon);
1576 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1577 }
1578 else
1579 {
1580 /* Hide icon */
1581 priv->showPrimaryIcon=FALSE;
1582 clutter_actor_hide(priv->actorPrimaryIcon);
1583 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1584 }
1585
1586 /* Notify about property change */
1587 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_PRIMARY_ICON_NAME]);
1588 }
1589 }
1590
1591 /* Get/set secondary icon */
xfdashboard_text_box_get_secondary_icon(XfdashboardTextBox * self)1592 const gchar* xfdashboard_text_box_get_secondary_icon(XfdashboardTextBox *self)
1593 {
1594 g_return_val_if_fail(XFDASHBOARD_IS_TEXT_BOX(self), NULL);
1595
1596 return(self->priv->secondaryIconName);
1597 }
1598
xfdashboard_text_box_set_secondary_icon(XfdashboardTextBox * self,const gchar * inIconName)1599 void xfdashboard_text_box_set_secondary_icon(XfdashboardTextBox *self, const gchar *inIconName)
1600 {
1601 XfdashboardTextBoxPrivate *priv;
1602
1603 g_return_if_fail(XFDASHBOARD_IS_TEXT_BOX(self));
1604 g_return_if_fail(!inIconName || strlen(inIconName)>0);
1605
1606 priv=self->priv;
1607
1608 /* Set themed icon name or icon file name for primary icon */
1609 if(g_strcmp0(priv->secondaryIconName, inIconName)!=0)
1610 {
1611 /* Set new primary icon name */
1612 if(priv->secondaryIconName)
1613 {
1614 g_free(priv->secondaryIconName);
1615 priv->secondaryIconName=NULL;
1616 }
1617
1618 if(inIconName)
1619 {
1620 /* Load and set new icon */
1621 priv->secondaryIconName=g_strdup(inIconName);
1622 xfdashboard_label_set_icon_name(XFDASHBOARD_LABEL(priv->actorSecondaryIcon), priv->secondaryIconName);
1623
1624 /* Show icon */
1625 priv->showSecondaryIcon=TRUE;
1626 clutter_actor_show(priv->actorSecondaryIcon);
1627 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1628 }
1629 else
1630 {
1631 /* Hide icon */
1632 priv->showSecondaryIcon=FALSE;
1633 clutter_actor_hide(priv->actorSecondaryIcon);
1634 clutter_actor_queue_relayout(CLUTTER_ACTOR(self));
1635 }
1636
1637 /* Notify about property change */
1638 g_object_notify_by_pspec(G_OBJECT(self), XfdashboardTextBoxProperties[PROP_SECONDARY_ICON_NAME]);
1639 }
1640 }
1641