2 * Copyright © 2003, 2004, 2005 Christian Persch
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
19 * Adapted and modified from gtk+ code:
21 * Copyright © 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
22 * Modified by the GTK+ Team and others 1997-2005. See the AUTHORS
23 * file in the gtk+ distribution for a list of people on the GTK+ Team.
24 * See the ChangeLog in the gtk+ distribution files for a list of changes.
25 * These files are distributed with GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 * $Id: ephy-icon-entry.c 6952 2007-03-11 19:42:02Z chpe $
32 #include "ephy-icon-entry.h"
34 #include <gtk/gtkentry.h>
35 #include <gtk/gtkbox.h>
36 #include <gtk/gtkhbox.h>
38 #define EPHY_ICON_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ICON_ENTRY, EphyIconEntryPrivate))
40 struct _EphyIconEntryPrivate
45 static GtkWidgetClass
*parent_class
= NULL
;
47 /* private helper functions */
50 entry_focus_change_cb (GtkWidget
*widget
,
54 gtk_widget_queue_draw (entry
);
60 ephy_icon_entry_get_borders (GtkWidget
*widget
,
66 gboolean interior_focus
;
68 g_return_if_fail (entry
->style
!= NULL
);
70 gtk_widget_style_get (entry
,
71 "focus-line-width", &focus_width
,
72 "interior-focus", &interior_focus
,
75 *xborder
= entry
->style
->xthickness
;
76 *yborder
= entry
->style
->ythickness
;
80 *xborder
+= focus_width
;
81 *yborder
+= focus_width
;
86 ephy_icon_entry_paint (GtkWidget
*widget
,
87 GdkEventExpose
*event
)
89 EphyIconEntry
*entry
= EPHY_ICON_ENTRY (widget
);
90 GtkWidget
*entry_widget
= entry
->entry
;
91 int x
= 0, y
= 0, width
, height
, focus_width
;
92 gboolean interior_focus
;
94 gtk_widget_style_get (entry_widget
,
95 "interior-focus", &interior_focus
,
96 "focus-line-width", &focus_width
,
99 gdk_drawable_get_size (widget
->window
, &width
, &height
);
101 if (GTK_WIDGET_HAS_FOCUS (entry_widget
) && !interior_focus
)
105 width
-= 2 * focus_width
;
106 height
-= 2 * focus_width
;
109 gtk_paint_flat_box (entry_widget
->style
, widget
->window
,
110 GTK_WIDGET_STATE (entry_widget
), GTK_SHADOW_NONE
,
111 NULL
, entry_widget
, "entry_bg",
112 /* FIXME: was 0, 0 in gtk_entry_expose, but I think this is correct: */
113 x
, y
, width
, height
);
115 gtk_paint_shadow (entry_widget
->style
, widget
->window
,
116 GTK_STATE_NORMAL
, GTK_SHADOW_IN
,
117 NULL
, entry_widget
, "entry",
118 x
, y
, width
, height
);
120 if (GTK_WIDGET_HAS_FOCUS (entry_widget
) && !interior_focus
)
124 width
+= 2 * focus_width
;
125 height
+= 2 * focus_width
;
127 gtk_paint_focus (entry_widget
->style
, widget
->window
,
128 GTK_WIDGET_STATE (entry_widget
),
129 NULL
, entry_widget
, "entry",
130 /* FIXME: was 0, 0 in gtk_entry_draw_frame, but I think this is correct: */
131 x
, y
, width
, height
);
135 /* Class implementation */
138 ephy_icon_entry_init (EphyIconEntry
*entry
)
140 EphyIconEntryPrivate
*priv
;
141 GtkWidget
*widget
= (GtkWidget
*) entry
;
143 priv
= entry
->priv
= EPHY_ICON_ENTRY_GET_PRIVATE (entry
);
145 GTK_WIDGET_UNSET_FLAGS (widget
, GTK_NO_WINDOW
);
147 priv
->hbox
= gtk_hbox_new (FALSE
, /* FIXME */ 0);
148 gtk_container_add (GTK_CONTAINER (entry
), priv
->hbox
);
150 entry
->entry
= gtk_entry_new ();
151 gtk_entry_set_has_frame (GTK_ENTRY (entry
->entry
), FALSE
);
152 gtk_box_pack_start (GTK_BOX (priv
->hbox
), entry
->entry
, TRUE
, TRUE
, /* FIXME */ 0);
154 /* We need to queue a redraw when focus changes, to comply with themes
155 * (like Clearlooks) which draw focused and unfocused entries differently.
157 g_signal_connect_after (entry
->entry
, "focus-in-event",
158 G_CALLBACK (entry_focus_change_cb
), entry
);
159 g_signal_connect_after (entry
->entry
, "focus-out-event",
160 G_CALLBACK (entry_focus_change_cb
), entry
);
164 ephy_icon_entry_realize (GtkWidget
*widget
)
166 GdkWindowAttr attributes
;
167 gint attributes_mask
;
170 GTK_WIDGET_SET_FLAGS (widget
, GTK_REALIZED
);
172 border_width
= GTK_CONTAINER (widget
)->border_width
;
174 attributes
.x
= widget
->allocation
.x
+ border_width
;
175 attributes
.y
= widget
->allocation
.y
+ border_width
;
176 attributes
.width
= widget
->allocation
.width
- 2 * border_width
;
177 attributes
.height
= widget
->allocation
.height
- 2 * border_width
;
178 attributes
.window_type
= GDK_WINDOW_CHILD
;
179 attributes
.event_mask
= gtk_widget_get_events (widget
)
182 attributes
.visual
= gtk_widget_get_visual (widget
);
183 attributes
.colormap
= gtk_widget_get_colormap (widget
);
184 attributes
.wclass
= GDK_INPUT_OUTPUT
;
185 attributes_mask
= GDK_WA_X
| GDK_WA_Y
| GDK_WA_VISUAL
| GDK_WA_COLORMAP
;
187 widget
->window
= gdk_window_new (gtk_widget_get_parent_window (widget
),
188 &attributes
, attributes_mask
);
189 gdk_window_set_user_data (widget
->window
, widget
);
191 widget
->style
= gtk_style_attach (widget
->style
, widget
->window
);
193 gtk_style_set_background (widget
->style
, widget
->window
, GTK_STATE_NORMAL
);
197 ephy_icon_entry_size_request (GtkWidget
*widget
,
198 GtkRequisition
*requisition
)
200 EphyIconEntry
*entry
= EPHY_ICON_ENTRY (widget
);
201 GtkContainer
*container
= GTK_CONTAINER (widget
);
202 GtkBin
*bin
= GTK_BIN (widget
);
203 int xborder
, yborder
;
205 requisition
->width
= requisition
->height
= container
->border_width
* 2;
207 gtk_widget_ensure_style (entry
->entry
);
208 ephy_icon_entry_get_borders (widget
, entry
->entry
, &xborder
, &yborder
);
210 if (GTK_WIDGET_VISIBLE (bin
->child
))
212 GtkRequisition child_requisition
;
214 gtk_widget_size_request (bin
->child
, &child_requisition
);
215 requisition
->width
+= child_requisition
.width
;
216 requisition
->height
+= child_requisition
.height
;
219 requisition
->width
+= 2 * xborder
;
220 requisition
->height
+= 2 * yborder
;
224 ephy_icon_entry_size_allocate (GtkWidget
*widget
,
225 GtkAllocation
*allocation
)
227 EphyIconEntry
*entry
= EPHY_ICON_ENTRY (widget
);
228 GtkContainer
*container
= GTK_CONTAINER (widget
);
229 GtkBin
*bin
= GTK_BIN (widget
);
230 GtkAllocation child_allocation
;
231 int xborder
, yborder
;
233 widget
->allocation
= *allocation
;
235 ephy_icon_entry_get_borders (widget
, entry
->entry
, &xborder
, &yborder
);
237 if (GTK_WIDGET_REALIZED (widget
))
239 child_allocation
.x
= container
->border_width
;
240 child_allocation
.y
= container
->border_width
;
241 child_allocation
.width
= MAX (allocation
->width
- container
->border_width
* 2, 0);
242 child_allocation
.height
= MAX (allocation
->height
- container
->border_width
* 2, 0);
244 gdk_window_move_resize (widget
->window
,
245 allocation
->x
+ child_allocation
.x
,
246 allocation
->y
+ child_allocation
.y
,
247 child_allocation
.width
,
248 child_allocation
.height
);
251 child_allocation
.x
= container
->border_width
+ xborder
;
252 child_allocation
.y
= container
->border_width
+ yborder
;
253 child_allocation
.width
= MAX (allocation
->width
- (container
->border_width
+ xborder
) * 2, 0);
254 child_allocation
.height
= MAX (allocation
->height
- (container
->border_width
+ yborder
) * 2, 0);
256 gtk_widget_size_allocate (bin
->child
, &child_allocation
);
260 ephy_icon_entry_expose (GtkWidget
*widget
,
261 GdkEventExpose
*event
)
263 if (GTK_WIDGET_DRAWABLE (widget
) &&
264 event
->window
== widget
->window
)
266 ephy_icon_entry_paint (widget
, event
);
269 return parent_class
->expose_event (widget
, event
);
273 ephy_icon_entry_class_init (EphyIconEntryClass
*klass
)
275 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
276 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS (klass
);
278 parent_class
= GTK_WIDGET_CLASS (g_type_class_peek_parent (klass
));
280 widget_class
->realize
= ephy_icon_entry_realize
;
281 widget_class
->size_request
= ephy_icon_entry_size_request
;
282 widget_class
->size_allocate
= ephy_icon_entry_size_allocate
;
283 widget_class
->expose_event
= ephy_icon_entry_expose
;
285 g_type_class_add_private (object_class
, sizeof (EphyIconEntryPrivate
));
289 ephy_icon_entry_get_type (void)
291 static GType type
= 0;
293 if (G_UNLIKELY (type
== 0))
295 const GTypeInfo our_info
=
297 sizeof (EphyIconEntryClass
),
300 (GClassInitFunc
) ephy_icon_entry_class_init
,
303 sizeof (EphyIconEntry
),
305 (GInstanceInitFunc
) ephy_icon_entry_init
308 type
= g_type_register_static (GTK_TYPE_BIN
,
316 /* public functions */
319 ephy_icon_entry_new (void)
321 return GTK_WIDGET (g_object_new (EPHY_TYPE_ICON_ENTRY
, NULL
));
325 ephy_icon_entry_pack_widget (EphyIconEntry
*entry
,
329 EphyIconEntryPrivate
*priv
;
331 g_return_if_fail (EPHY_IS_ICON_ENTRY (entry
));
337 gtk_box_pack_start (GTK_BOX (priv
->hbox
), widget
, FALSE
, FALSE
, /* FIXME */ 2);
338 gtk_box_reorder_child (GTK_BOX (priv
->hbox
), widget
, 0);
342 gtk_box_pack_end (GTK_BOX (priv
->hbox
), widget
, FALSE
, FALSE
, /* FIXME */ 2);
347 ephy_icon_entry_get_entry (EphyIconEntry
*entry
)
349 g_return_val_if_fail (EPHY_IS_ICON_ENTRY (entry
), NULL
);