fix crash when copy'ing latent plugins
[ardour.git] / libs / clearlooks-older / clearlooks_draw.c
1 #include "clearlooks_draw.h"
2 #include "clearlooks_style.h"
3
4 #include "support.h"
5
6 /** WANTED:
7     FASTER GRADIENT FILL FUNCTION, POSSIBLY USING XRENDER. **/
8
9 static void cl_draw_borders (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
10                       int x, int y, int width, int height, CLRectangle *r);
11
12 static void cl_draw_line (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
13                    int x1, int y1, int x2, int y2, CLBorderType border,
14                    CLRectangle *r);
15
16 static void cl_draw_corner (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
17                      int x, int y, int width, int height,
18                      CLRectangle *r, CLCornerSide corner);
19
20 static void cl_draw_fill (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
21                    int x, int y, int width, int height, CLRectangle *r);
22
23 void cl_draw_rectangle (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
24                         int x, int y, int width, int height, CLRectangle *r)
25 {
26         if (r->fillgc)
27         {
28                 cl_draw_fill(window, widget, style, x, y, width, height, r);
29         }
30
31         if (r->bordergc)
32         {
33                 cl_draw_borders(window, widget, style, x, y, width, height, r);
34         }
35 }
36
37
38 static void cl_get_coords ( CLBorderType border,
39                      int x, int y, int width, int height,
40                      CLRectangle *r, int *x1, int *y1, int *x2, int *y2)
41 {
42         switch (border)
43         {
44                 case CL_BORDER_TOP:
45                         *x1 = x + r->corners[CL_CORNER_TOPLEFT];
46                         *x2 = *x1 + width - r->corners[CL_CORNER_TOPLEFT] - r->corners[CL_CORNER_TOPRIGHT] - 1;
47                         *y1 = *y2 = y;
48                         break;
49                 case CL_BORDER_BOTTOM:
50                         *x1 = x + r->corners[CL_CORNER_BOTTOMLEFT];
51                         *x2 = *x1 + width - r->corners[CL_CORNER_BOTTOMLEFT] - r->corners[CL_CORNER_BOTTOMRIGHT] - 1;
52                         *y1 = *y2 = y + height - 1;
53                         break;
54                 case CL_BORDER_LEFT:
55                         *x1 = *x2 = x;
56                         *y1 = y + r->corners[CL_CORNER_TOPLEFT];
57                         *y2 = *y1 + height - r->corners[CL_CORNER_TOPLEFT] - r->corners[CL_CORNER_BOTTOMLEFT] - 1;
58                         break;
59                 case CL_BORDER_RIGHT:
60                         *x1 = *x2 = x + width - 1;
61                         *y1 = y + r->corners[CL_CORNER_TOPRIGHT];
62                         *y2 = *y1 + height - r->corners[CL_CORNER_TOPRIGHT] - r->corners[CL_CORNER_BOTTOMRIGHT] - 1;
63                         break;
64         }
65 }
66
67 void cl_draw_borders (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
68                       int x, int y, int width, int height, CLRectangle *r)
69 {
70         int x1, y1, x2, y2, i;
71
72         if (r->bordergc == NULL)
73                 return;
74
75         for ( i=0; i<4; i++) /* draw all four borders + corners */
76         {
77                 cl_get_coords (i, x, y, width, height, r, &x1, &y1, &x2, &y2);
78                 cl_draw_line (window, widget, style, x1, y1, x2, y2, i, r);
79                 cl_draw_corner (window, widget, style, x, y, width, height, r, i );
80         }
81 }
82
83
84 static GdkColor cl_gc_get_foreground(GdkGC *gc)
85 {
86         GdkGCValues values;
87         gdk_gc_get_values (gc, &values);
88         return values.foreground;
89 }
90
91 static void cl_draw_line (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
92                    int x1, int y1, int x2, int y2, CLBorderType border,
93                    CLRectangle *r)
94 {
95         if (r->gradient_type == CL_GRADIENT_NONE ||
96                 r->border_gradient.from == NULL || r->border_gradient.to == NULL )
97         {
98                 gdk_draw_line (window, r->bordergc, x1, y1, x2, y2);
99         }
100         else if (r->gradient_type == CL_GRADIENT_HORIZONTAL && (border == CL_BORDER_TOP || border == CL_BORDER_BOTTOM))
101         {
102                 draw_vgradient (window, r->bordergc, style,
103                                 x1, y1, x2-x1+1, 1,
104                                 r->border_gradient.from, r->border_gradient.to);
105         }
106         else if (r->gradient_type == CL_GRADIENT_VERTICAL && (border == CL_BORDER_LEFT || border == CL_BORDER_RIGHT))
107         {
108                 draw_hgradient (window, r->bordergc, style,
109                                 x1, y1, 1, y2-y1+1,
110                                 r->border_gradient.from, r->border_gradient.to);
111         }
112         else
113         {
114                 GdkColor tmp_color = cl_gc_get_foreground (r->bordergc);
115
116                 if (r->gradient_type == CL_GRADIENT_HORIZONTAL && border == CL_BORDER_LEFT ||
117                         r->gradient_type == CL_GRADIENT_VERTICAL && border == CL_BORDER_TOP)
118                         gdk_gc_set_foreground (r->bordergc, r->border_gradient.from);
119                 else
120                         gdk_gc_set_foreground (r->bordergc, r->border_gradient.to);
121
122                 gdk_draw_line (window, r->bordergc, x1, y1, x2, y2);
123
124                 gdk_gc_set_foreground (r->bordergc, &tmp_color);
125         }
126 }
127
128 static GdkColor *cl_get_gradient_corner_color (CLRectangle *r, CLCornerSide corner)
129 {
130         GdkColor *color;
131
132         if (r->border_gradient.from == NULL || r->border_gradient.to == NULL)
133         {
134                 color = NULL;
135         }
136         else if ((r->gradient_type == CL_GRADIENT_HORIZONTAL && (corner == CL_CORNER_TOPLEFT || corner == CL_CORNER_BOTTOMLEFT)) ||
137             (r->gradient_type == CL_GRADIENT_VERTICAL && (corner == CL_CORNER_TOPLEFT || corner == CL_CORNER_TOPRIGHT)))
138         {
139                 color = r->border_gradient.from;
140         }
141         else /* no gradient or other corner */
142         {
143                 color = r->border_gradient.to;
144         }
145
146         return color;
147 }
148
149 static void cl_draw_corner (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
150                      int x, int y, int width, int height,
151                      CLRectangle *r, CLCornerSide corner)
152 {
153         GdkColor    *color;
154         GdkColor     aacolor; /* anti-aliasing color */
155         GdkGCValues  values;
156         GdkColor     tmp;
157         GdkColor    *bgcolor;
158
159         int x1;
160         int y1;
161
162         if (r->corners[corner] == CL_CORNER_NONE)
163                 return;
164
165         color = cl_get_gradient_corner_color (r, corner);
166         gdk_gc_get_values (r->bordergc, &values);
167
168         if (color == NULL)
169         {
170                 tmp = values.foreground;
171                 gdk_colormap_query_color (gtk_widget_get_colormap(widget), values.foreground.pixel, &tmp);
172                 color = &tmp;
173         }
174
175         bgcolor = get_parent_bgcolor(widget);
176
177         if (bgcolor == NULL)
178         {
179                 bgcolor = color;
180         }
181
182         blend (style->colormap, bgcolor, color, &aacolor, 70);
183
184         if (r->corners[corner] == CL_CORNER_ROUND)
185         {
186                 x1 = (corner == CL_CORNER_TOPLEFT ||
187                       corner == CL_CORNER_BOTTOMLEFT) ? x+1 : x+width - 2;
188
189                 y1 = (corner == CL_CORNER_TOPLEFT ||
190                       corner == CL_CORNER_TOPRIGHT) ? y+1 : y+height - 2;
191
192                 gdk_gc_set_foreground (r->bordergc, color);
193                 gdk_draw_point (window, r->bordergc, x1, y1);
194
195                 gdk_gc_set_foreground (r->bordergc, &aacolor);
196
197                 x1 = (corner == CL_CORNER_TOPLEFT ||
198                       corner == CL_CORNER_BOTTOMLEFT) ? x+1 : x+width-2;
199
200                 y1 = (corner == CL_CORNER_TOPLEFT ||
201                       corner == CL_CORNER_TOPRIGHT) ? y : y+height-1;
202
203                 gdk_draw_point (window, r->bordergc, x1, y1);
204
205                 x1 = (corner == CL_CORNER_TOPLEFT ||
206                       corner == CL_CORNER_BOTTOMLEFT) ? x : x+width-1;
207
208                 y1 = (corner == CL_CORNER_TOPLEFT ||
209                       corner == CL_CORNER_TOPRIGHT) ? y+1 : y+height-2;
210
211                 gdk_draw_point (window, r->bordergc, x1, y1);
212
213         }
214         else if (r->corners[corner] == CL_CORNER_NARROW)
215         {
216                 x1 = (corner == CL_CORNER_TOPLEFT ||
217                       corner == CL_CORNER_BOTTOMLEFT) ? x : x+width-1;
218
219                 y1 = (corner == CL_CORNER_TOPLEFT ||
220                       corner == CL_CORNER_TOPRIGHT) ? y : y+height-1;
221
222                 gdk_gc_set_foreground (r->bordergc, &aacolor);
223                 gdk_draw_point (window, r->bordergc, x1, y1);
224         }
225
226         gdk_gc_set_foreground (r->bordergc, &values.foreground);
227 }
228
229 static void cl_draw_fill (GdkWindow *window, GtkWidget *widget, GtkStyle *style,
230                    int x, int y, int width, int height, CLRectangle *r)
231 {
232         if (r->gradient_type == CL_GRADIENT_NONE ||
233                 r->fill_gradient.from == NULL || r->fill_gradient.to == NULL)
234         {
235                 gdk_draw_rectangle (window, r->fillgc, TRUE,
236                                     x+1, y+1, width-2, height-2);
237         }
238         else if (r->gradient_type == CL_GRADIENT_HORIZONTAL)
239         {
240                 draw_vgradient (window, r->fillgc, gtk_widget_get_style(widget),
241                                 x+1, y+1, width-2, height-2,
242                                 r->fill_gradient.from, r->fill_gradient.to);
243         }
244         else if (r->gradient_type == CL_GRADIENT_VERTICAL)
245         {
246                 draw_hgradient (window, r->fillgc, gtk_widget_get_style(widget),
247                                 x+1, y+1, width-2, height-2,
248                                 r->fill_gradient.from, r->fill_gradient.to);
249         }
250 }
251
252 void cl_rectangle_set_button(CLRectangle *r, GtkStyle *style,
253                             GtkStateType state_type,  gboolean has_default,
254                             gboolean has_focus,
255                             CLBorderType tl, CLBorderType tr,
256                             CLBorderType bl, CLBorderType br)
257 {
258         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
259         int              my_state_type = (state_type == GTK_STATE_ACTIVE) ? 2 : 0;
260         GdkGC           *border_gc = clearlooks_style->border_gc[CL_BORDER_UPPER+my_state_type];
261
262
263         cl_rectangle_init (r, style->bg_gc[state_type],
264                            clearlooks_style->border_gc[CL_BORDER_UPPER+my_state_type],
265                            tl, tr, bl, br);
266
267         if (state_type != GTK_STATE_INSENSITIVE && !has_default)
268         {
269                 cl_rectangle_set_gradient (&r->border_gradient,
270                                            &clearlooks_style->border[CL_BORDER_UPPER+my_state_type],
271                                            &clearlooks_style->border[CL_BORDER_LOWER+my_state_type]);
272         }
273         else if (has_default)
274                 r->bordergc = style->black_gc;
275         else
276                 r->bordergc = clearlooks_style->shade_gc[4];
277
278         r->gradient_type = CL_GRADIENT_VERTICAL;
279
280         r->topleft     = (state_type != GTK_STATE_ACTIVE) ? style->light_gc[state_type] : clearlooks_style->shade_gc[4];
281         r->bottomright = (state_type != GTK_STATE_ACTIVE) ? clearlooks_style->shade_gc[1] : NULL;
282
283         shade (&style->bg[state_type], &r->tmp_color, 0.93);
284
285
286         cl_rectangle_set_gradient (&r->fill_gradient,
287                                    &style->bg[state_type],
288                                    &r->tmp_color);
289 }
290
291 void cl_rectangle_set_entry (CLRectangle *r, GtkStyle *style,
292                             GtkStateType state_type,
293                             CLBorderType tl, CLBorderType tr,
294                             CLBorderType bl, CLBorderType br,
295                             gboolean has_focus)
296 {
297         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
298         GdkGC *bordergc;
299
300         if (has_focus)
301                 bordergc = clearlooks_style->spot3_gc;
302         else if (state_type != GTK_STATE_INSENSITIVE)
303                 bordergc = clearlooks_style->border_gc[CL_BORDER_LOWER];
304         else
305                 bordergc = clearlooks_style->shade_gc[3];
306
307         cl_rectangle_init (r, style->base_gc[state_type], bordergc,
308                        tl, tr, bl, br);
309
310         if (state_type != GTK_STATE_INSENSITIVE )
311                 r->topleft     = (has_focus) ? clearlooks_style->spot1_gc
312                                          : style->bg_gc[GTK_STATE_NORMAL];
313
314         if (has_focus)
315                 r->bottomright = clearlooks_style->spot1_gc;
316         else if (state_type == GTK_STATE_INSENSITIVE)
317                 r->bottomright = style->base_gc[state_type];
318 }
319
320 void cl_draw_shadow(GdkWindow *window, GtkWidget *widget, GtkStyle *style,
321                     int x, int y, int width, int height, CLRectangle *r)
322 {
323         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
324         int x1, y1, x2, y2;
325
326         if (r->bottomright != NULL)
327         {
328                 x1 = x+1+(r->corners[CL_CORNER_BOTTOMLEFT]/2);
329                 y1 = y2 = y+height-2;
330                 x2 = x+width - 1 - (1+r->corners[CL_CORNER_BOTTOMRIGHT]/2);
331
332                 gdk_draw_line (window, r->bottomright, x1, y1, x2, y2);
333
334                 x1 = x2 = x+width-2;
335                 y1 = y+1+(r->corners[CL_CORNER_TOPRIGHT]/2);
336                 y2 = y+height - 1 - (1+r->corners[CL_CORNER_BOTTOMRIGHT]/2);
337
338                 gdk_draw_line (window, r->bottomright, x1, y1, x2, y2);
339         }
340
341         if (r->topleft != NULL)
342         {
343                 x1 = x+1+(r->corners[CL_CORNER_TOPLEFT]/2);
344                 y1 = y2 = y+1;
345                 x2 = x+width-1-(1+r->corners[CL_CORNER_TOPRIGHT]/2);
346
347                 gdk_draw_line (window, r->topleft, x1, y1, x2, y2);
348
349                 x1 = x2 = x+1;
350                 y1 = y+1+(r->corners[CL_CORNER_TOPLEFT]/2);
351                 y2 = y+height-1-(1+r->corners[CL_CORNER_BOTTOMLEFT]/2);
352
353                 gdk_draw_line (window, r->topleft, x1, y1, x2, y2);
354         }
355 }
356
357 void cl_rectangle_set_color (CLGradient *g, GdkColor *color)
358 {
359         g->from = color;
360         g->to   = color;
361 }
362
363 void cl_rectangle_set_gradient (CLGradient *g, GdkColor *from, GdkColor *to)
364 {
365         g->from = from;
366         g->to   = to;
367 }
368
369 void cl_rectangle_init (CLRectangle *r,
370                         GdkGC *fillgc, GdkGC *bordergc,
371                         int tl, int tr, int bl, int br)
372 {
373         r->gradient_type = CL_GRADIENT_NONE;
374
375         r->border_gradient.from = r->border_gradient.to = NULL;
376         r->fill_gradient.from   = r->fill_gradient.to   = NULL;
377
378         r->fillgc      = fillgc;
379         r->bordergc    = bordergc;
380
381         r->topleft     = NULL;
382         r->bottomright = NULL;
383
384         r->corners[CL_CORNER_TOPLEFT] = tl;
385         r->corners[CL_CORNER_TOPRIGHT] = tr;
386         r->corners[CL_CORNER_BOTTOMLEFT] = bl;
387         r->corners[CL_CORNER_BOTTOMRIGHT] = br;
388 }
389
390 void cl_rectangle_set_corners (CLRectangle *r, int tl, int tr, int bl, int br)
391 {
392         r->corners[CL_CORNER_TOPLEFT] = tl;
393         r->corners[CL_CORNER_TOPRIGHT] = tr;
394         r->corners[CL_CORNER_BOTTOMLEFT] = bl;
395         r->corners[CL_CORNER_BOTTOMRIGHT] = br;
396 }
397
398 void cl_set_corner_sharpness (const gchar *detail, GtkWidget *widget, CLRectangle *r)
399 {
400         if (widget->parent && GTK_IS_COMBO_BOX_ENTRY (widget->parent) || GTK_IS_COMBO (widget->parent))
401         {
402                 gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL;
403                 int cl = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE;
404                 int cr = rtl ? CL_CORNER_NONE  : CL_CORNER_ROUND;
405
406                 cl_rectangle_set_corners (r, cl, cr, cl, cr);
407         }
408         else if (detail && !strcmp (detail, "spinbutton_up"))
409         {
410                 gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL;
411                 int tl = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE;
412                 int tr = rtl ? CL_CORNER_NONE  : CL_CORNER_ROUND;
413
414                 cl_rectangle_set_corners (r, tl, tr,
415                                           CL_CORNER_NONE, CL_CORNER_NONE);
416         }
417         else if (detail && !strcmp (detail, "spinbutton_down"))
418         {
419                 gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL;
420                 int bl = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE;
421                 int br = rtl ? CL_CORNER_NONE  : CL_CORNER_ROUND;
422
423                 cl_rectangle_set_corners (r, CL_CORNER_NONE, CL_CORNER_NONE,
424                                           bl, br);
425         }
426         else
427         {
428                 cl_rectangle_set_corners (r, CL_CORNER_ROUND, CL_CORNER_ROUND,
429                                           CL_CORNER_ROUND, CL_CORNER_ROUND);
430         };
431 }
432
433 void cl_rectangle_set_clip_rectangle (CLRectangle *r, GdkRectangle *area)
434 {
435         if (area == NULL)
436                 return;
437
438         if (r->fillgc)
439                 gdk_gc_set_clip_rectangle (r->fillgc, area);
440
441         if (r->bordergc)
442                 gdk_gc_set_clip_rectangle (r->bordergc, area);
443
444         if (r->topleft)
445                 gdk_gc_set_clip_rectangle (r->topleft, area);
446
447         if (r->bottomright)
448                 gdk_gc_set_clip_rectangle (r->bottomright, area);
449 }
450
451 void cl_rectangle_reset_clip_rectangle (CLRectangle *r)
452 {
453         if (r->fillgc)
454                 gdk_gc_set_clip_rectangle (r->fillgc, NULL);
455
456         if (r->bordergc)
457                 gdk_gc_set_clip_rectangle (r->bordergc, NULL);
458
459         if (r->topleft)
460                 gdk_gc_set_clip_rectangle (r->topleft, NULL);
461
462         if (r->bottomright)
463                 gdk_gc_set_clip_rectangle (r->bottomright, NULL);
464 }
465
466 void cl_rectangle_reset (CLRectangle *r, GtkStyle *style)
467 {
468         cl_rectangle_init (r,
469                            NULL, NULL,
470                            CL_CORNER_ROUND, CL_CORNER_ROUND,
471                            CL_CORNER_ROUND, CL_CORNER_ROUND);
472 }
473
474 static void cl_progressbar_points_transform (GdkPoint *points, int npoints,
475                                              int offset, gboolean is_horizontal)
476 {
477         int i;
478         for ( i=0; i<npoints; i++) {
479                 if ( is_horizontal )
480                         points[i].x += offset;
481                 else
482                         points[i].y += offset;
483         }
484 }
485
486 GdkPixmap* cl_progressbar_tile_new (GdkDrawable *drawable, GtkWidget *widget,
487                               GtkStyle *style, gint height, gint offset)
488 {
489         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
490         int width  = height;
491         int line   = 0;
492         int center = width/2;
493         int xdir   = 1;
494         int trans;
495
496         int stripe_width   = height/2;
497         int topright       = height + stripe_width;
498         int topright_div_2 = topright/2;
499
500         double shift;
501         GdkPoint points[4];
502
503         GtkProgressBarOrientation orientation = gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (widget));
504         gboolean is_horizontal = (orientation == GTK_PROGRESS_LEFT_TO_RIGHT || orientation == GTK_PROGRESS_RIGHT_TO_LEFT) ? 1 : 0;
505
506         GdkPixmap *tmp = gdk_pixmap_new (widget->window, width, height, -1);
507
508         GdkColor tmp_color;
509         shade (&clearlooks_style->spot2, &tmp_color, 0.90);
510
511         if (is_horizontal)
512                 draw_hgradient (tmp, style->black_gc, style, 0, 0, width, height,
513                             &clearlooks_style->spot2, &tmp_color );
514         else
515                 draw_vgradient (tmp, style->black_gc, style, 0, 0, width, height,
516                             &tmp_color, &clearlooks_style->spot2); /* TODO: swap for RTL */
517
518         if (orientation == GTK_PROGRESS_RIGHT_TO_LEFT ||
519             orientation == GTK_PROGRESS_BOTTOM_TO_TOP)
520         {
521                 offset = -offset;
522                 xdir = -1;
523         }
524
525         if (get_direction (widget) == GTK_TEXT_DIR_RTL)
526                 offset = -offset;
527
528         if (is_horizontal)
529         {
530                 points[0] = (GdkPoint){xdir*(topright - stripe_width - topright_div_2), 0};  /* topleft */
531                 points[1] = (GdkPoint){xdir*(topright - topright_div_2), 0};                 /* topright */
532                 points[2] = (GdkPoint){xdir*(stripe_width - topright_div_2), height};        /* bottomright */
533                 points[3] = (GdkPoint){xdir*(-topright_div_2), height};                      /* bottomleft */
534         }
535         else
536         {
537                 points[0] = (GdkPoint){height, xdir*(topright - stripe_width - topright_div_2)};  /* topleft */
538                 points[1] = (GdkPoint){height, xdir*(topright - topright_div_2)};                 /* topright */
539                 points[2] = (GdkPoint){0, xdir*(stripe_width - topright_div_2)};        /* bottomright */
540                 points[3] = (GdkPoint){0, xdir*(-topright_div_2)};                      /* bottomleft */
541         }
542
543
544         shift = (stripe_width*2)/(double)10;
545         cl_progressbar_points_transform (points, 4, (offset*shift), is_horizontal);
546
547         trans = (width/2)-1-(stripe_width*2);
548         cl_progressbar_points_transform (points, 4, trans, is_horizontal);
549         gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4);
550         cl_progressbar_points_transform (points, 4, -trans, is_horizontal);
551
552         trans = width/2-1;
553         cl_progressbar_points_transform (points, 4, trans, is_horizontal);
554         gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4);
555         cl_progressbar_points_transform (points, 4, -trans, is_horizontal);
556
557         trans = (width/2)-1+(stripe_width*2);
558         cl_progressbar_points_transform (points, 4, trans, is_horizontal);
559         gdk_draw_polygon (tmp, clearlooks_style->spot2_gc, TRUE, points, 4);
560
561         return tmp;
562 }
563
564 /* could be improved, I think. */
565 void cl_progressbar_fill (GdkDrawable *drawable, GtkWidget *widget,
566                           GtkStyle *style, GdkGC *gc,
567                           gint x, gint y,
568                           gint width, gint height,
569                           guint8 offset, GdkRectangle *area)
570 {
571         GtkProgressBarOrientation orientation = gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (widget));
572         gint size = (orientation == GTK_PROGRESS_LEFT_TO_RIGHT || orientation == GTK_PROGRESS_RIGHT_TO_LEFT) ? height : width;
573         GdkPixmap *tile = cl_progressbar_tile_new (widget->window, widget, style, size, offset);
574
575         gint nx = x,
576              ny = y,
577              nwidth = height,
578              nheight = width;
579
580         gdk_gc_set_clip_rectangle (gc, area);
581
582         switch (orientation)
583         {
584                 case GTK_PROGRESS_LEFT_TO_RIGHT:
585                 {
586                         while (nx <= x + width )
587                         {
588                                 if (nx + nwidth > x+width ) nwidth = (x+width) - nx;
589                                 gdk_draw_drawable (drawable, gc, tile, 0, 0, nx, y, nwidth, height);
590                                 if (height <= 1)
591                                     nx += 1;
592                                 else
593                                     nx += (height-1 + !(height % 2));
594                         }
595                         break;
596                 }
597                 case GTK_PROGRESS_RIGHT_TO_LEFT:
598                 {
599                         gint src_x = 0, dst_x;
600                         nx += width;
601                         while (nx >= x )
602                         {
603                                 dst_x = nx - height;
604                                 if (dst_x < x )
605                                 {
606                                         src_x = x - dst_x;
607                                         dst_x = x;
608                                 }
609                                 gdk_draw_drawable (drawable, gc, tile, src_x, 0, dst_x, y, nwidth, height);
610                                 if (height <= 1)
611                                     nx -= 1;
612                                 else
613                                     nx -= (height-1 + !(height % 2));
614                         }
615                         break;
616                 }
617                 case GTK_PROGRESS_TOP_TO_BOTTOM:
618                 {
619                         while (ny <= y + height )
620                         {
621                                 if (ny + nheight > y+height ) nheight = (y+height) - ny;
622                                 gdk_draw_drawable (drawable, gc, tile, 0, 0, x, ny, width, nheight);
623                                 if (width <= 1)
624                                     ny += 1;
625                                 else
626                                     ny += (width-1 + !(width % 2));
627                         }
628                         break;
629                 }
630                 case GTK_PROGRESS_BOTTOM_TO_TOP:
631                 {
632                         gint src_y = 0, dst_y;
633                         ny += height;
634                         while (ny >= y )
635                         {
636                                 dst_y = ny - width;
637                                 if (dst_y < y )
638                                 {
639                                         src_y = y - dst_y;
640                                         dst_y = y;
641                                 }
642                                 gdk_draw_drawable (drawable, gc, tile, 0, src_y, x, dst_y, width, width);
643                                 if (width <= 1)
644                                     ny -= 1;
645                                 else
646                                     ny -= (width-1 + !(width % 2));
647                         }
648                         break;
649                 }
650         }
651
652         gdk_gc_set_clip_rectangle (gc, NULL);
653
654         g_object_unref (tile);
655 }
656
657 GdkColor cl_gc_set_fg_color_shade (GdkGC *gc, GdkColormap *colormap,
658                                    GdkColor *from, gfloat s)
659 {
660         GdkColor tmp_color;
661         GdkGCValues values;
662
663         shade (from, &tmp_color, s);
664         gdk_gc_get_values (gc, &values);
665         gdk_rgb_find_color (colormap, &tmp_color);
666         gdk_gc_set_foreground (gc, &tmp_color);
667
668         return values.foreground;
669 }
670
671 /* #warning MOVE THIS TO SUPPORT.C/H SO THE DRAW_CORNER FUNCTION CAN USE IT. OR, MAKE DRAW_CORNER USE IT SOME OTHER WAY. */
672
673 static void cl_get_window_style_state (GtkWidget *widget, GtkStyle **style, GtkStateType *state_type)
674 {
675         GtkStyle *windowstyle = NULL;
676         GtkWidget *tmpwidget = widget;
677         GtkStateType windowstate;
678
679         if (widget && GTK_IS_ENTRY (widget))
680                 tmpwidget = tmpwidget->parent;
681
682         while (tmpwidget && GTK_WIDGET_NO_WINDOW (tmpwidget) && !GTK_IS_NOTEBOOK(tmpwidget))
683         {
684                 tmpwidget = tmpwidget->parent;
685         }
686
687         *style     = tmpwidget->style;
688         *state_type = GTK_WIDGET_STATE(tmpwidget);
689 }
690
691 static GdkGC *cl_get_window_bg_gc (GtkWidget *widget)
692 {
693         GtkStyle *style;
694         GtkStateType state_type;
695
696         cl_get_window_style_state (widget, &style, &state_type);
697
698         return style->bg_gc[state_type];
699 }
700
701 /******************************************************************************
702  *   DRAW THE MIGHTY WIDGETS!                                                 *
703  ******************************************************************************/
704
705 void cl_draw_inset (GtkStyle *style, GdkWindow *window, GtkWidget *widget,
706                     GdkRectangle *area,
707                     gint x, gint y, gint width, gint height,
708                     int tl, int tr, int bl, int br )
709 {
710         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style);
711         ClearlooksStyle *clwindowstyle; /* style of the window this widget is on */
712         GtkStateType     windowstate;
713         CLRectangle      r;
714
715         cl_rectangle_init (&r, NULL, style->black_gc,
716                            tl, tr, bl, br);
717
718         r.gradient_type = CL_GRADIENT_VERTICAL;
719
720         cl_get_window_style_state(widget, (GtkStyle**)&clwindowstyle, &windowstate);
721
722         g_assert (clwindowstyle != NULL);
723
724         if (GTK_WIDGET_HAS_DEFAULT (widget))
725         {
726                 r.bordergc = style->mid_gc[GTK_STATE_NORMAL];
727         }
728         else
729         {
730                 cl_rectangle_set_gradient (&r.border_gradient,
731                                            &clwindowstyle->inset_dark[windowstate],
732                                            &clwindowstyle->inset_light[windowstate]);
733         }
734         cl_rectangle_set_clip_rectangle (&r, area);
735         cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
736         cl_rectangle_reset_clip_rectangle (&r);
737 }
738
739 /* Draw a normal (toggle)button. Not spinbuttons.*/
740 void cl_draw_button(GtkStyle *style, GdkWindow *window,
741                     GtkStateType state_type, GtkShadowType shadow_type,
742                     GdkRectangle *area,
743                     GtkWidget *widget, const gchar *detail,
744                     gint x, gint y, gint width, gint height)
745 {
746         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style);
747         int my_state_type = (state_type == GTK_STATE_ACTIVE) ? 2 : 0;
748         GdkGC *bg_gc = NULL;
749         gboolean is_active = FALSE;
750         CLRectangle r;
751
752         /* Get the background color of the window we're on */
753         bg_gc = cl_get_window_bg_gc(widget);
754
755         cl_rectangle_set_button (&r, style, state_type,
756                                  GTK_WIDGET_HAS_DEFAULT (widget),
757                                  GTK_WIDGET_HAS_FOCUS (widget),
758                                  CL_CORNER_ROUND, CL_CORNER_ROUND,
759                                  CL_CORNER_ROUND, CL_CORNER_ROUND);
760
761         if (state_type == GTK_STATE_ACTIVE)
762                 is_active = TRUE;
763
764         if (GTK_IS_TOGGLE_BUTTON(widget) &&
765             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)) &&
766             state_type == GTK_STATE_PRELIGHT)
767         {
768                 cl_rectangle_set_gradient (&r.fill_gradient, &clearlooks_style->shade[1], &clearlooks_style->shade[1]);
769                 r.topleft     = clearlooks_style->shade_gc[3];
770                 r.bottomright = clearlooks_style->shade_gc[1];
771
772                 is_active = TRUE;
773         }
774
775         if (!is_active)
776                 r.fillgc = NULL;
777
778         if (!GTK_IS_NOTEBOOK (widget->parent))
779         {
780                 gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1);
781
782                 /* Draw "sunken" look when border thickness is more than 2 pixels. */
783                 if (style->xthickness > 2 && style->ythickness > 2)
784                 cl_draw_inset (style, window, widget, area, x, y, width, height,
785                                CL_CORNER_ROUND, CL_CORNER_ROUND,
786                                CL_CORNER_ROUND, CL_CORNER_ROUND);
787         }
788
789         /* Draw "sunken" look when border thickness is more than 2 pixels.*/
790         if (style->xthickness > 2 && style->ythickness > 2)
791         {
792                 x++;
793                 y++;
794                 height-=2;
795                 width-=2;
796         }
797
798         /* Don't draw the normal gradient for normal buttons. */
799
800         cl_rectangle_set_clip_rectangle (&r, area);
801         cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
802
803
804         if (!is_active)
805         {
806                 int tmp_height = (float)height*0.25;
807
808                 gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
809
810                 draw_hgradient (window, style->bg_gc[state_type], style,
811                                 x+2,y+2,width-4,tmp_height,
812                                 &clearlooks_style->button_g1[state_type],
813                                     &clearlooks_style->button_g2[state_type]);
814
815                 draw_hgradient (window, style->bg_gc[state_type], style,
816                                 x+2, y+2+tmp_height, width-4, height-3-tmp_height*2,
817                                 &clearlooks_style->button_g2[state_type],
818                                     &clearlooks_style->button_g3[state_type]);
819
820                 draw_hgradient (window, style->bg_gc[state_type], style,
821                                 x+2,y+height-tmp_height-1,width-4,tmp_height,
822                                 &clearlooks_style->button_g3[state_type],
823                                     &clearlooks_style->button_g4[state_type]);
824
825                 gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
826         }
827
828         cl_draw_shadow    (window, widget, style, x, y, width, height, &r);
829         cl_rectangle_reset_clip_rectangle (&r);
830 }
831
832 /* Draw spinbuttons. */
833 void cl_draw_spinbutton(GtkStyle *style, GdkWindow *window,
834                         GtkStateType state_type, GtkShadowType shadow_type,
835                         GdkRectangle *area,
836                         GtkWidget *widget, const gchar *detail,
837                         gint x, gint y, gint width, gint height)
838 {
839         CLRectangle r;
840         GdkRectangle new_area;
841
842         int tl = CL_CORNER_NONE, tr = CL_CORNER_NONE,
843             bl = CL_CORNER_NONE, br = CL_CORNER_NONE;
844
845         if (area == NULL)
846         {
847                 new_area.x = x;
848                 new_area.y = y;
849                 new_area.width = width;
850                 new_area.height = height;
851                 area = &new_area;
852         }
853
854         if (!strcmp (detail, "spinbutton")) /* draws the 'back' of the spinbutton */
855         {
856                 GdkGC *bg_gc = cl_get_window_bg_gc(widget);
857
858                 gdk_gc_set_clip_rectangle (bg_gc, area);
859                 gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1);
860                 gdk_gc_set_clip_rectangle (bg_gc, NULL);
861
862                 if (style->xthickness > 2 && style->ythickness > 2)
863                         cl_draw_inset (style, window, widget, area, x, y, width, height,
864                                        CL_CORNER_NONE, CL_CORNER_ROUND,
865                                        CL_CORNER_NONE, CL_CORNER_ROUND);
866
867                 return;
868         }
869
870         if (!strcmp (detail, "spinbutton_up"))
871         {
872                 tr = CL_CORNER_ROUND;
873
874                 (style->xthickness > 2 && style->ythickness > 2) ? y++ : height++;
875         }
876
877         if (!strcmp (detail, "spinbutton_down"))
878         {
879                 br = CL_CORNER_ROUND;
880
881                 if (style->xthickness > 2 && style->ythickness > 2)
882                         height--;
883         }
884
885         cl_rectangle_set_button (&r, style, state_type,
886                                  GTK_WIDGET_HAS_DEFAULT  (widget),
887                                  GTK_WIDGET_HAS_FOCUS (widget),
888                                  tl, tr,
889                                  bl, br);
890         width--;
891
892         cl_rectangle_set_clip_rectangle (&r, area);
893         cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
894         cl_draw_shadow    (window, widget, style, x, y, width, height, &r);
895         cl_rectangle_reset_clip_rectangle (&r);
896 }
897
898 void cl_draw_combobox_entry (GtkStyle *style, GdkWindow *window,
899                              GtkStateType state_type, GtkShadowType shadow_type,
900                              GdkRectangle *area,
901                              GtkWidget *widget, const gchar *detail,
902                              gint x, gint y, gint width, gint height)
903 {
904         CLRectangle r;
905
906         gboolean rtl = get_direction (widget->parent) == GTK_TEXT_DIR_RTL;
907         gboolean has_focus = GTK_WIDGET_HAS_FOCUS (widget);
908
909         int cl = rtl ? CL_CORNER_NONE  : CL_CORNER_ROUND,
910                 cr = rtl ? CL_CORNER_ROUND : CL_CORNER_NONE;
911
912         GdkGC *bg_gc = cl_get_window_bg_gc(widget);
913
914         if (rtl)
915         {
916                 if (!has_focus)
917                 {
918                         x -= 1;
919                         width +=1;
920                 }
921         }
922         else
923         {
924                 width += 2;
925                 if (has_focus) width--; /* this gives us a 2px focus line at the right side. */
926         }
927
928         cl_rectangle_set_entry (&r, style, state_type,
929                                                    cl, cr, cl, cr,
930                                                    has_focus);
931
932         gdk_gc_set_clip_rectangle (bg_gc, area);
933         gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1);
934         gdk_gc_set_clip_rectangle (bg_gc, NULL);
935
936         /* Draw "sunken" look when border thickness is more than 2 pixels. */
937         if (style->xthickness > 2 && style->ythickness > 2)
938         {
939                 cl_draw_inset (style, window, widget, area, x, y, width, height,
940                                cl, cr, cl, cr);
941
942                 y++;
943                 x++;
944                 width-=2;
945                 height-=2;
946         }
947
948         cl_rectangle_set_clip_rectangle (&r, area);
949
950         cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
951         cl_draw_shadow (window, widget, style, x, y, width, height, &r);
952
953         cl_rectangle_reset_clip_rectangle (&r);
954 }
955
956 void cl_draw_combobox_button (GtkStyle *style, GdkWindow *window,
957                     GtkStateType state_type, GtkShadowType shadow_type,
958                     GdkRectangle *area,
959                     GtkWidget *widget, const gchar *detail,
960                     gint x, gint y, gint width, gint height)
961 {
962         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style);
963         gboolean is_active  = FALSE;
964         gboolean draw_inset = FALSE;
965         CLRectangle r;
966
967         cl_rectangle_set_button (&r, style, state_type,
968                                  GTK_WIDGET_HAS_DEFAULT  (widget),
969                                  GTK_WIDGET_HAS_FOCUS (widget),
970                                  CL_CORNER_NONE, CL_CORNER_ROUND,
971                                  CL_CORNER_NONE, CL_CORNER_ROUND);
972
973         if (state_type == GTK_STATE_ACTIVE)
974                 is_active = TRUE;
975         else
976                 r.fillgc = NULL;
977
978         /* Seriously, why can't non-gtk-apps at least try to be decent citizens?
979            Take this fscking OpenOffice.org 1.9 for example. The morons responsible
980            for this utter piece of crap give the clip size wrong values! :'(  */
981
982         if (area)
983         {
984                 area->x = x;
985                 area->y = y;
986                 area->width = width;
987                 area->height = height;
988         }
989
990         x--;
991         width++;
992
993         /* Draw "sunken" look when border thickness is more than 2 pixels. */
994         if (GTK_IS_COMBO(widget->parent))
995                 draw_inset = (widget->parent->style->xthickness > 2 &&
996                           widget->parent->style->ythickness > 2);
997         else
998                 draw_inset = (style->xthickness > 2 && style->ythickness > 2);
999
1000         if (draw_inset)
1001         {
1002                 cl_draw_inset (style, window, widget, area, x, y, width, height,
1003                                CL_CORNER_NONE, CL_CORNER_ROUND,
1004                                CL_CORNER_NONE, CL_CORNER_ROUND);
1005
1006                 x++;
1007                 y++;
1008                 height-=2;
1009                 width-=2;
1010         }
1011         else
1012         {
1013                 x++;
1014                 width--;
1015         }
1016
1017         if (area)
1018                 cl_rectangle_set_clip_rectangle (&r, area);
1019
1020         cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
1021
1022         if (!is_active)
1023         {
1024                 int tmp_height = (float)height*0.25;
1025
1026                 gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
1027
1028                 draw_hgradient (window, style->bg_gc[state_type], style,
1029                                 x+2,y+2,width-4,tmp_height,
1030                                 &clearlooks_style->button_g1[state_type],
1031                                     &clearlooks_style->button_g2[state_type]);
1032
1033                 draw_hgradient (window, style->bg_gc[state_type], style,
1034                                 x+2, y+2+tmp_height, width-4, height-3-tmp_height*2,
1035                                 &clearlooks_style->button_g2[state_type],
1036                                     &clearlooks_style->button_g3[state_type]);
1037
1038                 draw_hgradient (window, style->bg_gc[state_type], style,
1039                                 x+2,y+height-tmp_height-1,width-4,tmp_height,
1040                                 &clearlooks_style->button_g3[state_type],
1041                                     &clearlooks_style->button_g4[state_type]);
1042
1043                 gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
1044         }
1045
1046         cl_draw_shadow    (window, widget, style, x, y, width, height, &r);
1047
1048         if (area)
1049                 cl_rectangle_reset_clip_rectangle (&r);
1050 }
1051
1052 /* Draw text Entry */
1053 void cl_draw_entry (GtkStyle *style, GdkWindow *window,
1054                         GtkStateType state_type, GtkShadowType shadow_type,
1055                         GdkRectangle *area,
1056                         GtkWidget *widget, const gchar *detail,
1057                         gint x, gint y, gint width, gint height)
1058 {
1059         CLRectangle r;
1060         gboolean has_focus = GTK_WIDGET_HAS_FOCUS(widget);
1061         GdkGC *bg_gc = cl_get_window_bg_gc(widget);
1062
1063         gdk_draw_rectangle (window, bg_gc, FALSE, x, y, width-1, height-1);
1064
1065         gtk_style_apply_default_background (style, window, TRUE, state_type,
1066                                                                                 area, x+1, y+1, width-2, height-2);
1067
1068
1069         cl_rectangle_set_entry (&r, style, state_type,
1070                                                         CL_CORNER_ROUND, CL_CORNER_ROUND,
1071                                                         CL_CORNER_ROUND, CL_CORNER_ROUND,
1072                                                         has_focus);
1073
1074         /* Draw "sunken" look when border thickness is more than 2 pixels. */
1075         if (style->xthickness > 2 && style->ythickness > 2)
1076         {
1077                 cl_draw_inset (style, window, widget, area, x, y, width, height,
1078                                CL_CORNER_ROUND, CL_CORNER_ROUND,
1079                                CL_CORNER_ROUND, CL_CORNER_ROUND);
1080
1081                 x++;
1082                 y++;
1083                 width-=2;
1084                 height-=2;
1085         }
1086
1087         cl_rectangle_set_clip_rectangle (&r, area);
1088         cl_draw_rectangle (window, widget, style, x, y, width, height, &r);
1089         cl_draw_shadow (window, widget, style, x, y, width, height, &r);
1090         cl_rectangle_reset_clip_rectangle (&r);
1091 }
1092
1093 void cl_draw_optionmenu(GtkStyle *style, GdkWindow *window,
1094                         GtkStateType state_type, GtkShadowType shadow_type,
1095                         GdkRectangle *area, GtkWidget *widget,
1096                         const gchar *detail,
1097                         gint x, gint y, gint width, gint height)
1098 {
1099         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE(style);
1100         GtkRequisition indicator_size;
1101         GtkBorder indicator_spacing;
1102         int line_pos;
1103
1104         option_menu_get_props (widget, &indicator_size, &indicator_spacing);
1105
1106         if (get_direction (widget) == GTK_TEXT_DIR_RTL)
1107                 line_pos = x + (indicator_size.width + indicator_spacing.left + indicator_spacing.right) + style->xthickness;
1108         else
1109                 line_pos = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
1110
1111         cl_draw_button (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
1112
1113         gdk_draw_line (window, clearlooks_style->shade_gc[3],
1114                                    line_pos, y + style->ythickness - 1, line_pos,
1115                                    y + height - style->ythickness);
1116
1117         gdk_draw_line (window, style->light_gc[state_type],
1118                                    line_pos+1, y + style->ythickness - 1, line_pos+1,
1119                                    y + height - style->ythickness);
1120 }
1121
1122
1123 void cl_draw_menuitem_button (GdkDrawable *window, GtkWidget *widget, GtkStyle *style,
1124                               GdkRectangle *area, GtkStateType state_type,
1125                               int x, int y, int width, int height, CLRectangle *r)
1126 {
1127         ClearlooksStyle *clearlooks_style = (ClearlooksStyle*)style;
1128         gboolean menubar  = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE;
1129         int corner        = CL_CORNER_NARROW;
1130         GdkColor lower_color;
1131
1132         shade (&style->base[GTK_STATE_SELECTED], &lower_color, 0.85);
1133
1134         if (menubar)
1135         {
1136                 height++;
1137                 corner = CL_CORNER_NONE;
1138                 r->bordergc    = clearlooks_style->border_gc[CL_BORDER_UPPER];
1139         }
1140         else
1141         {
1142                 r->bordergc    = clearlooks_style->spot3_gc;
1143         }
1144
1145         cl_rectangle_set_corners (r, corner, corner, corner, corner);
1146
1147         cl_rectangle_set_gradient (&r->fill_gradient,
1148                                    &style->base[GTK_STATE_SELECTED], &lower_color);
1149
1150         r->gradient_type = CL_GRADIENT_VERTICAL;
1151
1152         r->fillgc  = clearlooks_style->spot2_gc;
1153         r->topleft = clearlooks_style->spot1_gc;
1154
1155         cl_rectangle_set_clip_rectangle (r, area);
1156         cl_draw_rectangle (window, widget, style, x, y, width, height, r);
1157         cl_draw_shadow (window, widget, style, x, y, width, height, r);
1158         cl_rectangle_reset_clip_rectangle (r);
1159 }
1160
1161 void cl_draw_menuitem_flat (GdkDrawable *window, GtkWidget *widget, GtkStyle *style,
1162                               GdkRectangle *area, GtkStateType state_type,
1163                               int x, int y, int width, int height, CLRectangle *r)
1164 {
1165         ClearlooksStyle *clearlooks_style = (ClearlooksStyle*)style;
1166         gboolean menubar  = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE;
1167         GdkColor tmp;
1168
1169         cl_rectangle_set_corners (r, CL_CORNER_NARROW, CL_CORNER_NARROW,
1170                                      CL_CORNER_NARROW, CL_CORNER_NARROW);
1171
1172         tmp = cl_gc_set_fg_color_shade (style->black_gc, style->colormap,
1173                                         &style->base[GTK_STATE_PRELIGHT], 0.8);
1174
1175         r->bordergc = style->black_gc;
1176         r->fillgc = style->base_gc[GTK_STATE_PRELIGHT];
1177
1178         if (menubar) height++;
1179
1180         cl_rectangle_set_clip_rectangle (r, area);
1181         cl_draw_rectangle (window, widget, style, x, y, width, height, r);
1182         cl_rectangle_reset_clip_rectangle (r);
1183
1184         gdk_gc_set_foreground (style->black_gc, &tmp);
1185 }
1186
1187 void cl_draw_menuitem_gradient (GdkDrawable *window, GtkWidget *widget, GtkStyle *style,
1188                                 GdkRectangle *area, GtkStateType state_type,
1189                                 int x, int y, int width, int height, CLRectangle *r)
1190 {
1191         ClearlooksStyle *clearlooks_style = (ClearlooksStyle*)style;
1192         gboolean menubar  = (widget->parent && GTK_IS_MENU_BAR(widget->parent)) ? TRUE : FALSE;
1193         GdkColor tmp;
1194         GdkColor lower_color;
1195
1196         shade (&style->base[GTK_STATE_SELECTED], &lower_color, 0.8);
1197
1198         cl_rectangle_set_corners (r, CL_CORNER_NARROW, CL_CORNER_NARROW,
1199                                      CL_CORNER_NARROW, CL_CORNER_NARROW);
1200
1201         cl_rectangle_set_gradient (&r->fill_gradient,
1202                                    &style->base[GTK_STATE_SELECTED], &lower_color);
1203
1204         r->gradient_type = CL_GRADIENT_VERTICAL;
1205
1206         tmp = cl_gc_set_fg_color_shade (style->black_gc, style->colormap,
1207                                         &style->base[GTK_STATE_PRELIGHT], 0.8);
1208
1209         r->bordergc = style->black_gc;
1210         r->fillgc = style->base_gc[GTK_STATE_PRELIGHT];
1211
1212         if (menubar) height++;
1213
1214         cl_rectangle_set_clip_rectangle (r, area);
1215         cl_draw_rectangle (window, widget, style, x, y, width, height, r);
1216         cl_rectangle_reset_clip_rectangle (r);
1217
1218         gdk_gc_set_foreground (style->black_gc, &tmp);
1219 }
1220
1221 void cl_draw_treeview_header (GtkStyle *style, GdkWindow *window,
1222                               GtkStateType state_type, GtkShadowType shadow_type,
1223                               GdkRectangle *area,
1224                               GtkWidget *widget, const gchar *detail,
1225                               gint x, gint y, gint width, gint height)
1226 {
1227         ClearlooksStyle *clearlooks_style = CLEARLOOKS_STYLE (style);
1228         gint columns = 0, column_index = -1, fill_width = width;
1229         gboolean is_etree = strcmp("ETree", G_OBJECT_TYPE_NAME(widget->parent)) == 0;
1230         gboolean resizable = TRUE;
1231
1232         GdkGC *bottom = clearlooks_style->shade_gc[5];
1233
1234         if ( width < 2 || height < 2 )
1235                 return;
1236
1237         if (GTK_IS_TREE_VIEW (widget->parent))
1238         {
1239                 gtk_treeview_get_header_index (GTK_TREE_VIEW(widget->parent),
1240                                            widget, &column_index, &columns,
1241                                            &resizable);
1242         }
1243         else if (GTK_IS_CLIST (widget->parent))
1244         {
1245                 gtk_clist_get_header_index (GTK_CLIST(widget->parent),
1246                                             widget, &column_index, &columns);
1247         }
1248
1249         if (area)
1250         {
1251                 gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], area);
1252                 gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[4], area);
1253                 gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
1254                 gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[5], area);
1255         }
1256
1257         if (state_type != GTK_STATE_NORMAL)
1258                 fill_width-=2;
1259
1260         gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE, x, y, fill_width, height-(height/3)+1);
1261
1262         draw_hgradient (window, style->bg_gc[state_type], style,
1263                         x, 1+y+height-(height/3), fill_width, height/3,
1264                         &style->bg[state_type], &clearlooks_style->inset_dark[state_type]);
1265
1266         if (resizable || (column_index != columns-1))
1267         {
1268                 gdk_draw_line (window, clearlooks_style->shade_gc[4], x+width-2, y+4, x+width-2, y+height-5);
1269                 gdk_draw_line (window, clearlooks_style->shade_gc[0], x+width-1, y+4, x+width-1, y+height-5);
1270         }
1271
1272         /* left light line */
1273         if (column_index == 0)
1274                 gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y+1, x, y+height-2);
1275
1276         /* top light line */
1277         gdk_draw_line (window, clearlooks_style->shade_gc[0], x, y, x+width-1, y);
1278
1279         /* bottom dark line */
1280         if (state_type == GTK_STATE_INSENSITIVE)
1281                 bottom = clearlooks_style->shade_gc[3];
1282
1283
1284         gdk_draw_line (window, bottom, x, y+height-1, x+width-1, y+height-1);
1285
1286         if (area)
1287         {
1288                 gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[0], NULL);
1289                 gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[4], NULL);
1290                 gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
1291                 gdk_gc_set_clip_rectangle (clearlooks_style->shade_gc[5], NULL);
1292         }
1293 }