~ubuntu-branches/ubuntu/lucid/gnome-themes-extras/lucid

« back to all changes in this revision

Viewing changes to Smooth/utils/draw_arrows.c

  • Committer: Bazaar Package Importer
  • Author(s): Josselin Mouette
  • Date: 2004-06-23 20:28:52 UTC
  • Revision ID: james.westby@ubuntu.com-20040623202852-j7hu6zargn5hnban
Tags: upstream-0.7.debian.1
ImportĀ upstreamĀ versionĀ 0.7.debian.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "misc_functions.h"
 
2
 
 
3
/* This function is based on XFCE's & CleanIce draw arrow routines, both which  were based on ThinIce's */
 
4
static void
 
5
do_draw_default_arrow(GdkWindow * window,
 
6
                        GdkRectangle * area,
 
7
                        GtkArrowType arrow_type,
 
8
                        GdkGC * gc,
 
9
                        gint x,
 
10
                        gint y,
 
11
                        gint width,
 
12
                        gint height)
 
13
{
 
14
  gint steps, extra;
 
15
  gint start, increment;
 
16
  gint i;
 
17
 
 
18
  if (area)
 
19
    gdk_gc_set_clip_rectangle (gc, area);
 
20
 
 
21
  if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
 
22
  {
 
23
    width = width + width % 2 - 1;      /* Force odd */
 
24
 
 
25
    steps = 1 + width / 2;
 
26
 
 
27
    extra = height - steps;
 
28
 
 
29
    if (arrow_type == GTK_ARROW_DOWN)
 
30
    {
 
31
      start = y;
 
32
      increment = 1;
 
33
    }
 
34
    else
 
35
    {
 
36
      start = y + height - 1;
 
37
      increment = -1;
 
38
    }
 
39
 
 
40
    for (i = 0; i < extra; i++)
 
41
    {
 
42
      gdk_draw_line (window, gc, x, start + i * increment, x + width - 1, start + i * increment);
 
43
    }
 
44
    for (; i < height; i++)
 
45
    {
 
46
      gdk_draw_line (window, gc, x + (i - extra), start + i * increment, x + width - (i - extra) - 1, start + i * increment);
 
47
    }
 
48
  }
 
49
  else
 
50
  {
 
51
    height = height + height % 2 - 1;   /* Force odd */
 
52
 
 
53
    steps = 1 + height / 2;
 
54
 
 
55
    extra = width - steps;
 
56
 
 
57
    if (arrow_type == GTK_ARROW_RIGHT)
 
58
    {
 
59
      start = x;
 
60
      increment = 1;
 
61
    }
 
62
    else
 
63
    {
 
64
      start = x + width - 1;
 
65
      increment = -1;
 
66
    }
 
67
 
 
68
    for (i = 0; i < extra; i++)
 
69
    {
 
70
      gdk_draw_line (window, gc, start + i * increment, y, start + i * increment, y + height - 1);
 
71
    }
 
72
    for (; i < width; i++)
 
73
    {
 
74
      gdk_draw_line (window, gc, start + i * increment, y + (i - extra), start + i * increment, y + height - (i - extra) - 1);
 
75
    }
 
76
  }
 
77
  if (area)
 
78
    gdk_gc_set_clip_rectangle (gc, NULL);
 
79
}
 
80
 
 
81
/* This function is based on EnGradient/IceGradient's draw arrow routines */
 
82
static void
 
83
do_draw_icegradient_arrow(GdkWindow * window,
 
84
                        GdkRectangle * area,
 
85
                        GtkArrowType arrow_type,
 
86
                        GdkGC * gc,
 
87
                        gboolean fill,
 
88
                        gint x,
 
89
                        gint y,
 
90
                        gint width,
 
91
                        gint height)
 
92
{
 
93
  gint half_width, half_height,w;
 
94
  GdkPoint points[4];
 
95
 
 
96
  width &= 0xfffe;
 
97
  height &= 0xfffe;
 
98
  
 
99
  w = MIN(width, height);
 
100
  x += (width-w)/2;
 
101
  y += (height-w)/2;
 
102
  width = height = w;
 
103
  
 
104
  half_width = width / 2;
 
105
  half_height = height / 2;
 
106
 
 
107
  switch (arrow_type) {
 
108
    case GTK_ARROW_UP:
 
109
      points[0].x = x + half_width - 1;
 
110
      points[0].y = y;
 
111
      points[1].x = x;
 
112
      points[1].y = y + height - 1;
 
113
      points[2].x = x + width  - 1;
 
114
      points[2].y = y + height - 1;
 
115
      points[3].x = x + half_width;
 
116
      points[3].y = y;
 
117
      break;
 
118
 
 
119
    case GTK_ARROW_DOWN:
 
120
      points[0].x = x + half_width ;
 
121
      points[0].y = y + height     - 1;
 
122
      points[1].x = x + width - 1;
 
123
      points[1].y = y;
 
124
      points[2].x = x;
 
125
      points[2].y = y;
 
126
      points[3].x = x + half_width - 1;
 
127
      points[3].y = y + height     - 1;
 
128
      break;
 
129
 
 
130
    case GTK_ARROW_LEFT:
 
131
      points[0].x = x;
 
132
      points[0].y = y + half_height;
 
133
      points[1].x = x + width - 1;
 
134
      points[1].y = y + height - 1;
 
135
      points[2].x = x + width - 1;
 
136
      points[2].y = y;
 
137
      points[3].x = x;
 
138
      points[3].y = y + half_height - 1;
 
139
      break;
 
140
 
 
141
    case GTK_ARROW_RIGHT:
 
142
      points[0].x = x + width - 1;
 
143
      points[0].y = y + half_height - 1;
 
144
      points[1].x = x;
 
145
      points[1].y = y;
 
146
      points[2].x = x;
 
147
      points[2].y = y + height - 1;
 
148
      points[3].x = x + width - 1;
 
149
      points[3].y = y + half_height;
 
150
      break;
 
151
 
 
152
    default:
 
153
      return;
 
154
  }    
 
155
 
 
156
  if (gc) {
 
157
    if (area)
 
158
      gdk_gc_set_clip_rectangle (gc, area);
 
159
    
 
160
    gdk_draw_polygon (window, gc, fill, points, 4);
 
161
    
 
162
    if (area)
 
163
      gdk_gc_set_clip_rectangle (gc, NULL);
 
164
  }
 
165
}
 
166
 
 
167
/* This function is taken straight from the Wonderland 
 
168
 * theme engine, with no modifications whatsoever.(yet...)
 
169
 */
 
170
static void
 
171
arrow_draw_hline (GdkWindow     *window,
 
172
                  GdkGC         *gc,
 
173
                  int            x1,
 
174
                  int            x2,
 
175
                  int            y,
 
176
                  gboolean       last)
 
177
{
 
178
  if (x2 - x1 < 7 && !last) /* 7 to get garretts pixels, otherwise 6 */
 
179
    gdk_draw_line (window, gc, x1, y, x2, y);
 
180
  else if (last)
 
181
    {
 
182
      if (x2 - x1 <= 7)
 
183
        {
 
184
          gdk_draw_line (window, gc, x1+1, y, x1+1, y);
 
185
          gdk_draw_line (window, gc, x2-1, y, x2-1, y); 
 
186
        }
 
187
      else
 
188
        {
 
189
          gdk_draw_line (window, gc, x1+2, y, x1+2, y);
 
190
          gdk_draw_line (window, gc, x2-2, y, x2-2, y);
 
191
        }
 
192
    }
 
193
  else
 
194
    {
 
195
      gdk_draw_line (window, gc, x1, y, x1+2, y);
 
196
      gdk_draw_line (window, gc, x2-2, y, x2, y); 
 
197
    }
 
198
}
 
199
 
 
200
/* This function is taken straight from the Wonderland 
 
201
 * theme engine, with no modifications whatsoever.(yet...)
 
202
 */
 
203
static void
 
204
arrow_draw_vline (GdkWindow     *window,
 
205
                  GdkGC         *gc,
 
206
                  int            y1,
 
207
                  int            y2,
 
208
                  int            x,
 
209
                  gboolean       last)
 
210
{
 
211
  if (y2 - y1 < 7 && !last) /* 7 to get garretts pixels */
 
212
    gdk_draw_line (window, gc, x, y1, x, y2);
 
213
  else if (last)
 
214
    {
 
215
      gdk_draw_line (window, gc, x, y1+2, x, y1+2);
 
216
      gdk_draw_line (window, gc, x, y2-2, x, y2-2); 
 
217
    }
 
218
  else
 
219
    {
 
220
      gdk_draw_line (window, gc, x, y1, x, y1+2);
 
221
      gdk_draw_line (window, gc, x, y2-2, x, y2); 
 
222
    }
 
223
}
 
224
 
 
225
/* This function is based on the Wonderland theme engine, 
 
226
 * it is essentially calculate_arrow_geometry and draw_arrow,
 
227
 * concatted into one composite whole...
 
228
 */
 
229
static void
 
230
do_draw_wonderland_arrow(GdkWindow * window,
 
231
                        GdkRectangle * area,
 
232
                        GtkArrowType arrow_type,
 
233
                        GdkGC * gc,
 
234
                        gint x,
 
235
                        gint y,
 
236
                        gint width,
 
237
                        gint height)
 
238
{
 
239
  gint i, j;
 
240
  gint w = width;
 
241
  gint h = height;
 
242
  
 
243
  switch (arrow_type)
 
244
    {
 
245
    case GTK_ARROW_UP:
 
246
    case GTK_ARROW_DOWN:
 
247
      w += (w % 2) - 1;
 
248
      h = (w / 2 + 1) + 1;
 
249
 
 
250
      if (h > height)
 
251
        {
 
252
          h = height;
 
253
          w = 2 * (h - 1) - 1;
 
254
        }
 
255
      
 
256
      if (arrow_type == GTK_ARROW_DOWN)
 
257
        {
 
258
          if (height % 2 == 1 || h % 2 == 0)
 
259
            height += 1;
 
260
        }
 
261
      else
 
262
        {
 
263
          if (height % 2 == 0 || h % 2 == 0)
 
264
            height -= 1;
 
265
        }
 
266
      break;
 
267
 
 
268
    case GTK_ARROW_RIGHT:
 
269
    case GTK_ARROW_LEFT:
 
270
      h += (h % 2) - 1;
 
271
      w = (h / 2 + 1) + 1; 
 
272
      
 
273
      if (w > width)
 
274
        {
 
275
          w = width;
 
276
          h = 2 * (w - 1) - 1;
 
277
        }
 
278
      
 
279
      if (arrow_type == GTK_ARROW_RIGHT)
 
280
        {
 
281
          if (width % 2 == 1 || w % 2 == 0)
 
282
            width += 1;
 
283
        }
 
284
      else
 
285
        {
 
286
          if (width % 2 == 0 || w % 2 == 0)
 
287
            width -= 1;
 
288
        }
 
289
      break;
 
290
      
 
291
    default:
 
292
      /* should not be reached */
 
293
      return;
 
294
    }
 
295
 
 
296
  x += (width - w) / 2;
 
297
  y += (height - h) / 2;
 
298
  height = h;
 
299
  width = w;
 
300
  
 
301
  if (gc) {
 
302
    if (area)
 
303
      gdk_gc_set_clip_rectangle (gc, area);
 
304
    
 
305
    if (arrow_type == GTK_ARROW_DOWN)
 
306
      {
 
307
        for (i = 0, j = -1; i < height; i++, j++)
 
308
          arrow_draw_hline (window, gc, x + j, x + width - j - 1, y + i, i == 0);
 
309
          
 
310
      }
 
311
    else if (arrow_type == GTK_ARROW_UP)
 
312
      {
 
313
        for (i = height - 1, j = -1; i >= 0; i--, j++)
 
314
          arrow_draw_hline (window, gc, x + j, x + width - j - 1, y + i, i == height - 1);
 
315
      }
 
316
    else if (arrow_type == GTK_ARROW_LEFT)
 
317
      {
 
318
        for (i = width - 1, j = -1; i >= 0; i--, j++)
 
319
          arrow_draw_vline (window, gc, y + j, y + height - j - 1, x + i, i == width - 1);
 
320
      }
 
321
    else if (arrow_type == GTK_ARROW_RIGHT)
 
322
      {
 
323
        for (i = 0, j = -1; i < width; i++, j++)
 
324
          arrow_draw_vline (window, gc, y + j, y + height - j - 1,  x + i, i == 0);
 
325
      }
 
326
    
 
327
    if (area)
 
328
      gdk_gc_set_clip_rectangle (gc, NULL);
 
329
  }
 
330
}
 
331
 
 
332
/* This function is another home grown routine simply for the
 
333
 * purpose of abstracting the multiple draw_arrow routines, so
 
334
 * that modifications such as new variants could easily be added 
 
335
 * later on with virtually no modifications anywhere else.
 
336
 */
 
337
void
 
338
do_draw_arrow(GdkWindow * window,
 
339
              GdkRectangle * area,
 
340
              GtkArrowType arrow_type,
 
341
              GdkGC * fill_gc,
 
342
              GdkGC * border_gc,
 
343
              gint x,
 
344
              gint y,
 
345
              gint width,
 
346
              gint height,
 
347
              gint arrow_style)
 
348
{
 
349
  gint aw=width, ah=height, extra_tail=0;
 
350
 
 
351
  switch (arrow_style) {
 
352
    case ARROW_STYLE_ICEGRADIENT : 
 
353
      ah -= 2;
 
354
      aw -= 2;
 
355
      x += (width - aw) / 2;
 
356
      y += (height - ah) / 2;
 
357
      do_draw_icegradient_arrow(window, area, arrow_type, fill_gc, TRUE, x, y, aw, ah);
 
358
      do_draw_icegradient_arrow(window, area, arrow_type, border_gc, FALSE, x, y, aw, ah);
 
359
      break;
 
360
    case ARROW_STYLE_WONDERLAND : 
 
361
      do_draw_wonderland_arrow(window, area, arrow_type, border_gc, x+1, y+1, width-2, height-2);
 
362
      break;
 
363
    case ARROW_STYLE_THINICE : 
 
364
    case ARROW_STYLE_XFCE :
 
365
    case ARROW_STYLE_DEFAULT : 
 
366
      if (arrow_style == ARROW_STYLE_THINICE) 
 
367
        extra_tail=3;
 
368
      else  
 
369
        if (arrow_style == ARROW_STYLE_XFCE) 
 
370
          extra_tail=1;
 
371
 
 
372
      ah -= 2;
 
373
      aw -= 2;
 
374
      if ((arrow_type == GTK_ARROW_LEFT) || (arrow_type == GTK_ARROW_RIGHT)) {
 
375
        gfloat tmp=((ah+1)/2) - ((width%2)?1:0);
 
376
        if (tmp > aw) {
 
377
          ah = 2*aw - 1 - ((width%2)?1:0);
 
378
          aw = (ah+1)/2;
 
379
        } else {
 
380
          aw = (gint) tmp;
 
381
          ah = 2*aw - 1;
 
382
        }  
 
383
 
 
384
        if ((ah < 5) || (aw < 3)) {
 
385
          ah = 5;
 
386
          aw = 3;
 
387
        }
 
388
        aw += extra_tail;
 
389
      } else { 
 
390
        gfloat tmp=((aw+1)/2) - ((height%2)?1:0);
 
391
      
 
392
        if (tmp > ah) {
 
393
          aw = 2*ah - 1 - ((height%2)?1:0);
 
394
          ah = (aw+1)/2;
 
395
        } else {
 
396
          ah = (gint) tmp;
 
397
          aw = 2*ah - 1;
 
398
        }  
 
399
 
 
400
        if ((aw < 5) || (ah < 3)) {
 
401
          aw = 5;
 
402
          ah = 3;
 
403
        }
 
404
        ah += extra_tail;
 
405
      }
 
406
 
 
407
      x += (width - aw) / 2 ;
 
408
      y += (height - ah) / 2;
 
409
      
 
410
      do_draw_default_arrow(window, area, arrow_type, border_gc, x, y, aw, ah);
 
411
      do_draw_default_arrow(window, area, arrow_type, fill_gc, x+1, y+1, aw-2, ah-2);
 
412
      break;
 
413
    case ARROW_STYLE_XPM : 
 
414
    default :
 
415
      do_draw_arrow(window, area, arrow_type, fill_gc, border_gc, x, y, width, height, ARROW_STYLE_ICEGRADIENT);
 
416
      break;
 
417
  }
 
418
}
 
419
 
 
420
 
 
421
gboolean 
 
422
TranslateArrowStyleName (gchar * str, gint *retval)
 
423
{
 
424
#define is_enum(XX)  (g_ascii_strncasecmp(str, XX, strlen(XX))==0)
 
425
  if (is_enum("icegradient"))
 
426
    *retval = ARROW_STYLE_ICEGRADIENT;
 
427
  else if (is_enum("thinice"))
 
428
    *retval = ARROW_STYLE_THINICE;
 
429
  else if (is_enum("wonderland"))
 
430
    *retval = ARROW_STYLE_WONDERLAND;
 
431
  else if (is_enum("default") || is_enum("cleanice"))
 
432
    *retval = ARROW_STYLE_DEFAULT;
 
433
  else if (is_enum("xfce"))
 
434
    *retval = ARROW_STYLE_XFCE;
 
435
  else if (is_enum("xpm"))
 
436
    *retval = ARROW_STYLE_XPM;
 
437
  else
 
438
    return FALSE; 
 
439
 
 
440
  return TRUE;
 
441
}