KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > java > swing > plaf > gtk > BlueprintEngine


1 /*
2  * @(#)BlueprintEngine.java 1.23 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package com.sun.java.swing.plaf.gtk;
8
9 import java.awt.*;
10 import java.awt.image.*;
11 import java.security.AccessController JavaDoc;
12 import java.util.*;
13 import javax.swing.*;
14 import javax.swing.plaf.ComponentUI JavaDoc;
15 import javax.swing.plaf.synth.*;
16 import sun.security.action.GetPropertyAction;
17 import sun.swing.plaf.synth.SynthUI;
18
19 /**
20  * GTKEngine implementation that renders using images. The images to render
21  * are dictated by the <code>BlueprintStyle.Info</code>.
22  *
23  * @version 1.23 12/19/03
24  * @author Joshua Outwater
25  */

26 class BlueprintEngine extends GTKEngine implements GTKConstants {
27     /**
28      * By default we don't use smooth scaling as it is currently not optimized.
29      */

30     private static final Object JavaDoc RENDERING_HINT;
31
32     private int COMPONENT_NORTH_WEST = 1;
33     private int COMPONENT_NORTH = 2;
34     private int COMPONENT_NORTH_EAST = 4;
35     private int COMPONENT_WEST = 8;
36     private int COMPONENT_CENTER = 16;
37     private int COMPONENT_EAST = 32;
38     private int COMPONENT_SOUTH_EAST = 64;
39     private int COMPONENT_SOUTH = 128;
40     private int COMPONENT_SOUTH_WEST = 256;
41     private int COMPONENT_ALL = 512;
42
43     private int _clipX1;
44     private int _clipX2;
45     private int _clipY1;
46     private int _clipY2;
47
48     static {
49         if ("true".equals((String JavaDoc)AccessController.doPrivileged(
50                    new GetPropertyAction("swing.pixmap.smoothScaling")))) {
51             RENDERING_HINT = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
52         }
53         else {
54             RENDERING_HINT = null;
55         }
56     }
57
58     public void paintSlider(SynthContext context, Graphics g, int state,
59                            int shadowType, String JavaDoc info,
60                            int x, int y, int w, int h, int orientation) {
61         if (!paintSimpleImage(context, g, x, y, w, h, true,
62                 ((BlueprintStyle)context.getStyle()).
63                          getInfo("SLIDER", info, state, shadowType, orientation,
64                                  UNDEFINED, UNDEFINED, null))) {
65             super.paintSlider(context, g, state, shadowType, info,
66                               x, y, w, h, orientation);
67         }
68     }
69
70     public void paintHline(SynthContext context, Graphics g, int state,
71                            String JavaDoc info, int x, int y, int w, int h) {
72
73         SynthStyle style = context.getStyle();
74         Component c = context.getComponent();
75
76         // We have a different style to use if we are the child of
77
// a popup menu.
78
c = c.getParent();
79         if (c instanceof JPopupMenu) {
80             SynthStyle newStyle = getStyle((JPopupMenu)c,
81                     ((JPopupMenu)c).getUI());
82             if (newStyle != null) {
83                 style = newStyle;
84             }
85         }
86
87         BlueprintStyle.Info blueprintInfo =
88                 ((BlueprintStyle)style).getInfo("HLINE", info,
89                         state, UNDEFINED, GTKConstants.HORIZONTAL,
90                         UNDEFINED, UNDEFINED, null);
91         if (blueprintInfo != null && blueprintInfo.getImage() != null) {
92             themeBlueprintRender(context, g, x, y, w, h,
93                     blueprintInfo.getImage(), blueprintInfo.getImageInsets(),
94                     COMPONENT_ALL, blueprintInfo.getStretch(), false,
95                     blueprintInfo.isBkgMask(), blueprintInfo.isRecolorable(),
96                     blueprintInfo.getColorizeColor());
97         } else {
98             super.paintHline(context, g, state, info, x, y, w, h);
99         }
100     }
101
102     public void paintVline(SynthContext context, Graphics g, int state,
103                            String JavaDoc info, int x, int y, int w, int h) {
104         BlueprintStyle.Info blueprintInfo =
105                 ((BlueprintStyle)context.getStyle()).getInfo("VLINE", info,
106                         state, UNDEFINED, GTKConstants.VERTICAL,
107                         UNDEFINED, UNDEFINED, null);
108         if (blueprintInfo != null && blueprintInfo.getImage() != null) {
109             themeBlueprintRender(context, g, x, y, w, h, blueprintInfo.getImage(),
110                     blueprintInfo.getImageInsets(), COMPONENT_ALL,
111                     blueprintInfo.getStretch(), false,
112                     blueprintInfo.isBkgMask(), blueprintInfo.isRecolorable(),
113                     blueprintInfo.getColorizeColor());
114         } else {
115             super.paintVline(context, g, state, info, x, y, w, h);
116         }
117     }
118
119     public void paintArrow(SynthContext context, Graphics g, int state,
120                            int shadowType, int direction, String JavaDoc info,
121                            int x, int y, int w, int h) {
122         Component c = context.getComponent();
123
124         // Don't paint the arrow if we're in a spinner or combo box.
125
// We get that from the image.
126
if (c.getName() == "Spinner.nextButton" ||
127                 c.getName() == "Spinner.previousButton" ||
128                 c.getName() == "ComboBox.arrowButton") {
129             return;
130         }
131
132         String JavaDoc parentType = null;
133         c = c.getParent();
134         if (c != null && c instanceof JComponent) {
135             c = c.getParent();
136             if (c != null && c instanceof JComponent) {
137                 parentType = getComponentType((JComponent)c);
138             }
139         }
140
141         if (!paintSimpleImage(context, g, x, y, w, h, true,
142                 ((BlueprintStyle)context.getStyle()).
143                         getInfo("ARROW", info, state, shadowType,
144                             UNDEFINED, UNDEFINED, direction, parentType))) {
145             super.paintArrow(context, g, state, shadowType, direction,
146                     info, x, y, w, h);
147         }
148     }
149
150     public void paintBox(SynthContext context, Graphics g, int state,
151                          int shadowType, String JavaDoc info, int x, int y,
152                          int w, int h) {
153         int orientation;
154         Region id = context.getRegion();
155         Component c = context.getComponent();
156         SynthStyle style = context.getStyle();
157
158         // Blueprint checks to make sure that we aren't calling
159
// paintBox on a slider/scrollbar with detail hscrollbar or
160
// vscrollbar, because they do the work in paintArrow instead.
161
// We do it here because we have the correct bounds for the whole
162
// button.
163
Integer JavaDoc arrowDirection =
164             (Integer JavaDoc)((JComponent)c).getClientProperty("__arrow_direction__");
165         if (info == "vscrollbar" || info == "hscrollbar" &&
166                 arrowDirection != null) {
167             int direction = arrowDirection.intValue();
168             switch (direction) {
169             case SwingConstants.NORTH:
170                 direction = GTKConstants.ARROW_UP;
171                 break;
172             case SwingConstants.SOUTH:
173                 direction = GTKConstants.ARROW_DOWN;
174                 break;
175             case SwingConstants.EAST:
176                 direction = GTKConstants.ARROW_RIGHT;
177                 break;
178             case SwingConstants.WEST:
179                 direction = GTKConstants.ARROW_LEFT;
180                 break;
181             }
182
183             c = (JComponent)c.getParent();
184             if (c == null || !(c instanceof JComponent)) {
185                 return;
186             }
187
188             if (c instanceof JScrollBar) {
189                 SynthStyle newStyle = getStyle((JScrollBar)c,
190                         ((JScrollBar)c).getUI());
191                 if (newStyle != null) {
192                     style = newStyle;
193                 }
194
195                 if (paintSimpleImage(context, g, x, y, w, h, true,
196                         ((BlueprintStyle)style).getInfo("STEPPER", info,
197                                 state, UNDEFINED, UNDEFINED, UNDEFINED,
198                                 direction, null))) {
199                     return;
200                 }
201                 if (!paintSimpleImage(context, g, x, y, w, h, true,
202                     ((BlueprintStyle)style).getInfo("BOX", info, state,
203                                 shadowType, UNDEFINED, UNDEFINED,
204                                 UNDEFINED, null))) {
205                     super.paintBox(context, g, state, shadowType, info,
206                         x, y, w, h);
207                 }
208                 return;
209             }
210         }
211
212         // If the button is in a spinner get the style of the JSpinner.
213
if (c.getName() == "Spinner.nextButton" ||
214                 c.getName() == "Spinner.previousButton" &&
215                 arrowDirection != null) {
216             if (arrowDirection.intValue() == SwingConstants.NORTH) {
217                 info = "spinbutton_up";
218             } else {
219                 info = "spinbutton_down";
220             }
221             c = c.getParent();
222             if (c instanceof JSpinner) {
223                 SynthStyle newStyle = getStyle((JSpinner)c,
224                         ((JSpinner)c).getUI());
225                 if (newStyle != null) {
226                     style = newStyle;
227                 }
228             }
229         }
230
231         if (id == Region.SCROLL_BAR) {
232             if (((JScrollBar)c).getOrientation() ==
233                     SwingConstants.HORIZONTAL) {
234                 orientation = GTKConstants.HORIZONTAL;
235             }
236             else {
237                 orientation = GTKConstants.VERTICAL;
238             }
239         }
240         else if (id == Region.SLIDER_TRACK) {
241             if (((JSlider)c).getOrientation() ==
242                     SwingConstants.HORIZONTAL) {
243                 orientation = GTKConstants.HORIZONTAL;
244             }
245             else {
246                 orientation = GTKConstants.VERTICAL;
247             }
248         }
249         else {
250             orientation = UNDEFINED;
251         }
252
253         String JavaDoc parentType = null;
254         if (c != null) {
255             c = c.getParent();
256             if (c != null && c instanceof JComponent) {
257                 parentType = getComponentType((JComponent)c);
258             }
259         }
260
261         if (!paintSimpleImage(context, g, x, y, w, h, true,
262                 ((BlueprintStyle)style).getInfo("BOX", info, state,
263                         shadowType, orientation, UNDEFINED, UNDEFINED,
264                         parentType))) {
265             super.paintBox(context, g, state, shadowType, info, x, y, w, h);
266         }
267     }
268
269     public void paintBoxGap(SynthContext context, Graphics g, int state,
270                             int shadow, String JavaDoc key, int x, int y,
271                             int w, int h, int gapSide, int gapStart,
272                             int gapSize) {
273         BlueprintStyle.Info info = ((BlueprintStyle)context.getStyle()).getInfo(
274               "BOX_GAP", key, state, shadow, UNDEFINED, gapSide, UNDEFINED,
275               null);
276
277         if (info != null) {
278             paintGapImage(context, info, g, x, y, w, h, true, gapSide,
279                     gapStart, gapSize);
280         } else {
281             super.paintBoxGap(context, g, state, shadow, key, x, y, w, h,
282                               gapSide, gapStart, gapSize);
283         }
284     }
285
286     public void paintHandle(SynthContext context, Graphics g, int paintState,
287                             int shadowType, String JavaDoc info, int x, int y,
288                             int w, int h, int orientation) {
289         if (info == "handlebox" || info == "dockitem") {
290             w -=2;
291             h -=1;
292         }
293
294         if (!paintSimpleImage(context, g, x, y, w, h, true,
295                 ((BlueprintStyle)context.getStyle()).
296                         getInfo("HANDLE", info, paintState, shadowType,
297                                 orientation, UNDEFINED, UNDEFINED, null))) {
298             super.paintHandle(context, g, paintState, shadowType, info, x, y,
299                     w, h, orientation);
300         }
301     }
302
303     public void paintOption(SynthContext context, Graphics g, int paintState,
304                             int shadowType, String JavaDoc info, int x, int y,
305                             int w, int h) {
306         if (!paintSimpleImage(context, g, x, y, w, h, true,
307                     ((BlueprintStyle)context.getStyle()).
308                          getInfo("OPTION", info, paintState, shadowType,
309                                  UNDEFINED, UNDEFINED, UNDEFINED, null))) {
310             super.paintOption(context, g, paintState, shadowType, info, x, y,
311                               w, h);
312         }
313     }
314
315     public void paintFocus(SynthContext context, Graphics g, int state,
316                            String JavaDoc key, int x, int y, int w, int h) {
317         if (!paintSimpleImage(context, g, x, y, w, h, true,
318                 ((BlueprintStyle)context.getStyle()).
319                         getInfo("FOCUS", key, state, UNDEFINED, UNDEFINED,
320                                 UNDEFINED, UNDEFINED, null))) {
321             super.paintFocus(context, g, state, key, x, y, w, h);
322         }
323     }
324
325     public void paintShadow(SynthContext context, Graphics g, int state,
326                             int shadowType, String JavaDoc info, int x, int y,
327                             int w, int h) {
328         Component c = context.getComponent();
329         String JavaDoc parentType = null;
330         SynthStyle style = context.getStyle();
331
332         if (c.getName() == "ComboBox.textField") {
333             parentType = "GtkCombo";
334         } else if (c.getName() == "ComboBox.renderer") {
335             c = c.getParent();
336             if (c != null) {
337                 c = c.getParent();
338                 parentType = "GtkCombo";
339             }
340         }
341
342         if (c instanceof JComboBox) {
343             // Use the Style from the editor
344
JComboBox cb = (JComboBox)c;
345             Component editor = cb.getEditor().getEditorComponent();
346             if (editor instanceof JTextField) {
347                 if (!cb.isEditable() && editor.getParent() == null) {
348                     // GTKStyleFactory hands back a bogus Style when a
349
// Component doesn't have a parent. As the editor
350
// is only parented when the JComboBox is editable it
351
// means we can get back a bogus style. To force the
352
// real style to be assigned we parent the editor.
353
// YES, this is ugly!
354
cb.add(editor);
355                     cb.remove(editor);
356                 }
357                 SynthStyle newStyle = getStyle((JTextField)editor,
358                         ((JTextField)editor).getUI());
359                 if (newStyle != null) {
360                     style = newStyle;
361                 }
362             }
363         }
364
365         if (info == "menu" && parentType == "GtkHBox") {
366             return;
367         }
368
369         if (!paintSimpleImage(context, g, x, y, w, h, true,
370                 ((BlueprintStyle)style).getInfo("SHADOW", info, state,
371                         shadowType, UNDEFINED, UNDEFINED, UNDEFINED,
372                         parentType))) {
373            super.paintShadow(context, g, state, shadowType, info, x, y, w, h);
374         }
375     }
376
377     public void paintExpander(SynthContext context, Graphics g, int state,
378                               int expanderStyle, String JavaDoc info, int x,
379                               int y, int w, int h) {
380         // It does not appear that there is a way to override this.
381
super.paintExpander(context, g, state, expanderStyle, info, x, y, w,h);
382     }
383
384     public void paintCheck(SynthContext context, Graphics g, int state,
385                            int shadowType, String JavaDoc info, int x, int y,
386                            int w, int h) {
387         if (!paintSimpleImage(context, g, x, y, w, h, true,
388                 ((BlueprintStyle)context.getStyle()).
389                         getInfo("CHECK", info, state, shadowType, UNDEFINED,
390                                 UNDEFINED, UNDEFINED, null))) {
391             super.paintCheck(context, g, state, shadowType, info, x, y, w, h);
392         }
393     }
394
395     public void paintExtension(SynthContext context, Graphics g, int state,
396                                int shadowType, String JavaDoc info, int x, int y,
397                                int w, int h, int placement, int tabIndex) {
398         if (!paintSimpleImage(context, g, x, y, w, h, true,
399                 ((BlueprintStyle)context.getStyle()).
400                          getInfo("EXTENSION", info, state, shadowType,
401                                  UNDEFINED, placement, UNDEFINED, null))) {
402             super.paintExtension(context, g, state, shadowType, info, x, y,
403                                  w, h, placement, tabIndex);
404         }
405     }
406
407     public void paintFlatBox(SynthContext context, Graphics g, int state,
408                              String JavaDoc key, int x, int y, int w, int h) {
409         if (key == "checkbutton" && state == SynthConstants.MOUSE_OVER) {
410             return;
411         }
412
413         Component c = context.getComponent();
414
415         String JavaDoc parentType = null;
416         c = c.getParent();
417         if (c instanceof CellRendererPane) {
418             // Skip the CellRendererPane
419
c = c.getParent();
420         }
421         if (c != null && c instanceof JComponent) {
422             parentType = getComponentType((JComponent)c);
423         }
424
425         if (!paintSimpleImage(context, g, x, y, w, h, true,
426                 ((BlueprintStyle)context.getStyle()).
427                          getInfo("FLAT_BOX", key, state, UNDEFINED, UNDEFINED,
428                                  UNDEFINED, UNDEFINED, parentType))) {
429             super.paintFlatBox(context, g, state, key, x, y, w, h);
430         }
431     }
432
433     void paintBackground(SynthContext context, Graphics g, int state,
434             Color color, int x, int y, int w, int h) {
435         JComponent c = context.getComponent();
436         if (c instanceof JPopupMenu) {
437             if (paintSimpleImage(context, g, x, y, w, h, true,
438                 ((BlueprintStyle)context.getStyle()).
439                          getInfo("BACKGROUND", null, state, UNDEFINED,
440                              UNDEFINED, UNDEFINED, UNDEFINED, null))) {
441                 return;
442             }
443         }
444         super.paintBackground(context, g, state, color, x, y, w, h);
445     }
446
447     /**
448      * Paints a gap image. This renders the image into a portion of
449      * the passed in region that is dictated
450      * by the <code>gapSide</code> and <code>size</code> arguments. For
451      * example, if <code>gapSide</code> is <code>GTKConstants.TOP</code>,
452      * this will render the image into the space:
453      * <table>
454      * <tr><td>x origin<td> <code>x</code> + <code>gapStart</code>
455      * <tr><td>y origin<td> <code>y</code>
456      * <tr><td>width<td> <code>gapSize</code>
457      * <tr><td>height<td> <code>size</code>
458      * </table>
459      *
460      * @param context Context used to retrieve style information.
461      * @param info Blueprint style info
462      * @param g Graphics object to paint to
463      * @param x X origin
464      * @param y Y origin
465      * @param w Width to draw to
466      * @param h Height to draw to
467      * @param drawCenter Whether or not the center is drawn.
468      * @param gapSide Side the gap is on, one of GTKConstants.LEFT,
469      * GTKConstants.RIGHT, GTKConstants.TOP or GTKConstants.BOTTOM
470      * @param gapStart Starting location of the gap. The axis the gap is
471      * on is dictated by the gapSide
472      * @param gapSize size of the gap
473      */

474     private void paintGapImage(SynthContext context, BlueprintStyle.Info info,
475                                Graphics g, int x, int y, int w, int h,
476                                boolean drawCenter, int gapSide, int gapStart,
477                                int gapSize) {
478         
479         Rectangle r1 = new Rectangle();
480         Rectangle r2 = new Rectangle();
481         Rectangle r3 = new Rectangle();
482         int size = 0;
483         int componentMask = COMPONENT_ALL;
484         Image startImage = info.getGapStartImage();
485         Image image = info.getGapImage();
486         Image endImage = info.getGapEndImage();
487
488         if (!drawCenter) {
489             componentMask |= COMPONENT_CENTER;
490         }
491
492         // Blueprint doesn't look at each individual image for size, just the
493
// starting image.
494
if (startImage != null) {
495             if (gapSide == TOP || gapSize == BOTTOM) {
496                 size = startImage.getHeight(null);
497             } else {
498                 size = startImage.getWidth(null);
499             }
500         } else {
501             if (gapSide == TOP || gapSize == BOTTOM) {
502                 size = ((BlueprintStyle)context.getStyle()).getYThickness();
503             } else {
504                 size = ((BlueprintStyle)context.getStyle()).getXThickness();
505             }
506         }
507
508         if (gapSize > 0) {
509             switch(gapSide) {
510             case TOP:
511                 if (!drawCenter) {
512                     componentMask |= COMPONENT_NORTH_WEST | COMPONENT_NORTH |
513                         COMPONENT_NORTH_EAST;
514                 }
515                 // gap start
516
r1.x = x;
517                 r1.y = y;
518                 r1.width = gapStart;
519                 r1.height = size;
520                 // gap
521
r2.x = x + gapStart;
522                 r2.y = y;
523                 r2.width = gapSize;
524                 r2.height = size;
525                 // gap end
526
r3.x = x + gapStart + gapSize;
527                 r3.y = y;
528                 r3.width = w - (gapStart + gapSize);
529                 r3.height = size;
530                 break;
531             case BOTTOM:
532                 if (!drawCenter) {
533                     componentMask |= COMPONENT_SOUTH_WEST | COMPONENT_SOUTH |
534                         COMPONENT_SOUTH_EAST;
535                 }
536                 // gap start
537
r1.x = x;
538                 r1.y = y + h - size;
539                 r1.width = gapStart;
540                 r1.height = size;
541                 // gap
542
r2.x = x + gapStart;
543                 r2.y = y + h - size;
544                 r2.width = gapSize;
545                 r2.height = size;
546                 // gap end
547
r3.x = x + gapStart + gapSize;
548                 r3.y = y + h - size;
549                 r3.width = w - (gapStart + gapSize);
550                 r3.height = size;
551                 break;
552             case LEFT:
553                 if (!drawCenter) {
554                     componentMask |= COMPONENT_NORTH_WEST | COMPONENT_WEST |
555                         COMPONENT_SOUTH_WEST;
556                 }
557                 // gap start
558
r1.x = x;
559                 r1.y = y;
560                 r1.width = size;
561                 r1.height = gapStart;
562                 // gap
563
r2.x = x;
564                 r2.y = y + gapStart;
565                 r2.width = size;
566                 r2.height = gapSize;
567                 // gap end
568
r3.x = x;
569                 r3.y = y + gapStart + gapSize;
570                 r3.width = size;
571                 r3.height = h - (gapStart + gapSize);
572                 break;
573             case RIGHT:
574                 if (!drawCenter) {
575                     componentMask |= COMPONENT_NORTH_EAST | COMPONENT_EAST |
576                         COMPONENT_SOUTH_EAST;
577                 }
578                 // gap start
579
r1.x = x + w - size;
580                 r1.y = y;
581                 r1.width = size;
582                 r1.height = gapStart;
583                 // gap
584
r2.x = x + w - size;
585                 r2.y = y + gapStart;
586                 r2.width = size;
587                 r2.height = gapSize;
588                 // gap end
589
r3.x = x + w - size;
590                 r3.y = y + gapStart + gapSize;
591                 r3.width = size;
592                 r3.height = h - (gapStart + gapSize);
593                 break;
594             }
595
596             themeBlueprintRender(context, g, x, y, w, h, info.getImage(),
597                     info.getImageInsets(), componentMask, true, false,
598                     info.isBkgMask(), info.isRecolorable(),
599                     info.getColorizeColor());
600
601             // NOTE:
602
// stretch should be queried from the info, but there is currently
603
// no support for that field for gap images in BlueprintStyle.Info.
604
if (startImage != null) {
605                 themeBlueprintRender(context, g, r1.x, r1.y, r1.width, r1.height,
606                         startImage, info.getGapStartInsets(), COMPONENT_ALL,
607                         true, false, false, false, null);
608             }
609             if (image != null) {
610                 themeBlueprintRender(context, g, r2.x, r2.y, r2.width, r2.height,
611                         image, info.getGapInsets(), COMPONENT_ALL,
612                         true, false, false, false, null);
613             }
614             if (endImage != null) {
615                 themeBlueprintRender(context, g, r3.x, r3.y, r3.width, r3.height,
616                         endImage, info.getGapEndInsets(), COMPONENT_ALL,
617                         true, false, false, false, null);
618             }
619         }
620     }
621
622     /**
623      * Paints the image and overlay image from the passed in style.
624      *
625      * @param g Graphics object to paint to
626      * @param x X origin
627      * @param y Y origin
628      * @param w Width to draw to
629      * @param h Height to draw to
630      * @param drawCenter Whether the center of the image should be drawn
631      * @param info Used to fetch image, insets and overlay image from
632      */

633     private boolean paintSimpleImage(SynthContext context, Graphics g, int x, int y,
634             int w, int h, boolean drawCenter, BlueprintStyle.Info info) {
635         if (info != null) {
636             Rectangle clip = g.getClipBounds();
637             _clipX1 = clip.x;
638             _clipY1 = clip.y;
639             _clipX2 = _clipX1 + clip.width;
640             _clipY2 = _clipY1 + clip.height;
641             themeBlueprintRender(context, g, x, y, w, h, info.getImage(),
642                     info.getImageInsets(), drawCenter ? COMPONENT_ALL :
643                     COMPONENT_ALL | COMPONENT_CENTER, info.getStretch(),
644                     false, info.isBkgMask(), info.isRecolorable(),
645                     info.getColorizeColor());
646             if (drawCenter) {
647                 themeBlueprintRender(context, g, x, y, w, h,
648                         info.getOverlayImage(), info.getOverlayInsets(),
649                         COMPONENT_ALL, info.getOverlayStretch(), true,
650                         false, false, null);
651             }
652             return true;
653         }
654         return false;
655     }
656
657     /**
658      * Paints the image in the specified region.
659      *
660      * @param g Graphics object to paint to
661      * @param x X origin
662      * @param y Y origin
663      * @param w Width to draw to
664      * @param h Height to draw to
665      * @param image Image to render
666      * @param insets Insets used to determine portion of image that is fixed.
667      * @param componentMask Mask defining the areas of the image to draw.
668      * @param stretch Stretch the image to fit the drawing area.
669      * @param center Centers the image to the middle of the drawing area.
670      * @param isBkgMask Whether or not the image is a background mask.
671      * @param isRecolorable If the image is recolorable.
672      * @param colorizeColor Color to use if image is recolorable.
673      */

674     private void themeBlueprintRender(SynthContext context, Graphics g,
675                                       int x, int y, int w, int h, Image image,
676                                       Insets insets, int componentMask,
677                                       boolean stretch, boolean center,
678                                       boolean isBkgMask, boolean isRecolorable,
679                                       Color colorizeColor) {
680         if (image == null) {
681             return;
682         }
683         if (insets == null) {
684             insets = GTKPainter.EMPTY_INSETS;
685         }
686         int iw = image.getWidth(null);
687         int ih = image.getHeight(null);
688  
689         if (isBkgMask) {
690             // Colorize mask using the colorizeColor from info.
691
BufferedImage i = new BufferedImage(iw, ih,
692                                                 BufferedImage.TYPE_INT_ARGB);
693             Graphics2D g3 = i.createGraphics();
694              
695             boolean topParentReached = false;
696             int steps = 0;
697  
698             Component compParent = context.getComponent();
699  
700             while (!topParentReached && steps <= 2) {
701                 compParent = compParent.getParent ();
702                 steps ++;
703  
704                 if (compParent != null) {
705                     Color color = compParent.getBackground ();
706                     if (color != null) {
707                         if (!color.equals (colorizeColor) &&
708                             !color.equals (Color.black) &&
709                             !(compParent instanceof JFileChooser)) {
710                             colorizeColor = color;
711                             topParentReached = true;
712                         }
713                     }
714                 } else {
715                     topParentReached = true;
716                 }
717             }
718  
719             if (colorizeColor == null) {
720                 colorizeColor = ((GTKStyle)context.getStyle()).
721                     getGTKColor(context.getComponent(), context.getRegion(),
722                                 context.getComponentState(),
723                                 ColorType.BACKGROUND);
724             }
725             g3.setColor(colorizeColor);
726             g3.fillRect(0, 0, iw, ih);
727             g3.setComposite(AlphaComposite.DstIn);
728             g3.drawImage(image, 0, 0, null);
729             g3.dispose();
730             image = i;
731         } else if (isRecolorable) {
732             // Create a copy of the image to manipulate the pixels.
733
BufferedImage i = new BufferedImage(iw, ih,
734                     BufferedImage.TYPE_INT_ARGB);
735             Graphics2D g3 = i.createGraphics();
736             g3.setComposite(AlphaComposite.Src);
737             g3.drawImage(image, 0, 0, null);
738             g3.dispose();
739
740             int red = colorizeColor.getRed();
741             int green = colorizeColor.getGreen();
742             int blue = colorizeColor.getBlue();
743             int alpha = colorizeColor.getAlpha();
744
745             Color color = RGBtoHLS(red, green, blue);
746
747             int hue = color.getRed();
748             int lum = color.getGreen();
749             int sat = color.getBlue();
750
751             int[] pixels = null;
752             // Get the pixel data from the image.
753
pixels = i.getRaster().getPixels(0, 0, iw, ih, pixels);
754
755             // Colorize the pixels.
756
for (int index = 0; index < pixels.length; index+=4) {
757                 red = pixels[index];
758                 green = pixels[index + 1];
759                 blue = pixels[index + 2];
760
761                 color = RGBtoHLS(red, green, blue);
762                 red = hue;
763                 green = color.getGreen();
764                 blue = sat;
765
766                 color = HLStoRGB(red, green, blue);
767
768                 pixels[index] = color.getRed();
769                 pixels[index + 1] = color.getGreen();
770                 pixels[index + 2] = color.getBlue();
771                 pixels[index + 3] = Math.min(
772                         pixels[index + 3], alpha);
773             }
774             // Set the pixel data for the image.
775
i.getRaster().setPixels(0, 0, iw, ih, pixels);
776             image = i;
777         }
778
779         if (stretch) {
780 // themeBlueprintComputeHints();
781
}
782
783         if (iw <= 0 || ih <= 0) {
784             return;
785         }
786         Object JavaDoc lastHint;
787         Object JavaDoc renderingHint = RENDERING_HINT;
788
789         if (renderingHint != null && stretch) {
790             Graphics2D g2 = (Graphics2D)g;
791
792             lastHint = g2.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
793             if (lastHint == null) {
794                 lastHint = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
795             }
796             g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
797                                 renderingHint);
798         }
799         else {
800             lastHint = null;
801         }
802
803         if (!stretch) {
804             if (center) {
805                 /* Center the image. */
806                 blueprintRender(image, g, 0, 0, iw, ih, x + (w / 2) - (iw / 2),
807                         y + (h / 2) - (ih / 2), iw, ih);
808             }
809             else {
810                 /* Tile the image. */
811                 int lastIY = 0;
812                 for (int yCounter = y, maxY = y + h; yCounter < maxY;
813                          yCounter += (ih - lastIY), lastIY = 0) {
814                     int lastIX = 0;
815                     for (int xCounter = x, maxX = x + w; xCounter < maxX;
816                              xCounter += (iw - lastIX), lastIX = 0) {
817                         int dx2 = Math.min(maxX, xCounter + iw - lastIX);
818                         int dy2 = Math.min(maxY, yCounter + ih - lastIY);
819                         if (intersectsClip(xCounter, yCounter, dx2, dy2)) {
820                             g.drawImage(image, xCounter, yCounter, dx2, dy2,
821                                         lastIX, lastIY, lastIX + dx2 -xCounter,
822                                         lastIY + dy2 - yCounter, null);
823                         }
824                     }
825                 }
826             }
827         }
828         else {
829             int srcX[] = new int[4];
830             int srcY[] = new int[4];
831             int destX[] = new int[4];
832             int destY[] = new int[4];
833
834             srcX[0] = 0;
835             srcX[1] = insets.left;
836             srcX[2] = iw - insets.right;
837             srcX[3] = iw;
838
839             srcY[0] = 0;
840             srcY[1] = insets.top;
841             srcY[2] = ih - insets.bottom;
842             srcY[3] = ih;
843
844             destX[0] = x;
845             destX[1] = x + insets.left;
846             destX[2] = x + w - insets.right;
847             destX[3] = x + w;
848
849             destY[0] = y;
850             destY[1] = y + insets.top;
851             destY[2] = y + h - insets.bottom;
852             destY[3] = y + h;
853
854             /* Scale the image. */
855             if ((componentMask & COMPONENT_ALL) != 0) {
856                 componentMask = (COMPONENT_ALL - 1) & ~componentMask;
857             }
858
859             // top left
860
if ((componentMask & COMPONENT_NORTH_WEST) != 0) {
861                 blueprintRender(image, g,
862                         srcX[0], srcY[0],
863                         srcX[1] - srcX[0], srcY[1] - srcY[0],
864                         destX[0], destY[0],
865                         destX[1] - destX[0], destY[1] - destY[0]);
866             }
867             // top
868
if ((componentMask & COMPONENT_NORTH) != 0) {
869                 blueprintRender(image, g,
870                         srcX[1], srcY[0],
871                         srcX[2] - srcX[1], srcY[1] - srcY[0],
872                         destX[1], destY[0],
873                         destX[2] - destX[1], destY[1] - destY[0]);
874             }
875             // top right
876
if ((componentMask & COMPONENT_NORTH_EAST) != 0) {
877                 blueprintRender(image, g,
878                         srcX[2], srcY[0],
879                         srcX[3] - srcX[2], srcY[1] - srcY[0],
880                         destX[2], destY[0],
881                         destX[3] - destX[2], destY[1] - destY[0]);
882             }
883             // left
884
if ((componentMask & COMPONENT_WEST) != 0) {
885                 blueprintRender(image, g,
886                         srcX[0], srcY[1],
887                         srcX[1] - srcX[0], srcY[2] - srcY[1],
888                         destX[0], destY[1],
889                         destX[1] - destX[0], destY[2] - destY[1]);
890             }
891             // center
892
if ((componentMask & COMPONENT_CENTER) != 0) {
893                 blueprintRender(image, g,
894                         srcX[1], srcY[1],
895                         srcX[2] - srcX[1], srcY[2] - srcY[1],
896                         destX[1], destY[1],
897                         destX[2] - destX[1], destY[2] - destY[1]);
898             }
899             // right
900
if ((componentMask & COMPONENT_EAST) != 0) {
901                 blueprintRender(image, g,
902                         srcX[2], srcY[1],
903                         srcX[3] - srcX[2], srcY[2] - srcY[1],
904                         destX[2], destY[1],
905                         destX[3] - destX[2], destY[2] - destY[1]);
906             }
907             // bottom left
908
if ((componentMask & COMPONENT_SOUTH_WEST) != 0) {
909                 blueprintRender(image, g,
910                         srcX[0], srcY[2],
911                         srcX[1] - srcX[0], srcY[3] - srcY[2],
912                         destX[0], destY[2],
913                         destX[1] - destX[0], destY[3] - destY[2]);
914             }
915             // bottom
916
if ((componentMask & COMPONENT_SOUTH) != 0) {
917                 blueprintRender(image, g,
918                         srcX[1], srcY[2],
919                         srcX[2] - srcX[1], srcY[3] - srcY[2],
920                         destX[1], destY[2],
921                         destX[2] - destX[1], destY[3] - destY[2]);
922             }
923             // bottom right
924
if ((componentMask & COMPONENT_SOUTH_EAST) != 0) {
925                 blueprintRender(image, g,
926                         srcX[2], srcY[2],
927                         srcX[3] - srcX[2], srcY[3] - srcY[2],
928                         destX[2], destY[2],
929                         destX[3] - destX[2], destY[3] - destY[2]);
930             }
931         }
932
933         if (lastHint != null) {
934             ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,
935                                              lastHint);
936         }
937     }
938
939     /**
940      * Draws a portion of an image stretched.
941      *
942      * @param image Image to render.
943      * @param g Graphics to render to
944      * @param srcX X origin to draw from
945      * @param srxY Y origin to draw from
946      * @param srcWidth Width of source
947      * @param srcHeight Height of source
948      * @param destX X origin to draw to
949      * @param destY Y origin to draw to
950      * @param destWidth Width of destination
951      * @param destHeight Height of destination
952      */

953     private void blueprintRender(Image image, Graphics g,
954                 int srcX, int srcY, int srcWidth, int srcHeight,
955                 int destX, int destY, int destWidth, int destHeight) {
956         if (destWidth <= 0 || destHeight <= 0 ||
957                 !intersectsClip(destX, destY,
958                     destX + destWidth, destY + destHeight)) {
959             // Bogus location, nothing to paint
960
return;
961         }
962
963         if (srcWidth == 0 && srcHeight == 0) {
964             // Paint bilinear gradient.
965
} else if (srcHeight == 0 && destHeight == srcHeight) {
966             // Paint horizontal gradient.
967
} else if (srcHeight == 0 && destWidth == srcWidth) {
968             // Paint vertical gradient.
969
}
970
971         g.drawImage(image, destX, destY, destX + destWidth, destY + destHeight,
972                 srcX, srcY, srcX + srcWidth, srcY + srcHeight, null);
973     }
974
975     private boolean hasAncestorOfTypeFromList(JComponent c, ArrayList list) {
976         if (list == null) {
977             return false;
978         }
979
980         Iterator itr = list.iterator();
981         while (itr.hasNext()) {
982             if (hasAncestorOfType(c, (String JavaDoc)itr.next())) {
983                 return true;
984             }
985         }
986         return false;
987     }
988
989     private boolean hasAncestorOfType(JComponent c, String JavaDoc parentType) {
990         String JavaDoc type = null;
991         while (c != null) {
992             type = getComponentType(c);
993             if (type == parentType) {
994                 return true;
995             }
996             if (c.getParent() instanceof JComponent) {
997                 c = (JComponent)c.getParent();
998             } else {
999                 c = null;
1000            }
1001        }
1002        return false;
1003    }
1004
1005    private String JavaDoc getComponentType(JComponent c) {
1006        return GTKStyleFactory.gtkClassFor(SynthLookAndFeel.getRegion(c));
1007    }
1008
1009    private SynthStyle getStyle(JComponent c, ComponentUI JavaDoc ui) {
1010        if (ui instanceof SynthUI) {
1011            SynthContext parentContext = ((SynthUI)ui).getContext(c);
1012            // Note that we don't dispose of the context here, while this
1013
// isn't good, it just means we won't be recycling as often as
1014
// we can.
1015
return parentContext.getStyle();
1016        }
1017        return null;
1018    }
1019
1020    /**
1021     * Returns true if the passed in region intersects the clip.
1022     */

1023    private boolean intersectsClip(int x1, int y1, int x2, int y2) {
1024        return ((x2 < x1 || x2 > _clipX1) &&
1025                (y2 < y1 || y2 > _clipY1) &&
1026                (_clipX2 < _clipX1 || _clipX2 > x1) &&
1027                (_clipY2 < _clipY1 || _clipY2 > y1));
1028    }
1029
1030    /**
1031     * Convert RGB to HLS.
1032     *
1033     * @param r Red
1034     * @param g Green
1035     * @param b Blue
1036     * @return Color Where red = hue, green = lightness and blue = saturation.
1037     */

1038    private Color RGBtoHLS(int r, int g, int b) {
1039        int h, l, s;
1040        int min, max;
1041        int delta;
1042
1043        if (r > g) {
1044            max = Math.max(r, b);
1045            min = Math.min(g, b);
1046        } else {
1047            max = Math.max(g, b);
1048            min = Math.min(r, b);
1049        }
1050
1051        l = (max + min) / 2;
1052
1053        if (max == min) {
1054            s = 0;
1055            h = 0;
1056        } else {
1057            delta = (max - min);
1058
1059            if (l < 128) {
1060                s = 255 * delta / (max + min);
1061            } else {
1062                s = 255 * delta / (511 - max - min);
1063            }
1064
1065            if (r == max) {
1066                h = (g - b) / delta;
1067            } else if (g == max) {
1068                h = 2 + (b - r) / delta;
1069            } else {
1070                h = 4 + (r - g) / delta;
1071            }
1072
1073            h = (int)(h * 42.5);
1074
1075            if (h < 0) {
1076                h+= 255;
1077            } else if (h > 255) {
1078                h -= 255;
1079            }
1080        }
1081
1082        return new Color(h, l, s);
1083    }
1084
1085    /**
1086     * Convert HLS to RGB.
1087     *
1088     * @param hue Hue
1089     * @param lightness Lightness
1090     * @param saturation Saturation
1091     * @return Color Resulting RGB color.
1092     */

1093    private Color HLStoRGB(int hue, int lightness, int saturation) {
1094        double h = hue;
1095        double l = lightness;
1096        double s = saturation;
1097        double m1, m2;
1098
1099        if (s == 0) {
1100            hue = lightness;
1101            saturation = lightness;
1102        } else {
1103            if (l < 128) {
1104                m2 = (l * (255 + s)) / 65025.0;
1105            } else {
1106                m2 = (l + s - (l * s) / 255.0) / 255.0;
1107            }
1108            m1 = (l / 127.5) - m2;
1109
1110            hue = HLSvalue(m1, m2, h + 85);
1111            lightness = HLSvalue(m1, m2, h);
1112            saturation = HLSvalue(m1, m2, h - 85);
1113        }
1114        return new Color(hue, lightness, saturation);
1115    }
1116
1117    private int HLSvalue(double n1, double n2, double hue) {
1118        double value;
1119
1120        if (hue > 255) {
1121            hue -= 255;
1122        } else if (hue < 0) {
1123            hue += 255;
1124        }
1125
1126        if (hue < 42.5) {
1127            value = n1 + (n2 - n1) * (hue / 42.5);
1128        } else if (hue < 127.5) {
1129            value = n2;
1130        } else if (hue < 170) {
1131            value = n1 + (n2 - n1) * ((170 - hue) / 42.5);
1132        } else {
1133            value = n1;
1134        }
1135
1136        return (int)(value * 255);
1137    }
1138}
1139
Popular Tags