~ubuntu-branches/ubuntu/utopic/pcmanfm/utopic

« back to all changes in this revision

Viewing changes to src/ptk/ptk-file-icon-renderer.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Lee
  • Date: 2006-10-16 16:47:04 UTC
  • Revision ID: james.westby@ubuntu.com-20061016164704-w8zobnrvdxc7rvm5
Tags: upstream-0.3.2.1
ImportĀ upstreamĀ versionĀ 0.3.2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
*  C Implementation: ptkfileiconrenderer
 
3
*
 
4
* Description: PtkFileIconRenderer is used to render file icons
 
5
*
 
6
*
 
7
* Author: Hong Jen Yee (PCMan) <pcman.tw (AT) gmail.com>, (C) 2006
 
8
*
 
9
* Copyright: See COPYING file that comes with this distribution
 
10
*
 
11
* Part of this class is taken from GtkCellRendererPixbuf written by
 
12
* Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
 
13
*
 
14
*/
 
15
 
 
16
 
 
17
#include "ptk-file-icon-renderer.h"
 
18
 
 
19
static void
 
20
ptk_file_icon_renderer_init ( PtkFileIconRenderer *renderer );
 
21
 
 
22
static void
 
23
ptk_file_icon_renderer_class_init ( PtkFileIconRendererClass *klass );
 
24
 
 
25
static void
 
26
ptk_file_icon_renderer_get_property ( GObject *object,
 
27
                                      guint param_id,
 
28
                                      GValue *value,
 
29
                                      GParamSpec *pspec );
 
30
 
 
31
static void
 
32
ptk_file_icon_renderer_set_property ( GObject *object,
 
33
                                      guint param_id,
 
34
                                      const GValue *value,
 
35
                                      GParamSpec *pspec );
 
36
 
 
37
static void
 
38
ptk_file_icon_renderer_finalize ( GObject *gobject );
 
39
 
 
40
 
 
41
static void
 
42
ptk_file_icon_renderer_get_size ( GtkCellRenderer *cell,
 
43
                                  GtkWidget *widget,
 
44
                                  GdkRectangle *cell_area,
 
45
                                  gint *x_offset,
 
46
                                  gint *y_offset,
 
47
                                  gint *width,
 
48
                                  gint *height );
 
49
 
 
50
 
 
51
static void
 
52
ptk_file_icon_renderer_render ( GtkCellRenderer *cell,
 
53
                                GdkWindow *window,
 
54
                                GtkWidget *widget,
 
55
                                GdkRectangle *background_area,
 
56
                                GdkRectangle *cell_area,
 
57
                                GdkRectangle *expose_area,
 
58
                                guint flags );
 
59
 
 
60
enum
 
61
{
 
62
    PROP_INFO = 1,
 
63
    PROP_FLAGS,
 
64
    PROP_FOLLOW_STATE
 
65
};
 
66
 
 
67
static gpointer parent_class;
 
68
 
 
69
static GdkPixbuf* link_icon = NULL;
 
70
 
 
71
/* GdkPixbuf RGBA C-Source image dump */
 
72
#ifdef __SUNPRO_C
 
73
#pragma align 4 (link_icon_data)
 
74
#endif
 
75
#ifdef __GNUC__
 
76
static const guint8 link_icon_data[] __attribute__ ((__aligned__ (4))) =
 
77
#else
 
78
static const guint8 link_icon_data[] =
 
79
#endif
 
80
    { ""
 
81
      /* Pixbuf magic (0x47646b50) */
 
82
      "GdkP"
 
83
      /* length: header (24) + pixel_data (400) */
 
84
      "\0\0\1\250"
 
85
      /* pixdata_type (0x1010002) */
 
86
      "\1\1\0\2"
 
87
      /* rowstride (40) */
 
88
      "\0\0\0("
 
89
      /* width (10) */
 
90
      "\0\0\0\12"
 
91
      /* height (10) */
 
92
      "\0\0\0\12"
 
93
      /* pixel_data: */
 
94
      "\200\200\200\377\200\200\200\377\200\200\200\377\200\200\200\377\200"
 
95
      "\200\200\377\200\200\200\377\200\200\200\377\200\200\200\377\200\200"
 
96
      "\200\377\0\0\0\377\200\200\200\377\377\377\377\377\377\377\377\377\377"
 
97
      "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
 
98
      "\377\377\377\377\377\377\0\0\0\377\200\200\200\377\377\377\377\377\0"
 
99
      "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377"
 
100
      "\377\377\377\0\0\0\377\200\200\200\377\377\377\377\377\0\0\0\377\0\0"
 
101
      "\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\377\377\377"
 
102
      "\377\0\0\0\377\200\200\200\377\377\377\377\377\0\0\0\377\0\0\0\377\0"
 
103
      "\0\0\377\0\0\0\377\0\0\0\377\377\377\377\377\377\377\377\377\0\0\0\377"
 
104
      "\200\200\200\377\377\377\377\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0"
 
105
      "\377\0\0\0\377\0\0\0\377\377\377\377\377\0\0\0\377\200\200\200\377\377"
 
106
      "\377\377\377\0\0\0\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0"
 
107
      "\0\377\0\0\0\377\377\377\377\377\0\0\0\377\200\200\200\377\377\377\377"
 
108
      "\377\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0"
 
109
      "\377\0\0\0\377\377\377\377\377\0\0\0\377\200\200\200\377\377\377\377"
 
110
      "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
 
111
      "\377\377\377\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0\377"
 
112
      "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377"
 
113
      "\0\0\0\377\0\0\0\377"
 
114
    };
 
115
 
 
116
 
 
117
/***************************************************************************
 
118
 *
 
119
 *  ptk_file_icon_renderer_get_type: here we register our type with
 
120
 *                                          the GObject type system if we
 
121
 *                                          haven't done so yet. Everything
 
122
 *                                          else is done in the callbacks.
 
123
 *
 
124
 ***************************************************************************/
 
125
 
 
126
GType
 
127
ptk_file_icon_renderer_get_type ( void )
 
128
{
 
129
    static GType renderer_type = 0;
 
130
    if ( G_UNLIKELY( !renderer_type ) )
 
131
    {
 
132
        static const GTypeInfo renderer_info =
 
133
            {
 
134
                sizeof ( PtkFileIconRendererClass ),
 
135
                NULL,                                                        /* base_init */
 
136
                NULL,                                                        /* base_finalize */
 
137
                ( GClassInitFunc ) ptk_file_icon_renderer_class_init,
 
138
                NULL,                                                        /* class_finalize */
 
139
                NULL,                                                        /* class_data */
 
140
                sizeof ( PtkFileIconRenderer ),
 
141
                0,                                                           /* n_preallocs */
 
142
                ( GInstanceInitFunc ) ptk_file_icon_renderer_init,
 
143
            };
 
144
 
 
145
        /* Derive from GtkCellRendererPixbuf */
 
146
        renderer_type = g_type_register_static ( GTK_TYPE_CELL_RENDERER_PIXBUF,
 
147
                                                 "PtkFileIconRenderer",
 
148
                                                 &renderer_info,
 
149
                                                 0 );
 
150
    }
 
151
 
 
152
    return renderer_type;
 
153
}
 
154
 
 
155
 
 
156
/***************************************************************************
 
157
 *
 
158
 *  ptk_file_icon_renderer_init: set some default properties of the
 
159
 *                                      parent (GtkCellRendererPixbuf).
 
160
 *
 
161
 ***************************************************************************/
 
162
 
 
163
static void
 
164
ptk_file_icon_renderer_init ( PtkFileIconRenderer *renderer )
 
165
{
 
166
    if ( !link_icon )
 
167
    {
 
168
        link_icon = gdk_pixbuf_new_from_inline(
 
169
                sizeof(link_icon_data),
 
170
                link_icon_data,
 
171
                FALSE, NULL );
 
172
        g_object_add_weak_pointer( G_OBJECT(link_icon), (gpointer)&link_icon  );
 
173
    }
 
174
    else
 
175
        gdk_pixbuf_ref( (link_icon) );
 
176
}
 
177
 
 
178
 
 
179
/***************************************************************************
 
180
 *
 
181
 *  ptk_file_icon_renderer_class_init:
 
182
 *
 
183
 ***************************************************************************/
 
184
 
 
185
static void
 
186
ptk_file_icon_renderer_class_init ( PtkFileIconRendererClass *klass )
 
187
{
 
188
    GtkCellRendererClass * parent_renderer_class = GTK_CELL_RENDERER_CLASS( klass );
 
189
    GObjectClass *object_class = G_OBJECT_CLASS( klass );
 
190
 
 
191
    parent_class = g_type_class_peek_parent ( klass );
 
192
    object_class->finalize = ptk_file_icon_renderer_finalize;
 
193
 
 
194
    /* Hook up functions to set and get our
 
195
    *   custom cell renderer properties */
 
196
    object_class->get_property = ptk_file_icon_renderer_get_property;
 
197
    object_class->set_property = ptk_file_icon_renderer_set_property;
 
198
 
 
199
    parent_renderer_class->get_size = ptk_file_icon_renderer_get_size;
 
200
    parent_renderer_class->render = ptk_file_icon_renderer_render;
 
201
 
 
202
    g_object_class_install_property ( object_class,
 
203
                                      PROP_INFO,
 
204
                                      g_param_spec_pointer ( "info",
 
205
                                                             "File info",
 
206
                                                             "File info",
 
207
                                                             G_PARAM_READWRITE ) );
 
208
    g_object_class_install_property ( object_class,
 
209
                                      PROP_FOLLOW_STATE,
 
210
                                      g_param_spec_boolean ( "follow-state",
 
211
                                                             "Follow State",
 
212
                                                             "Whether the rendered pixbuf should be "
 
213
                                                             "colorized according to the state",
 
214
                                                             FALSE,
 
215
                                                             G_PARAM_READWRITE ) );
 
216
}
 
217
 
 
218
 
 
219
/***************************************************************************
 
220
 *
 
221
 *  ptk_file_icon_renderer_finalize: free any resources here
 
222
 *
 
223
 ***************************************************************************/
 
224
 
 
225
static void
 
226
ptk_file_icon_renderer_finalize ( GObject *object )
 
227
{
 
228
    PtkFileIconRenderer* renderer = PTK_FILE_ICON_RENDERER(object); 
 
229
    if( renderer->info )
 
230
        vfs_file_info_unref( renderer->info );
 
231
 
 
232
    gdk_pixbuf_unref( (link_icon) );
 
233
    ( * G_OBJECT_CLASS ( parent_class ) ->finalize ) ( object );
 
234
}
 
235
 
 
236
/***************************************************************************
 
237
 *
 
238
 *  ptk_file_icon_renderer_get_property: as it says
 
239
 *
 
240
 ***************************************************************************/
 
241
 
 
242
static void
 
243
ptk_file_icon_renderer_get_property ( GObject *object,
 
244
                                      guint param_id,
 
245
                                      GValue *value,
 
246
                                      GParamSpec *psec )
 
247
{
 
248
    PtkFileIconRenderer * renderer = PTK_FILE_ICON_RENDERER( object );
 
249
 
 
250
    switch ( param_id )
 
251
    {
 
252
        /*    case PROP_FLAGS:
 
253
              g_value_set_long(value, renderer->flags);
 
254
              break;
 
255
        */
 
256
    case PROP_INFO:
 
257
        if( renderer->info )
 
258
            vfs_file_info_ref( renderer->info );
 
259
        g_value_set_pointer( value, renderer->info );
 
260
 
 
261
    case PROP_FOLLOW_STATE:
 
262
        g_value_set_boolean ( value, renderer->follow_state );
 
263
 
 
264
    default:
 
265
        G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, param_id, psec );
 
266
        break;
 
267
    }
 
268
}
 
269
 
 
270
 
 
271
/***************************************************************************
 
272
 *
 
273
 *  ptk_file_icon_renderer_set_property: as it says
 
274
 *
 
275
 ***************************************************************************/
 
276
 
 
277
static void
 
278
ptk_file_icon_renderer_set_property ( GObject *object,
 
279
                                      guint param_id,
 
280
                                      const GValue *value,
 
281
                                      GParamSpec *pspec )
 
282
{
 
283
    PtkFileIconRenderer * renderer = PTK_FILE_ICON_RENDERER ( object );
 
284
 
 
285
    switch ( param_id )
 
286
    {
 
287
    case PROP_INFO:
 
288
        if( renderer->info )
 
289
            vfs_file_info_unref( renderer->info );
 
290
        renderer->info = g_value_get_pointer( value );
 
291
        break;
 
292
 
 
293
        /*
 
294
            case PROP_FLAGS:
 
295
              renderer->flags = g_value_get_long(value);
 
296
              break;
 
297
        */
 
298
 
 
299
    case PROP_FOLLOW_STATE:
 
300
        renderer->follow_state = g_value_get_boolean ( value );
 
301
        break;
 
302
 
 
303
    default:
 
304
        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, param_id, pspec );
 
305
        break;
 
306
    }
 
307
}
 
308
 
 
309
/***************************************************************************
 
310
 *
 
311
 *  ptk_file_icon_renderer_new: return a new cell renderer instance
 
312
 *
 
313
 ***************************************************************************/
 
314
 
 
315
GtkCellRenderer *
 
316
ptk_file_icon_renderer_new ( void )
 
317
{
 
318
    return ( GtkCellRenderer* ) g_object_new( PTK_TYPE_FILE_ICON_RENDERER, NULL );
 
319
}
 
320
 
 
321
 
 
322
static GdkPixbuf *
 
323
create_colorized_pixbuf ( GdkPixbuf *src,
 
324
                          GdkColor *new_color )
 
325
{
 
326
    gint i, j;
 
327
    gint width, height, has_alpha, src_row_stride, dst_row_stride;
 
328
    gint red_value, green_value, blue_value;
 
329
    guchar *target_pixels;
 
330
    guchar *original_pixels;
 
331
    guchar *pixsrc;
 
332
    guchar *pixdest;
 
333
    GdkPixbuf *dest;
 
334
 
 
335
    red_value = new_color->red / 255.0;
 
336
    green_value = new_color->green / 255.0;
 
337
    blue_value = new_color->blue / 255.0;
 
338
 
 
339
    dest = gdk_pixbuf_new ( gdk_pixbuf_get_colorspace ( src ),
 
340
                            gdk_pixbuf_get_has_alpha ( src ),
 
341
                            gdk_pixbuf_get_bits_per_sample ( src ),
 
342
                            gdk_pixbuf_get_width ( src ),
 
343
                            gdk_pixbuf_get_height ( src ) );
 
344
 
 
345
    has_alpha = gdk_pixbuf_get_has_alpha ( src );
 
346
    width = gdk_pixbuf_get_width ( src );
 
347
    height = gdk_pixbuf_get_height ( src );
 
348
    src_row_stride = gdk_pixbuf_get_rowstride ( src );
 
349
    dst_row_stride = gdk_pixbuf_get_rowstride ( dest );
 
350
    target_pixels = gdk_pixbuf_get_pixels ( dest );
 
351
    original_pixels = gdk_pixbuf_get_pixels ( src );
 
352
 
 
353
    for ( i = 0; i < height; i++ )
 
354
    {
 
355
        pixdest = target_pixels + i * dst_row_stride;
 
356
        pixsrc = original_pixels + i * src_row_stride;
 
357
        for ( j = 0; j < width; j++ )
 
358
        {
 
359
            *pixdest++ = ( *pixsrc++ * red_value ) >> 8;
 
360
            *pixdest++ = ( *pixsrc++ * green_value ) >> 8;
 
361
            *pixdest++ = ( *pixsrc++ * blue_value ) >> 8;
 
362
            if ( has_alpha )
 
363
            {
 
364
                *pixdest++ = *pixsrc++;
 
365
            }
 
366
        }
 
367
    }
 
368
    return dest;
 
369
}
 
370
 
 
371
 
 
372
/***************************************************************************
 
373
    *
 
374
    *  ptk_file_icon_renderer_render: crucial - do the rendering.
 
375
    *
 
376
 ***************************************************************************/
 
377
 
 
378
static void
 
379
ptk_file_icon_renderer_render ( GtkCellRenderer *cell,
 
380
                                GdkWindow *window,
 
381
                                GtkWidget *widget,
 
382
                                GdkRectangle *background_area,
 
383
                                GdkRectangle *cell_area,
 
384
                                GdkRectangle *expose_area,
 
385
                                guint flags )
 
386
{
 
387
    GtkCellRendererPixbuf * cellpixbuf = ( GtkCellRendererPixbuf * ) cell;
 
388
 
 
389
    GdkPixbuf *pixbuf;
 
390
    GdkPixbuf *invisible = NULL;
 
391
    GdkPixbuf *colorized = NULL;
 
392
    GdkRectangle pix_rect;
 
393
    GdkRectangle draw_rect;
 
394
    VFSFileInfo* file;
 
395
 
 
396
#if GTK_CHECK_VERSION( 2, 8, 0 )
 
397
 
 
398
    cairo_t *cr;
 
399
#endif
 
400
 
 
401
    GtkCellRendererClass* parent_renderer_class;
 
402
 
 
403
    parent_renderer_class = GTK_CELL_RENDERER_CLASS( parent_class );
 
404
 
 
405
    parent_renderer_class->get_size ( cell, widget, cell_area,
 
406
                                      &pix_rect.x,
 
407
                                      &pix_rect.y,
 
408
                                      &pix_rect.width,
 
409
                                      &pix_rect.height );
 
410
 
 
411
    pix_rect.x += cell_area->x;
 
412
    pix_rect.y += cell_area->y;
 
413
    pix_rect.width -= cell->xpad * 2;
 
414
    pix_rect.height -= cell->ypad * 2;
 
415
 
 
416
    if ( !gdk_rectangle_intersect ( cell_area, &pix_rect, &draw_rect ) ||
 
417
            !gdk_rectangle_intersect ( expose_area, &draw_rect, &draw_rect ) )
 
418
        return ;
 
419
 
 
420
    pixbuf = cellpixbuf->pixbuf;
 
421
 
 
422
    if ( cell->is_expander )
 
423
    {
 
424
        if ( cell->is_expanded &&
 
425
                cellpixbuf->pixbuf_expander_open != NULL )
 
426
            pixbuf = cellpixbuf->pixbuf_expander_open;
 
427
        else if ( !cell->is_expanded &&
 
428
                  cellpixbuf->pixbuf_expander_closed != NULL )
 
429
            pixbuf = cellpixbuf->pixbuf_expander_closed;
 
430
    }
 
431
 
 
432
    if ( !pixbuf )
 
433
        return ;
 
434
 
 
435
    if ( PTK_FILE_ICON_RENDERER( cell ) ->follow_state )
 
436
    {
 
437
        if ( GTK_WIDGET_STATE ( widget ) == GTK_STATE_INSENSITIVE || !cell->sensitive )
 
438
        {
 
439
            GtkIconSource * source;
 
440
 
 
441
            source = gtk_icon_source_new ();
 
442
            gtk_icon_source_set_pixbuf ( source, pixbuf );
 
443
            /* The size here is arbitrary; since size isn't
 
444
            * wildcarded in the source, it isn't supposed to be
 
445
            * scaled by the engine function
 
446
            */
 
447
            gtk_icon_source_set_size ( source, GTK_ICON_SIZE_SMALL_TOOLBAR );
 
448
            gtk_icon_source_set_size_wildcarded ( source, FALSE );
 
449
 
 
450
            invisible = gtk_style_render_icon ( widget->style,
 
451
                                                source,
 
452
                                                gtk_widget_get_direction ( widget ),
 
453
                                                GTK_STATE_INSENSITIVE,
 
454
                                                /* arbitrary */
 
455
                                                ( GtkIconSize ) - 1,
 
456
                                                widget,
 
457
                                                "gtkcellrendererpixbuf" );
 
458
 
 
459
            gtk_icon_source_free ( source );
 
460
            pixbuf = invisible;
 
461
        }
 
462
        else if ( ( flags & ( GTK_CELL_RENDERER_SELECTED /*|GTK_CELL_RENDERER_PRELIT*/ ) ) != 0 )
 
463
        {
 
464
            GtkStateType state;
 
465
            GdkColor* color;
 
466
 
 
467
            if ( ( flags & GTK_CELL_RENDERER_SELECTED ) != 0 )
 
468
            {
 
469
                if ( GTK_WIDGET_HAS_FOCUS ( widget ) )
 
470
                    state = GTK_STATE_SELECTED;
 
471
                else
 
472
                    state = GTK_STATE_ACTIVE;
 
473
                color = &widget->style->base[ state ];
 
474
            }
 
475
            else
 
476
            {
 
477
                state = GTK_STATE_PRELIGHT;
 
478
            }
 
479
 
 
480
            colorized = create_colorized_pixbuf ( pixbuf,
 
481
                                                  color );
 
482
 
 
483
            pixbuf = colorized;
 
484
        }
 
485
    }
 
486
#if GTK_CHECK_VERSION(2, 8, 0)
 
487
    cr = gdk_cairo_create ( window );
 
488
    gdk_cairo_set_source_pixbuf ( cr, pixbuf, pix_rect.x, pix_rect.y );
 
489
    gdk_cairo_rectangle ( cr, &draw_rect );
 
490
    cairo_fill ( cr );
 
491
#else
 
492
    gdk_draw_pixbuf ( GDK_DRAWABLE ( window ), NULL, pixbuf, 0, 0,
 
493
                      pix_rect.x, pix_rect.y, pix_rect.width, pix_rect.height,
 
494
                      GDK_RGB_DITHER_NORMAL, 0, 0 );
 
495
#endif
 
496
 
 
497
    file = PTK_FILE_ICON_RENDERER( cell )->info;
 
498
    if ( file )
 
499
    {
 
500
        if ( vfs_file_info_is_symlink( file ) )
 
501
        {
 
502
#if GTK_CHECK_VERSION(2, 8, 0)
 
503
            gdk_cairo_set_source_pixbuf ( cr, link_icon,
 
504
                                          pix_rect.x - 2,
 
505
                                          pix_rect.y - 2 );
 
506
            draw_rect.x -= 2;
 
507
            draw_rect.y -= 2;
 
508
            gdk_cairo_rectangle ( cr, &draw_rect );
 
509
            cairo_fill ( cr );
 
510
#else
 
511
 
 
512
            gdk_draw_pixbuf ( GDK_DRAWABLE ( window ), NULL, link_icon, 0, 0,
 
513
                              pix_rect.x - 2, pix_rect.y - 2,
 
514
                              -1, -1, GDK_RGB_DITHER_NORMAL,
 
515
                              0, 0 );
 
516
#endif
 
517
        }
 
518
    }
 
519
 
 
520
#if GTK_CHECK_VERSION(2, 8, 0)
 
521
    cairo_destroy ( cr );
 
522
#endif
 
523
 
 
524
    if ( invisible )
 
525
        g_object_unref ( invisible );
 
526
 
 
527
    if ( colorized )
 
528
        g_object_unref ( colorized );
 
529
 
 
530
}
 
531
 
 
532
void ptk_file_icon_renderer_get_size ( GtkCellRenderer *cell,
 
533
                                       GtkWidget *widget,
 
534
                                       GdkRectangle *cell_area,
 
535
                                       gint *x_offset,
 
536
                                       gint *y_offset,
 
537
                                       gint *width,
 
538
                                       gint *height )
 
539
{
 
540
    GTK_CELL_RENDERER_CLASS( parent_class )->get_size( cell, widget, cell_area,
 
541
                                                       x_offset, y_offset,
 
542
                                                       width, height );
 
543
 
 
544
    if ( *width > *height )
 
545
        * height = *width;
 
546
    else if ( *width < *height )
 
547
        * width = *height;
 
548
}
 
549
 
 
550