2 * @file libsexy/sexy-icon-entry.c Entry widget
4 * @Copyright (C) 2004-2006 Christian Hammond.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
21 #include <libsexy/sexy-icon-entry.h>
28 #define IS_VALID_ICON_ENTRY_POSITION(pos) \
29 ((pos) == SEXY_ICON_ENTRY_PRIMARY || \
30 (pos) == SEXY_ICON_ENTRY_SECONDARY)
41 struct _SexyIconEntryPriv
43 SexyIconInfo icons
[MAX_ICONS
];
45 gulong icon_released_id
;
55 static void sexy_icon_entry_class_init(SexyIconEntryClass
*klass
);
56 static void sexy_icon_entry_editable_init(GtkEditableClass
*iface
);
57 static void sexy_icon_entry_init(SexyIconEntry
*entry
);
58 static void sexy_icon_entry_finalize(GObject
*obj
);
59 static void sexy_icon_entry_destroy(GtkObject
*obj
);
60 static void sexy_icon_entry_map(GtkWidget
*widget
);
61 static void sexy_icon_entry_unmap(GtkWidget
*widget
);
62 static void sexy_icon_entry_realize(GtkWidget
*widget
);
63 static void sexy_icon_entry_unrealize(GtkWidget
*widget
);
64 static void sexy_icon_entry_size_request(GtkWidget
*widget
,
65 GtkRequisition
*requisition
);
66 static void sexy_icon_entry_size_allocate(GtkWidget
*widget
,
67 GtkAllocation
*allocation
);
68 static gint
sexy_icon_entry_expose(GtkWidget
*widget
, GdkEventExpose
*event
);
69 static gint
sexy_icon_entry_enter_notify(GtkWidget
*widget
,
70 GdkEventCrossing
*event
);
71 static gint
sexy_icon_entry_leave_notify(GtkWidget
*widget
,
72 GdkEventCrossing
*event
);
73 static gint
sexy_icon_entry_button_press(GtkWidget
*widget
,
74 GdkEventButton
*event
);
75 static gint
sexy_icon_entry_button_release(GtkWidget
*widget
,
76 GdkEventButton
*event
);
78 static GtkEntryClass
*parent_class
= NULL
;
79 static guint signals
[LAST_SIGNAL
] = {0};
81 G_DEFINE_TYPE_EXTENDED(SexyIconEntry
, sexy_icon_entry
, GTK_TYPE_ENTRY
,
83 G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE
,
84 sexy_icon_entry_editable_init
));
87 sexy_icon_entry_class_init(SexyIconEntryClass
*klass
)
89 GObjectClass
*gobject_class
;
90 GtkObjectClass
*object_class
;
91 GtkWidgetClass
*widget_class
;
92 GtkEntryClass
*entry_class
;
94 parent_class
= g_type_class_peek_parent(klass
);
96 gobject_class
= G_OBJECT_CLASS(klass
);
97 object_class
= GTK_OBJECT_CLASS(klass
);
98 widget_class
= GTK_WIDGET_CLASS(klass
);
99 entry_class
= GTK_ENTRY_CLASS(klass
);
101 gobject_class
->finalize
= sexy_icon_entry_finalize
;
103 object_class
->destroy
= sexy_icon_entry_destroy
;
105 widget_class
->map
= sexy_icon_entry_map
;
106 widget_class
->unmap
= sexy_icon_entry_unmap
;
107 widget_class
->realize
= sexy_icon_entry_realize
;
108 widget_class
->unrealize
= sexy_icon_entry_unrealize
;
109 widget_class
->size_request
= sexy_icon_entry_size_request
;
110 widget_class
->size_allocate
= sexy_icon_entry_size_allocate
;
111 widget_class
->expose_event
= sexy_icon_entry_expose
;
112 widget_class
->enter_notify_event
= sexy_icon_entry_enter_notify
;
113 widget_class
->leave_notify_event
= sexy_icon_entry_leave_notify
;
114 widget_class
->button_press_event
= sexy_icon_entry_button_press
;
115 widget_class
->button_release_event
= sexy_icon_entry_button_release
;
118 * SexyIconEntry::icon-pressed:
119 * @entry: The entry on which the signal is emitted.
120 * @icon_pos: The position of the clicked icon.
121 * @button: The mouse button clicked.
123 * The ::icon-pressed signal is emitted when an icon is clicked.
125 signals
[ICON_PRESSED
] =
126 g_signal_new("icon_pressed",
127 G_TYPE_FROM_CLASS(gobject_class
),
128 G_SIGNAL_RUN_LAST
| G_SIGNAL_ACTION
,
129 G_STRUCT_OFFSET(SexyIconEntryClass
, icon_pressed
),
131 gtk_marshal_VOID__INT_INT
,
137 * SexyIconEntry::icon-released:
138 * @entry: The entry on which the signal is emitted.
139 * @icon_pos: The position of the clicked icon.
140 * @button: The mouse button clicked.
142 * The ::icon-released signal is emitted on the button release from a
145 signals
[ICON_RELEASED
] =
146 g_signal_new("icon_released",
147 G_TYPE_FROM_CLASS(gobject_class
),
148 G_SIGNAL_RUN_LAST
| G_SIGNAL_ACTION
,
149 G_STRUCT_OFFSET(SexyIconEntryClass
, icon_released
),
151 gtk_marshal_VOID__INT_INT
,
158 sexy_icon_entry_editable_init(GtkEditableClass
*iface
)
163 sexy_icon_entry_init(SexyIconEntry
*entry
)
165 entry
->priv
= g_new0(SexyIconEntryPriv
, 1);
169 sexy_icon_entry_finalize(GObject
*obj
)
171 SexyIconEntry
*entry
;
173 g_return_if_fail(obj
!= NULL
);
174 g_return_if_fail(SEXY_IS_ICON_ENTRY(obj
));
176 entry
= SEXY_ICON_ENTRY(obj
);
180 if (G_OBJECT_CLASS(parent_class
)->finalize
)
181 G_OBJECT_CLASS(parent_class
)->finalize(obj
);
185 sexy_icon_entry_destroy(GtkObject
*obj
)
187 SexyIconEntry
*entry
;
189 entry
= SEXY_ICON_ENTRY(obj
);
191 sexy_icon_entry_set_icon(entry
, SEXY_ICON_ENTRY_PRIMARY
, NULL
);
192 sexy_icon_entry_set_icon(entry
, SEXY_ICON_ENTRY_SECONDARY
, NULL
);
194 if (GTK_OBJECT_CLASS(parent_class
)->destroy
)
195 GTK_OBJECT_CLASS(parent_class
)->destroy(obj
);
199 sexy_icon_entry_map(GtkWidget
*widget
)
201 if (GTK_WIDGET_REALIZED(widget
) && !GTK_WIDGET_MAPPED(widget
))
203 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
206 GTK_WIDGET_CLASS(parent_class
)->map(widget
);
208 for (i
= 0; i
< MAX_ICONS
; i
++)
210 if (entry
->priv
->icons
[i
].icon
!= NULL
)
211 gdk_window_show(entry
->priv
->icons
[i
].window
);
217 sexy_icon_entry_unmap(GtkWidget
*widget
)
219 if (GTK_WIDGET_MAPPED(widget
))
221 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
224 for (i
= 0; i
< MAX_ICONS
; i
++)
226 if (entry
->priv
->icons
[i
].icon
!= NULL
)
227 gdk_window_hide(entry
->priv
->icons
[i
].window
);
230 GTK_WIDGET_CLASS(parent_class
)->unmap(widget
);
235 get_icon_width(SexyIconEntry
*entry
, SexyIconEntryPosition icon_pos
)
237 GtkRequisition requisition
;
238 gint menu_icon_width
;
240 SexyIconInfo
*icon_info
= &entry
->priv
->icons
[icon_pos
];
242 if (icon_info
->icon
== NULL
)
245 gtk_widget_size_request(GTK_WIDGET(icon_info
->icon
), &requisition
);
246 gtk_icon_size_lookup(GTK_ICON_SIZE_MENU
, &menu_icon_width
, NULL
);
248 width
= MAX(requisition
.width
, menu_icon_width
);
254 get_borders(SexyIconEntry
*entry
, gint
*xborder
, gint
*yborder
)
256 GtkWidget
*widget
= GTK_WIDGET(entry
);
258 gboolean interior_focus
;
260 gtk_widget_style_get(widget
,
261 "interior-focus", &interior_focus
,
262 "focus-line-width", &focus_width
,
265 if (gtk_entry_get_has_frame(GTK_ENTRY(entry
)))
267 *xborder
= widget
->style
->xthickness
;
268 *yborder
= widget
->style
->ythickness
;
278 *xborder
+= focus_width
;
279 *yborder
+= focus_width
;
284 get_text_area_size(SexyIconEntry
*entry
, GtkAllocation
*alloc
)
286 GtkWidget
*widget
= GTK_WIDGET(entry
);
287 GtkRequisition requisition
;
288 gint xborder
, yborder
;
290 gtk_widget_get_child_requisition(widget
, &requisition
);
291 get_borders(entry
, &xborder
, &yborder
);
295 alloc
->width
= widget
->allocation
.width
- xborder
* 2;
296 alloc
->height
= requisition
.height
- yborder
* 2;
300 get_icon_allocation(SexyIconEntry
*icon_entry
,
302 GtkAllocation
*widget_alloc
,
303 GtkAllocation
*text_area_alloc
,
304 GtkAllocation
*allocation
,
305 SexyIconEntryPosition
*icon_pos
)
309 rtl
= (gtk_widget_get_direction(GTK_WIDGET(icon_entry
)) ==
313 *icon_pos
= (rtl
? SEXY_ICON_ENTRY_SECONDARY
: SEXY_ICON_ENTRY_PRIMARY
);
315 *icon_pos
= (rtl
? SEXY_ICON_ENTRY_PRIMARY
: SEXY_ICON_ENTRY_SECONDARY
);
317 allocation
->y
= text_area_alloc
->y
;
318 allocation
->width
= get_icon_width(icon_entry
, *icon_pos
);
319 allocation
->height
= text_area_alloc
->height
;
322 allocation
->x
= text_area_alloc
->x
+ ICON_MARGIN
;
325 allocation
->x
= text_area_alloc
->x
+ text_area_alloc
->width
-
326 allocation
->width
- ICON_MARGIN
;
331 sexy_icon_entry_realize(GtkWidget
*widget
)
333 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
334 GdkWindowAttr attributes
;
335 gint attributes_mask
;
338 GTK_WIDGET_CLASS(parent_class
)->realize(widget
);
340 attributes
.width
= 1;
341 attributes
.height
= 1;
342 attributes
.window_type
= GDK_WINDOW_CHILD
;
343 attributes
.wclass
= GDK_INPUT_OUTPUT
;
344 attributes
.visual
= gtk_widget_get_visual(widget
);
345 attributes
.colormap
= gtk_widget_get_colormap(widget
);
346 attributes
.event_mask
= gtk_widget_get_events(widget
);
347 attributes
.event_mask
|=
349 | GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
350 | GDK_ENTER_NOTIFY_MASK
| GDK_LEAVE_NOTIFY_MASK
);
352 attributes_mask
= GDK_WA_VISUAL
| GDK_WA_COLORMAP
;
354 for (i
= 0; i
< MAX_ICONS
; i
++)
356 SexyIconInfo
*icon_info
;
358 icon_info
= &entry
->priv
->icons
[i
];
359 icon_info
->window
= gdk_window_new(widget
->window
, &attributes
,
361 gdk_window_set_user_data(icon_info
->window
, widget
);
363 gdk_window_set_background(icon_info
->window
,
364 &widget
->style
->base
[GTK_WIDGET_STATE(widget
)]);
367 gtk_widget_queue_resize(widget
);
371 sexy_icon_entry_unrealize(GtkWidget
*widget
)
373 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
376 GTK_WIDGET_CLASS(parent_class
)->unrealize(widget
);
378 for (i
= 0; i
< MAX_ICONS
; i
++)
380 SexyIconInfo
*icon_info
= &entry
->priv
->icons
[i
];
382 gdk_window_destroy(icon_info
->window
);
383 icon_info
->window
= NULL
;
388 sexy_icon_entry_size_request(GtkWidget
*widget
, GtkRequisition
*requisition
)
391 SexyIconEntry
*entry
;
392 gint icon_widths
= 0;
395 gtkentry
= GTK_ENTRY(widget
);
396 entry
= SEXY_ICON_ENTRY(widget
);
398 for (i
= 0; i
< MAX_ICONS
; i
++)
400 int icon_width
= get_icon_width(entry
, i
);
403 icon_widths
+= icon_width
+ ICON_MARGIN
;
406 GTK_WIDGET_CLASS(parent_class
)->size_request(widget
, requisition
);
408 if (icon_widths
> requisition
->width
)
409 requisition
->width
+= icon_widths
;
413 place_windows(SexyIconEntry
*icon_entry
, GtkAllocation
*widget_alloc
)
415 SexyIconEntryPosition left_icon_pos
;
416 SexyIconEntryPosition right_icon_pos
;
417 GtkAllocation left_icon_alloc
;
418 GtkAllocation right_icon_alloc
;
419 GtkAllocation text_area_alloc
;
421 get_text_area_size(icon_entry
, &text_area_alloc
);
422 get_icon_allocation(icon_entry
, TRUE
, widget_alloc
, &text_area_alloc
,
423 &left_icon_alloc
, &left_icon_pos
);
424 get_icon_allocation(icon_entry
, FALSE
, widget_alloc
, &text_area_alloc
,
425 &right_icon_alloc
, &right_icon_pos
);
427 if (left_icon_alloc
.width
> 0)
429 text_area_alloc
.x
= left_icon_alloc
.x
+ left_icon_alloc
.width
+
433 if (right_icon_alloc
.width
> 0)
434 text_area_alloc
.width
-= right_icon_alloc
.width
+ ICON_MARGIN
;
436 text_area_alloc
.width
-= text_area_alloc
.x
;
438 gdk_window_move_resize(icon_entry
->priv
->icons
[left_icon_pos
].window
,
439 left_icon_alloc
.x
, left_icon_alloc
.y
,
440 left_icon_alloc
.width
, left_icon_alloc
.height
);
442 gdk_window_move_resize(icon_entry
->priv
->icons
[right_icon_pos
].window
,
443 right_icon_alloc
.x
, right_icon_alloc
.y
,
444 right_icon_alloc
.width
, right_icon_alloc
.height
);
446 gdk_window_move_resize(GTK_ENTRY(icon_entry
)->text_area
,
447 text_area_alloc
.x
, text_area_alloc
.y
,
448 text_area_alloc
.width
, text_area_alloc
.height
);
452 sexy_icon_entry_size_allocate(GtkWidget
*widget
, GtkAllocation
*allocation
)
454 g_return_if_fail(SEXY_IS_ICON_ENTRY(widget
));
455 g_return_if_fail(allocation
!= NULL
);
457 widget
->allocation
= *allocation
;
459 GTK_WIDGET_CLASS(parent_class
)->size_allocate(widget
, allocation
);
461 if (GTK_WIDGET_REALIZED(widget
))
462 place_windows(SEXY_ICON_ENTRY(widget
), allocation
);
466 get_pixbuf_from_icon(SexyIconEntry
*entry
, SexyIconEntryPosition icon_pos
)
468 GdkPixbuf
*pixbuf
= NULL
;
470 SexyIconInfo
*icon_info
= &entry
->priv
->icons
[icon_pos
];
473 switch (gtk_image_get_storage_type(GTK_IMAGE(icon_info
->icon
)))
475 case GTK_IMAGE_PIXBUF
:
476 pixbuf
= gtk_image_get_pixbuf(GTK_IMAGE(icon_info
->icon
));
477 g_object_ref(pixbuf
);
480 case GTK_IMAGE_STOCK
:
481 gtk_image_get_stock(GTK_IMAGE(icon_info
->icon
), &stock_id
, &size
);
482 pixbuf
= gtk_widget_render_icon(GTK_WIDGET(entry
),
483 stock_id
, size
, NULL
);
493 /* Kudos to the gnome-panel guys. */
495 colorshift_pixbuf(GdkPixbuf
*dest
, GdkPixbuf
*src
, int shift
)
498 gint width
, height
, has_alpha
, src_rowstride
, dest_rowstride
;
499 guchar
*target_pixels
;
500 guchar
*original_pixels
;
506 has_alpha
= gdk_pixbuf_get_has_alpha(src
);
507 width
= gdk_pixbuf_get_width(src
);
508 height
= gdk_pixbuf_get_height(src
);
509 src_rowstride
= gdk_pixbuf_get_rowstride(src
);
510 dest_rowstride
= gdk_pixbuf_get_rowstride(dest
);
511 original_pixels
= gdk_pixbuf_get_pixels(src
);
512 target_pixels
= gdk_pixbuf_get_pixels(dest
);
514 for (i
= 0; i
< height
; i
++)
516 pix_dest
= target_pixels
+ i
* dest_rowstride
;
517 pix_src
= original_pixels
+ i
* src_rowstride
;
519 for (j
= 0; j
< width
; j
++)
526 *(pix_dest
++) = CLAMP(val
, 0, 255);
529 *(pix_dest
++) = CLAMP(val
, 0, 255);
532 *(pix_dest
++) = CLAMP(val
, 0, 255);
535 *(pix_dest
++) = *(pix_src
++);
541 draw_icon(GtkWidget
*widget
, SexyIconEntryPosition icon_pos
)
543 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
544 SexyIconInfo
*icon_info
= &entry
->priv
->icons
[icon_pos
];
546 gint x
, y
, width
, height
;
548 if (icon_info
->icon
== NULL
|| !GTK_WIDGET_REALIZED(widget
))
551 if ((pixbuf
= get_pixbuf_from_icon(entry
, icon_pos
)) == NULL
)
554 gdk_drawable_get_size(icon_info
->window
, &width
, &height
);
555 if ((width
< 2 * ICON_MARGIN
) || (height
< 2 * ICON_MARGIN
))
558 if (gdk_pixbuf_get_height(pixbuf
) > height
)
560 GdkPixbuf
*temp_pixbuf
;
563 scale
= height
- (2 * ICON_MARGIN
);
565 temp_pixbuf
= gdk_pixbuf_scale_simple(pixbuf
, scale
, scale
,
566 GDK_INTERP_BILINEAR
);
568 g_object_unref(pixbuf
);
570 pixbuf
= temp_pixbuf
;
573 x
= (width
- gdk_pixbuf_get_width(pixbuf
)) / 2;
574 y
= (height
- gdk_pixbuf_get_height(pixbuf
)) / 2;
576 if (icon_info
->hovered
)
578 GdkPixbuf
*temp_pixbuf
;
580 temp_pixbuf
= gdk_pixbuf_copy(pixbuf
);
582 colorshift_pixbuf(temp_pixbuf
, pixbuf
, 30);
584 g_object_unref(pixbuf
);
586 pixbuf
= temp_pixbuf
;
589 gdk_draw_pixbuf(icon_info
->window
, widget
->style
->black_gc
, pixbuf
,
591 GDK_RGB_DITHER_NORMAL
, 0, 0);
593 g_object_unref(pixbuf
);
597 sexy_icon_entry_expose(GtkWidget
*widget
, GdkEventExpose
*event
)
599 SexyIconEntry
*entry
;
601 g_return_val_if_fail(SEXY_IS_ICON_ENTRY(widget
), FALSE
);
602 g_return_val_if_fail(event
!= NULL
, FALSE
);
604 entry
= SEXY_ICON_ENTRY(widget
);
606 if (GTK_WIDGET_DRAWABLE(widget
))
608 gboolean found
= FALSE
;
611 for (i
= 0; i
< MAX_ICONS
&& !found
; i
++)
613 SexyIconInfo
*icon_info
= &entry
->priv
->icons
[i
];
615 if (event
->window
== icon_info
->window
)
618 GtkAllocation text_area_alloc
;
620 get_text_area_size(entry
, &text_area_alloc
);
621 gdk_drawable_get_size(icon_info
->window
, &width
, NULL
);
623 gtk_paint_flat_box(widget
->style
, icon_info
->window
,
624 GTK_WIDGET_STATE(widget
), GTK_SHADOW_NONE
,
625 NULL
, widget
, "entry_bg",
626 0, 0, width
, text_area_alloc
.height
);
628 draw_icon(widget
, i
);
635 GTK_WIDGET_CLASS(parent_class
)->expose_event(widget
, event
);
642 update_icon(GObject
*obj
, GParamSpec
*param
, SexyIconEntry
*entry
)
646 const char *name
= g_param_spec_get_name(param
);
648 if (strcmp(name
, "pixbuf") && strcmp(name
, "stock") &&
649 strcmp(name
, "image") && strcmp(name
, "pixmap") &&
650 strcmp(name
, "icon_set") && strcmp(name
, "pixbuf_animation"))
656 gtk_widget_queue_resize(GTK_WIDGET(entry
));
660 sexy_icon_entry_enter_notify(GtkWidget
*widget
, GdkEventCrossing
*event
)
662 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
665 for (i
= 0; i
< MAX_ICONS
; i
++)
667 if (event
->window
== entry
->priv
->icons
[i
].window
)
669 if (sexy_icon_entry_get_icon_highlight(entry
, i
))
671 entry
->priv
->icons
[i
].hovered
= TRUE
;
673 update_icon(NULL
, NULL
, entry
);
684 sexy_icon_entry_leave_notify(GtkWidget
*widget
, GdkEventCrossing
*event
)
686 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
689 for (i
= 0; i
< MAX_ICONS
; i
++)
691 if (event
->window
== entry
->priv
->icons
[i
].window
)
693 if (sexy_icon_entry_get_icon_highlight(entry
, i
))
695 entry
->priv
->icons
[i
].hovered
= FALSE
;
697 update_icon(NULL
, NULL
, entry
);
708 sexy_icon_entry_button_press(GtkWidget
*widget
, GdkEventButton
*event
)
710 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
713 for (i
= 0; i
< MAX_ICONS
; i
++)
715 if (event
->window
== entry
->priv
->icons
[i
].window
)
717 if (event
->button
== 1 &&
718 sexy_icon_entry_get_icon_highlight(entry
, i
))
720 entry
->priv
->icons
[i
].hovered
= FALSE
;
722 update_icon(NULL
, NULL
, entry
);
725 g_signal_emit(entry
, signals
[ICON_PRESSED
], 0, i
, event
->button
);
731 if (GTK_WIDGET_CLASS(parent_class
)->button_press_event
)
732 return GTK_WIDGET_CLASS(parent_class
)->button_press_event(widget
,
739 sexy_icon_entry_button_release(GtkWidget
*widget
, GdkEventButton
*event
)
741 SexyIconEntry
*entry
= SEXY_ICON_ENTRY(widget
);
744 for (i
= 0; i
< MAX_ICONS
; i
++)
746 GdkWindow
*icon_window
= entry
->priv
->icons
[i
].window
;
748 if (event
->window
== icon_window
)
751 gdk_drawable_get_size(icon_window
, &width
, &height
);
753 if (event
->button
== 1 &&
754 sexy_icon_entry_get_icon_highlight(entry
, i
) &&
755 event
->x
>= 0 && event
->y
>= 0 &&
756 event
->x
<= width
&& event
->y
<= height
)
758 entry
->priv
->icons
[i
].hovered
= TRUE
;
760 update_icon(NULL
, NULL
, entry
);
763 g_signal_emit(entry
, signals
[ICON_RELEASED
], 0, i
, event
->button
);
769 if (GTK_WIDGET_CLASS(parent_class
)->button_release_event
)
770 return GTK_WIDGET_CLASS(parent_class
)->button_release_event(widget
,
777 * sexy_icon_entry_new
779 * Creates a new SexyIconEntry widget.
781 * Returns a new #SexyIconEntry.
784 sexy_icon_entry_new(void)
786 return GTK_WIDGET(g_object_new(SEXY_TYPE_ICON_ENTRY
, NULL
));
790 * sexy_icon_entry_set_icon
791 * @entry: A #SexyIconEntry.
792 * @position: Icon position.
793 * @icon: A #GtkImage to set as the icon.
795 * Sets the icon shown in the entry
798 sexy_icon_entry_set_icon(SexyIconEntry
*entry
, SexyIconEntryPosition icon_pos
,
801 SexyIconInfo
*icon_info
;
803 g_return_if_fail(entry
!= NULL
);
804 g_return_if_fail(SEXY_IS_ICON_ENTRY(entry
));
805 g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos
));
806 g_return_if_fail(icon
== NULL
|| GTK_IS_IMAGE(icon
));
808 icon_info
= &entry
->priv
->icons
[icon_pos
];
810 if (icon
== icon_info
->icon
)
813 if (icon_pos
== SEXY_ICON_ENTRY_SECONDARY
&&
814 entry
->priv
->icon_released_id
!= 0)
816 g_signal_handler_disconnect(entry
, entry
->priv
->icon_released_id
);
817 entry
->priv
->icon_released_id
= 0;
822 if (icon_info
->icon
!= NULL
)
824 gtk_widget_destroy(GTK_WIDGET(icon_info
->icon
));
825 icon_info
->icon
= NULL
;
828 * Explicitly check, as the pointer may become invalidated
829 * during destruction.
831 if (icon_info
->window
!= NULL
&& GDK_IS_WINDOW(icon_info
->window
))
832 gdk_window_hide(icon_info
->window
);
837 if (icon_info
->window
!= NULL
&& icon_info
->icon
== NULL
)
838 gdk_window_show(icon_info
->window
);
840 g_signal_connect(G_OBJECT(icon
), "notify",
841 G_CALLBACK(update_icon
), entry
);
843 icon_info
->icon
= icon
;
847 update_icon(NULL
, NULL
, entry
);
851 * sexy_icon_entry_set_icon_highlight
852 * @entry: A #SexyIconEntry;
853 * @position: Icon position.
854 * @highlight: TRUE if the icon should highlight on mouse-over
856 * Determines whether the icon will highlight on mouse-over.
859 sexy_icon_entry_set_icon_highlight(SexyIconEntry
*entry
,
860 SexyIconEntryPosition icon_pos
,
863 SexyIconInfo
*icon_info
;
865 g_return_if_fail(entry
!= NULL
);
866 g_return_if_fail(SEXY_IS_ICON_ENTRY(entry
));
867 g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos
));
869 icon_info
= &entry
->priv
->icons
[icon_pos
];
871 if (icon_info
->highlight
== highlight
)
874 icon_info
->highlight
= highlight
;
878 * sexy_icon_entry_get_icon
879 * @entry: A #SexyIconEntry.
880 * @position: Icon position.
882 * Retrieves the image used for the icon
884 * Returns: A #GtkImage.
887 sexy_icon_entry_get_icon(const SexyIconEntry
*entry
,
888 SexyIconEntryPosition icon_pos
)
890 g_return_val_if_fail(entry
!= NULL
, NULL
);
891 g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry
), NULL
);
892 g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos
), NULL
);
894 return entry
->priv
->icons
[icon_pos
].icon
;
898 * sexy_icon_entry_get_icon_highlight
899 * @entry: A #SexyIconEntry.
900 * @position: Icon position.
902 * Retrieves whether entry will highlight the icon on mouseover.
904 * Returns: TRUE if icon highlights.
907 sexy_icon_entry_get_icon_highlight(const SexyIconEntry
*entry
,
908 SexyIconEntryPosition icon_pos
)
910 g_return_val_if_fail(entry
!= NULL
, FALSE
);
911 g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry
), FALSE
);
912 g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos
), FALSE
);
914 return entry
->priv
->icons
[icon_pos
].highlight
;
918 clear_button_clicked_cb(SexyIconEntry
*icon_entry
,
919 SexyIconEntryPosition icon_pos
,
922 if (icon_pos
!= SEXY_ICON_ENTRY_SECONDARY
|| button
!= 1)
925 gtk_entry_set_text(GTK_ENTRY(icon_entry
), "");
929 * sexy_icon_entry_add_clear_button
930 * @icon_entry: A #SexyIconEntry.
932 * A convenience function to add a clear button to the end of the entry.
933 * This is useful for search boxes.
936 sexy_icon_entry_add_clear_button(SexyIconEntry
*icon_entry
)
940 g_return_if_fail(icon_entry
!= NULL
);
941 g_return_if_fail(SEXY_IS_ICON_ENTRY(icon_entry
));
943 icon
= gtk_image_new_from_stock(GTK_STOCK_CLEAR
, GTK_ICON_SIZE_MENU
);
944 gtk_widget_show(icon
);
945 sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(icon_entry
),
946 SEXY_ICON_ENTRY_SECONDARY
,
948 sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(icon_entry
),
949 SEXY_ICON_ENTRY_SECONDARY
, TRUE
);
951 if (icon_entry
->priv
->icon_released_id
!= 0)
953 g_signal_handler_disconnect(icon_entry
,
954 icon_entry
->priv
->icon_released_id
);
957 icon_entry
->priv
->icon_released_id
=
958 g_signal_connect(G_OBJECT(icon_entry
), "icon_released",
959 G_CALLBACK(clear_button_clicked_cb
), NULL
);