~vcs-imports/mayanna/trunk

« back to all changes in this revision

Viewing changes to mayanna/iconentry/ephy-icon-entry.c

  • Committer: seiflotfy
  • Date: 2008-04-09 23:20:00 UTC
  • Revision ID: vcs-imports@canonical.com-20080409232000-qpgm81uu4kucnvs6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2003, 2004, 2005  Christian Persch
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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., 59 Temple Place - Suite 330,
 
17
 *  Boston, MA 02111-1307, USA.
 
18
 *
 
19
 *  Adapted and modified from gtk+ code:
 
20
 *
 
21
 *  Copyright (C) 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/. 
 
26
 *
 
27
 *  $Id: ephy-icon-entry.c 27 2006-02-10 19:19:43Z orph $
 
28
 */
 
29
 
 
30
#ifndef COMPILING_TESTICONENTRY
 
31
#include "config.h"
 
32
#endif
 
33
 
 
34
#include "ephy-icon-entry.h"
 
35
 
 
36
#include <gtk/gtkentry.h>
 
37
#include <gtk/gtkbox.h>
 
38
#include <gtk/gtkhbox.h>
 
39
 
 
40
#define EPHY_ICON_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ICON_ENTRY, EphyIconEntryPrivate))
 
41
 
 
42
struct _EphyIconEntryPrivate
 
43
{
 
44
        GtkWidget *hbox;
 
45
};
 
46
 
 
47
static GtkWidgetClass *parent_class = NULL;
 
48
 
 
49
/* private helper functions */
 
50
 
 
51
static gboolean
 
52
entry_focus_change_cb (GtkWidget *widget,
 
53
                       GdkEventFocus *event,
 
54
                       GtkWidget *entry)
 
55
{
 
56
        gtk_widget_queue_draw (entry);
 
57
 
 
58
        return FALSE;
 
59
}
 
60
 
 
61
static void
 
62
ephy_icon_entry_get_borders (GtkWidget *widget,
 
63
                             GtkWidget *entry,
 
64
                             int *xborder,
 
65
                             int *yborder)
 
66
{
 
67
        int focus_width;
 
68
        gboolean interior_focus;
 
69
 
 
70
        g_return_if_fail (entry->style != NULL);
 
71
 
 
72
        gtk_widget_style_get (entry,
 
73
                              "focus-line-width", &focus_width,
 
74
                              "interior-focus", &interior_focus,
 
75
                              NULL);
 
76
 
 
77
        *xborder = entry->style->xthickness;
 
78
        *yborder = entry->style->ythickness;
 
79
 
 
80
        if (!interior_focus)
 
81
        {
 
82
                *xborder += focus_width;
 
83
                *yborder += focus_width;
 
84
        }
 
85
}
 
86
 
 
87
static void
 
88
ephy_icon_entry_paint (GtkWidget *widget,
 
89
                       GdkEventExpose *event)
 
90
{
 
91
        EphyIconEntry *entry = EPHY_ICON_ENTRY (widget);
 
92
        GtkWidget *entry_widget = entry->entry;
 
93
        int x = 0, y = 0, width, height, focus_width;
 
94
        gboolean interior_focus;
 
95
 
 
96
        gtk_widget_style_get (entry_widget,
 
97
                              "interior-focus", &interior_focus,
 
98
                              "focus-line-width", &focus_width,
 
99
                              NULL);
 
100
 
 
101
        gdk_drawable_get_size (widget->window, &width, &height);
 
102
 
 
103
        if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus)
 
104
        {
 
105
                x += focus_width;
 
106
                y += focus_width;
 
107
                width -= 2 * focus_width;
 
108
                height -= 2 * focus_width;
 
109
        }
 
110
 
 
111
        gtk_paint_flat_box (entry_widget->style, widget->window, 
 
112
                            GTK_WIDGET_STATE (entry_widget), GTK_SHADOW_NONE,
 
113
                            NULL, entry_widget, "entry_bg", 
 
114
                            /* FIXME: was 0, 0 in gtk_entry_expose, but I think this is correct: */
 
115
                            x, y, width, height);
 
116
     
 
117
        gtk_paint_shadow (entry_widget->style, widget->window,
 
118
                          GTK_STATE_NORMAL, GTK_SHADOW_IN,
 
119
                          NULL, entry_widget, "entry",
 
120
                          x, y, width, height);
 
121
 
 
122
        if (GTK_WIDGET_HAS_FOCUS (entry_widget) && !interior_focus)
 
123
        {
 
124
                x -= focus_width;
 
125
                y -= focus_width;
 
126
                width += 2 * focus_width;
 
127
                height += 2 * focus_width;
 
128
 
 
129
                gtk_paint_focus (entry_widget->style, widget->window,
 
130
                                 GTK_WIDGET_STATE (entry_widget),
 
131
                                 NULL, entry_widget, "entry",
 
132
                                 /* FIXME: was 0, 0 in gtk_entry_draw_frame, but I think this is correct: */
 
133
                                 x, y, width, height);
 
134
        }
 
135
}
 
136
 
 
137
/* Class implementation */
 
138
 
 
139
static void
 
140
ephy_icon_entry_init (EphyIconEntry *entry)
 
141
{
 
142
        EphyIconEntryPrivate *priv;
 
143
        GtkWidget *widget = (GtkWidget *) entry;
 
144
 
 
145
        priv = entry->priv = EPHY_ICON_ENTRY_GET_PRIVATE (entry);
 
146
 
 
147
        GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW);
 
148
 
 
149
        gtk_container_set_border_width (GTK_CONTAINER (entry), 0);
 
150
 
 
151
        priv->hbox = gtk_hbox_new (FALSE, /* FIXME */ 0);
 
152
        gtk_container_add (GTK_CONTAINER (entry), priv->hbox);
 
153
 
 
154
        entry->entry = gtk_entry_new ();
 
155
        gtk_entry_set_has_frame (GTK_ENTRY (entry->entry), FALSE);
 
156
        gtk_box_pack_start (GTK_BOX (priv->hbox), entry->entry, TRUE, TRUE, /* FIXME */ 0);
 
157
 
 
158
        /* We need to queue a redraw when focus changes, to comply with themes
 
159
         * (like Clearlooks) which draw focused and unfocused entries differently.
 
160
         */
 
161
        g_signal_connect_after (entry->entry, "focus-in-event",
 
162
                                G_CALLBACK (entry_focus_change_cb), entry);
 
163
        g_signal_connect_after (entry->entry, "focus-out-event",
 
164
                                G_CALLBACK (entry_focus_change_cb), entry);
 
165
}
 
166
 
 
167
static void
 
168
ephy_icon_entry_realize (GtkWidget *widget)
 
169
{
 
170
        GdkWindowAttr attributes;
 
171
        gint attributes_mask;
 
172
        gint border_width;
 
173
 
 
174
        GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
175
 
 
176
        border_width = GTK_CONTAINER (widget)->border_width;
 
177
 
 
178
        attributes.x = widget->allocation.x + border_width;
 
179
        attributes.y = widget->allocation.y + border_width;
 
180
        attributes.width = widget->allocation.width - 2 * border_width;
 
181
        attributes.height = widget->allocation.height - 2 * border_width;
 
182
        attributes.window_type = GDK_WINDOW_CHILD;
 
183
        attributes.event_mask = gtk_widget_get_events (widget)
 
184
                                | GDK_EXPOSURE_MASK;
 
185
 
 
186
        attributes.visual = gtk_widget_get_visual (widget);
 
187
        attributes.colormap = gtk_widget_get_colormap (widget);
 
188
        attributes.wclass = GDK_INPUT_OUTPUT;
 
189
        attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
190
 
 
191
        widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
 
192
                                         &attributes, attributes_mask);
 
193
        gdk_window_set_user_data (widget->window, widget);
 
194
 
 
195
        widget->style = gtk_style_attach (widget->style, widget->window);
 
196
 
 
197
        gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 
198
}
 
199
 
 
200
static void
 
201
ephy_icon_entry_size_request (GtkWidget *widget,
 
202
                              GtkRequisition *requisition)
 
203
{
 
204
        EphyIconEntry *entry = EPHY_ICON_ENTRY (widget);
 
205
        GtkContainer *container = GTK_CONTAINER (widget);
 
206
        GtkBin *bin = GTK_BIN (widget);
 
207
        int xborder, yborder;
 
208
 
 
209
        requisition->width = requisition->height = container->border_width * 2;
 
210
 
 
211
        gtk_widget_ensure_style (entry->entry);
 
212
        ephy_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder);
 
213
 
 
214
        if (GTK_WIDGET_VISIBLE (bin->child))
 
215
        {
 
216
                GtkRequisition child_requisition;
 
217
 
 
218
                gtk_widget_size_request (bin->child, &child_requisition);
 
219
                requisition->width += child_requisition.width;
 
220
                requisition->height += child_requisition.height;
 
221
        }
 
222
 
 
223
        requisition->width += 2 * xborder;
 
224
        requisition->height += 2 * yborder;
 
225
}
 
226
 
 
227
static void
 
228
ephy_icon_entry_size_allocate (GtkWidget *widget,
 
229
                               GtkAllocation *allocation)
 
230
{
 
231
        EphyIconEntry *entry = EPHY_ICON_ENTRY (widget);
 
232
        GtkContainer *container = GTK_CONTAINER (widget);
 
233
        GtkBin *bin = GTK_BIN (widget);
 
234
        GtkAllocation child_allocation;
 
235
        GtkRequisition requisition;
 
236
        int xborder, yborder;
 
237
 
 
238
        widget->allocation = *allocation;
 
239
 
 
240
        ephy_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder);
 
241
 
 
242
        if (GTK_WIDGET_REALIZED (widget))
 
243
        {
 
244
                child_allocation.x = container->border_width;
 
245
                child_allocation.y = container->border_width;
 
246
                child_allocation.width = MAX (allocation->width - container->border_width * 2, 0);
 
247
                child_allocation.height = MAX (allocation->height - container->border_width * 2, 0);
 
248
 
 
249
                gdk_window_move_resize (widget->window,
 
250
                                        allocation->x + child_allocation.x,
 
251
                                        allocation->y + child_allocation.y,
 
252
                                        child_allocation.width,
 
253
                                        child_allocation.height);
 
254
        }
 
255
  
 
256
        gtk_widget_get_child_requisition (widget, &requisition);
 
257
 
 
258
        child_allocation.x = container->border_width + xborder;
 
259
        child_allocation.y = container->border_width + yborder 
 
260
                             + (widget->allocation.height - requisition.height) / 2;
 
261
        child_allocation.width = MAX (allocation->width - (container->border_width + xborder) * 2, 0);
 
262
        child_allocation.height = MAX (allocation->height - (container->border_width + yborder) * 2, 0);
 
263
 
 
264
        /* We have to set the size requisition on the GtkEntry explicitly,
 
265
         * since otherwise it'll end up too tall if someone uses
 
266
         * gtk_widget_set_size_request on this EphyIconEntry,
 
267
         * because gtk_entry_size_allocate checks its size with
 
268
         * gtk_widget_get_child_requisition.
 
269
         */
 
270
        gtk_widget_set_size_request (entry->entry, -1, child_allocation.height);
 
271
 
 
272
        gtk_widget_size_allocate (bin->child, &child_allocation);
 
273
}
 
274
 
 
275
static gboolean
 
276
ephy_icon_entry_expose (GtkWidget *widget,
 
277
                        GdkEventExpose *event)
 
278
{
 
279
        if (GTK_WIDGET_DRAWABLE (widget) &&
 
280
            event->window == widget->window)
 
281
        {
 
282
                ephy_icon_entry_paint (widget, event);
 
283
        }
 
284
 
 
285
        return parent_class->expose_event (widget, event);
 
286
}
 
287
 
 
288
static void
 
289
ephy_icon_entry_class_init (EphyIconEntryClass *klass)
 
290
{
 
291
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
292
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
293
 
 
294
        parent_class = GTK_WIDGET_CLASS (g_type_class_peek_parent (klass));
 
295
 
 
296
        widget_class->realize = ephy_icon_entry_realize;
 
297
        widget_class->size_request = ephy_icon_entry_size_request;
 
298
        widget_class->size_allocate = ephy_icon_entry_size_allocate;
 
299
        widget_class->expose_event = ephy_icon_entry_expose;
 
300
 
 
301
        g_type_class_add_private (object_class, sizeof (EphyIconEntryPrivate));
 
302
}
 
303
 
 
304
GType
 
305
ephy_icon_entry_get_type (void)
 
306
{
 
307
        static GType type = 0;
 
308
 
 
309
        if (G_UNLIKELY (type == 0))
 
310
        {
 
311
                static const GTypeInfo our_info =
 
312
                {
 
313
                        sizeof (EphyIconEntryClass),
 
314
                        NULL,
 
315
                        NULL,
 
316
                        (GClassInitFunc) ephy_icon_entry_class_init,
 
317
                        NULL,
 
318
                        NULL,
 
319
                        sizeof (EphyIconEntry),
 
320
                        0,
 
321
                        (GInstanceInitFunc) ephy_icon_entry_init
 
322
                };
 
323
 
 
324
                type = g_type_register_static (GTK_TYPE_BIN,
 
325
                                               "EphyIconEntry",
 
326
                                               &our_info, 0);
 
327
        }
 
328
 
 
329
        return type;
 
330
}
 
331
 
 
332
/* public functions */
 
333
 
 
334
GtkWidget *
 
335
ephy_icon_entry_new (void)
 
336
{
 
337
        return GTK_WIDGET (g_object_new (EPHY_TYPE_ICON_ENTRY, NULL));
 
338
}
 
339
 
 
340
void
 
341
ephy_icon_entry_pack_widget (EphyIconEntry *entry,
 
342
                             GtkWidget *widget,
 
343
                             gboolean start)
 
344
{
 
345
        EphyIconEntryPrivate *priv;
 
346
 
 
347
        g_return_if_fail (EPHY_IS_ICON_ENTRY (entry));
 
348
 
 
349
        priv = entry->priv;
 
350
 
 
351
        if (start)
 
352
        {
 
353
                gtk_box_pack_start (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2);
 
354
                gtk_box_reorder_child (GTK_BOX (priv->hbox), widget, 0);
 
355
        }
 
356
        else
 
357
        {
 
358
                gtk_box_pack_end (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2);
 
359
        }
 
360
}
 
361
 
 
362
GtkWidget *
 
363
ephy_icon_entry_get_entry (EphyIconEntry *entry)
 
364
{
 
365
        g_return_val_if_fail (EPHY_IS_ICON_ENTRY (entry), NULL);
 
366
 
 
367
        return entry->entry;
 
368
}