KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)GTKStyleFactory.java 1.29 04/03/18
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 javax.swing.plaf.synth.*;
10 import java.awt.*;
11 import java.util.*;
12 import java.util.regex.*;
13 import javax.swing.*;
14 import javax.swing.plaf.*;
15 import sun.swing.BakedArrayList;
16 import sun.swing.plaf.synth.DefaultSynthStyle;
17 import sun.swing.plaf.synth.StyleAssociation;
18
19 /**
20  * GTKStyleFactory extends DefaultSynthStyleFactory providing a mapping that
21  * mirrors the gtk name space. Styles registered for REGION are mapped to
22  * the corresponding gtk class name. Similarly styles registered for
23  * CLASS are mapped to the corresponding gtk class name, including the
24  * corresponding gtk class hierarchy.
25  *
26  * @version 1.29, 03/18/04
27  * @author Scott Violet
28  */

29 class GTKStyleFactory extends SynthStyleFactory {
30     /**
31      * Indicates lookup should be done using the name of the Component.
32      * If the name is null this fallsback to the name of the region.
33      */

34     public static final int WIDGET = 0;
35     /**
36      * Indicates lookup should be done using the region name.
37      */

38     public static final int WIDGET_CLASS = 1;
39     /**
40      * Indicates lookup should be done using the class name
41      */

42     public static final int CLASS = 2;
43
44     /**
45      * Maps from a GTK class name to its super class.
46      */

47     private static final Map GTK_CLASS_MAP;
48
49     /**
50      * Maps from Region to gtk class.
51      */

52     private static final Map REGION_MAP;
53
54     /**
55      * List of StyleAssociations for WIDGET.
56      */

57     private java.util.List JavaDoc _widgetStyles;
58
59     /**
60      * List of StyleAssociations for WIDGET_CLASS.
61      */

62     private java.util.List JavaDoc _widgetClassStyles;
63
64     /**
65      * List of StyleAssociations for CLASS.
66      */

67     private java.util.List JavaDoc _classStyles;
68
69     /**
70      * Labels are special cased. This is set to true when a Style for
71      * a label bearing widget is asked for and triggers massaging of
72      * the path and class name lookup.
73      */

74     private boolean _isLabel;
75
76
77     /**
78      * Will hold the label style and label bearing components style. This
79      * is used as the key to mergedStyleMap.
80      */

81     private BakedArrayList _labelStyleList;
82
83     /**
84      * Maps from a List containing the label style and label bearing components
85      * style to the merged style.
86      */

87     private Map _mergedStyleMap;
88
89     /**
90      * All lookups will at least get this style.
91      */

92     private SynthStyle _defaultStyle;
93
94     /**
95      * Default style for tooltips.
96      */

97     private GTKStyle _tooltipStyle;
98
99     /**
100      * Default style for progressbars.
101      */

102     private GTKStyle _pbStyle;
103
104     /**
105      * Default style for menu items.
106      */

107     private GTKStyle _menuItemStyle;
108
109     /**
110      * Maps from List to the resolved DefaultSynthStyle.
111      */

112     private Map _resolvedStyles;
113
114     /**
115      * Used for Style lookup to avoid garbage.
116      */

117     private BakedArrayList _tmpList;
118
119     /**
120      * StringBuffer used in building paths.
121      */

122     private StringBuffer JavaDoc _tmpPath;
123
124     /**
125      * Used in matching class styles, will contain the class depth of the
126      * matches.
127      */

128     private int[] _depth;
129
130
131     static {
132         REGION_MAP = new HashMap();
133         REGION_MAP.put(Region.ARROW_BUTTON, "GtkButton");
134         REGION_MAP.put(Region.BUTTON, "GtkButton");
135         REGION_MAP.put(Region.CHECK_BOX, "GtkCheckButton");
136         REGION_MAP.put(Region.CHECK_BOX_MENU_ITEM, "GtkCheckMenuItem");
137         REGION_MAP.put(Region.COLOR_CHOOSER, "GtkColorSelectionDialog");
138         REGION_MAP.put(Region.COMBO_BOX, "GtkCombo");
139         REGION_MAP.put(Region.DESKTOP_ICON, "GtkLabel");
140         REGION_MAP.put(Region.DESKTOP_PANE, "GtkContainer");
141         REGION_MAP.put(Region.EDITOR_PANE, "GtkTextView");
142         REGION_MAP.put(Region.FORMATTED_TEXT_FIELD, "GtkEntry");
143         REGION_MAP.put(GTKRegion.HANDLE_BOX, "GtkHandleBox");
144         REGION_MAP.put(Region.INTERNAL_FRAME, "GtkFrame");
145         REGION_MAP.put(Region.INTERNAL_FRAME_TITLE_PANE, "GtkLabel");
146         REGION_MAP.put(Region.LABEL, "GtkLabel");
147         REGION_MAP.put(Region.LIST, "GtkTreeView");
148         // GTK doesn't use menu's as swing does, Swing's menus better
149
// map to a GTKMenuItem.
150
REGION_MAP.put(Region.MENU, "GtkMenuItem");
151         REGION_MAP.put(Region.MENU_BAR, "GtkMenuBar");
152         REGION_MAP.put(Region.MENU_ITEM, "GtkMenuItem");
153         REGION_MAP.put(Region.MENU_ITEM_ACCELERATOR, "GtkLabel");
154         REGION_MAP.put(Region.OPTION_PANE, "GtkMessageDialog");
155         REGION_MAP.put(Region.PANEL, "GtkContainer");
156         REGION_MAP.put(Region.PASSWORD_FIELD, "GtkEntry");
157         // GTK does not have a distinct class for popups.
158
REGION_MAP.put(Region.POPUP_MENU, "GtkMenu");
159         REGION_MAP.put(Region.POPUP_MENU_SEPARATOR, "GtkSeparatorMenuItem");
160         REGION_MAP.put(Region.PROGRESS_BAR, "GtkProgressBar");
161         REGION_MAP.put(Region.RADIO_BUTTON, "GtkRadioButton");
162         REGION_MAP.put(Region.RADIO_BUTTON_MENU_ITEM, "GtkRadioMenuItem");
163         REGION_MAP.put(Region.ROOT_PANE, "GtkContainer");
164         // GTK has two subclasses for the two directions.
165
REGION_MAP.put(Region.SCROLL_BAR, "GtkScrollbar");
166         REGION_MAP.put(Region.SCROLL_BAR_TRACK, "GtkScrollbar");
167         REGION_MAP.put(Region.SCROLL_BAR_THUMB, "GtkScrollbar");
168         REGION_MAP.put(Region.SCROLL_PANE, "GtkScrolledWindow");
169         // GTK has two subclasses of GtkSeparator for the two directions
170
REGION_MAP.put(Region.SEPARATOR, "GtkSeparator");
171         // GTK has two subclasses of GtkScale for the two directions
172
REGION_MAP.put(Region.SLIDER, "GtkScale");
173         REGION_MAP.put(Region.SLIDER_TRACK, "GtkScale");
174         REGION_MAP.put(Region.SLIDER_THUMB, "GtkScale");
175         REGION_MAP.put(Region.SPINNER, "GtkSpinButton");
176         // GTK has two subclasses of GtkPaned for the two diretions.
177
REGION_MAP.put(Region.SPLIT_PANE, "GtkPaned");
178         REGION_MAP.put(Region.SPLIT_PANE_DIVIDER, "GtkPaned");
179         REGION_MAP.put(Region.TABBED_PANE, "GtkNotebook");
180         REGION_MAP.put(Region.TABBED_PANE_TAB_AREA, "GtkNotebook");
181         REGION_MAP.put(Region.TABBED_PANE_CONTENT, "GtkNotebook");
182         REGION_MAP.put(Region.TABBED_PANE_TAB, "GtkNotebook");
183         REGION_MAP.put(Region.TABLE, "GtkTreeView");
184         // It would appear the headers are drawn as buttons.
185
REGION_MAP.put(Region.TABLE_HEADER, "GtkButton");
186         REGION_MAP.put(Region.TEXT_AREA, "GtkTextView");
187         REGION_MAP.put(Region.TEXT_FIELD, "GtkEntry");
188         REGION_MAP.put(Region.TEXT_PANE, "GtkTextView");
189         REGION_MAP.put(Region.TOGGLE_BUTTON, "GtkToggleButton");
190         REGION_MAP.put(Region.TOOL_BAR, "GtkToolbar");
191         REGION_MAP.put(Region.TOOL_BAR_DRAG_WINDOW, "GtkToolbar");
192         // GTK does not define a distinct class for the toolbar separator
193
REGION_MAP.put(Region.TOOL_BAR_SEPARATOR, "GtkSeparator");
194         REGION_MAP.put(Region.TOOL_TIP, "GtkWindow");
195         REGION_MAP.put(Region.TREE, "GtkTreeView");
196         REGION_MAP.put(Region.TREE_CELL, "GtkTreeView");
197         REGION_MAP.put(Region.VIEWPORT, "GtkViewport");
198
199
200         GTK_CLASS_MAP = new HashMap();
201         GTK_CLASS_MAP.put("GtkHandleBox", "GtkBin");
202         GTK_CLASS_MAP.put("GtkFrame", "GtkBin");
203         GTK_CLASS_MAP.put("GtkProgress", "GtkWidget");
204         GTK_CLASS_MAP.put("GtkViewport", "GtkBin");
205         GTK_CLASS_MAP.put("GtkMessageDialog", "GtkDialog");
206         GTK_CLASS_MAP.put("GtkCombo", "GtkHBox");
207         GTK_CLASS_MAP.put("GtkHBox", "GtkBox");
208         GTK_CLASS_MAP.put("GtkBox", "GtkContainer");
209         GTK_CLASS_MAP.put("GtkTooltips", "GtkObject");
210         GTK_CLASS_MAP.put("GtkToolbar", "GtkContainer");
211         GTK_CLASS_MAP.put("GtkLabel", "GtkMisc");
212         GTK_CLASS_MAP.put("GtkMisc", "GtkWidget");
213         GTK_CLASS_MAP.put("GtkTreeView", "GtkContainer");
214         GTK_CLASS_MAP.put("GtkTextView", "GtkContainer");
215         GTK_CLASS_MAP.put("GtkNotebook", "GtkContainer");
216         GTK_CLASS_MAP.put("GtkSeparatorMenuItem", "GtkMenuItem");
217         GTK_CLASS_MAP.put("GtkSpinButton", "GtkEntry");
218         GTK_CLASS_MAP.put("GtkSeparator", "GtkWidget");
219         GTK_CLASS_MAP.put("GtkScale", "GtkRange");
220         GTK_CLASS_MAP.put("GtkRange", "GtkWidget");
221         GTK_CLASS_MAP.put("GtkPaned", "GtkContainer");
222         GTK_CLASS_MAP.put("GtkScrolledWindow", "GtkBin");
223         GTK_CLASS_MAP.put("GtkScrollbar", "GtkRange");
224         GTK_CLASS_MAP.put("GtkProgressBar", "GtkProgress");
225         GTK_CLASS_MAP.put("GtkRadioButton", "GtkCheckButton");
226         GTK_CLASS_MAP.put("GtkRadioMenuItem", "GtkCheckMenuItem");
227         GTK_CLASS_MAP.put("GtkCheckMenuItem", "GtkMenuItem");
228         GTK_CLASS_MAP.put("GtkMenuItem", "GtkItem");
229         GTK_CLASS_MAP.put("GtkItem", "GtkBin");
230         GTK_CLASS_MAP.put("GtkMenu", "GtkMenuShell");
231         GTK_CLASS_MAP.put("GtkMenuBar", "GtkMenuShell");
232         GTK_CLASS_MAP.put("GtkMenuShell", "GtkContainer");
233         GTK_CLASS_MAP.put("GtkEntry", "GtkWidget");
234         GTK_CLASS_MAP.put("GtkColorSelectionDialog", "GtkDialog");
235         GTK_CLASS_MAP.put("GtkDialog", "GtkWindow");
236         GTK_CLASS_MAP.put("GtkWindow", "GtkBin");
237         GTK_CLASS_MAP.put("GtkCheckButton", "GtkToggleButton");
238         GTK_CLASS_MAP.put("GtkToggleButton", "GtkButton");
239         GTK_CLASS_MAP.put("GtkButton", "GtkBin");
240         GTK_CLASS_MAP.put("GtkBin", "GtkContainer");
241         GTK_CLASS_MAP.put("GtkContainer", "GtkWidget");
242         GTK_CLASS_MAP.put("GtkWidget", "GtkObject");
243         GTK_CLASS_MAP.put("GtkObject", "GObject");
244     }
245
246     /**
247      * In GTK Button and other widgets that display text are actually
248      * implemented as two separate widgets, one for the text and one for
249      * the button, this method returns true if in GTK the Region would
250      * contain a Label to draw the text.
251      */

252     static final boolean isLabelBearing(Region id) {
253         return (id == Region.BUTTON || id == Region.CHECK_BOX ||
254                 id == Region.CHECK_BOX_MENU_ITEM || id == Region.MENU ||
255                 id == Region.MENU_ITEM || id == Region.RADIO_BUTTON ||
256                 id == Region.RADIO_BUTTON_MENU_ITEM ||
257                 id == Region.TABBED_PANE_TAB ||
258                 id == Region.TOGGLE_BUTTON || id == Region.TOOL_TIP);
259     }
260
261     /**
262      * Returns the gtk class that corresponds to the passed in region.
263      */

264     static String JavaDoc gtkClassFor(Region region) {
265         String JavaDoc name = (String JavaDoc)REGION_MAP.get(region);
266
267         if (name == null) {
268             // There are no GTK equivalents for some GTK classes, force
269
// a match.
270
return "XXX";
271         }
272         return name;
273     }
274
275     /**
276      * Returns the super class of the passed in gtk class, or null if
277      * <code>gtkClass</code> is the root class.
278      */

279     static String JavaDoc gtkSuperclass(String JavaDoc gtkClass) {
280         return (String JavaDoc)GTK_CLASS_MAP.get(gtkClass);
281     }
282
283     GTKStyleFactory() {
284         this(null);
285     }
286
287     GTKStyleFactory(GTKStyle baseStyle) {
288         _tmpList = new BakedArrayList(5);
289         _resolvedStyles = new HashMap();
290         _tmpPath = new StringBuffer JavaDoc();
291         _mergedStyleMap = new HashMap();
292         _defaultStyle = (baseStyle == null ? new GTKStyle() : baseStyle);
293         _labelStyleList = new BakedArrayList(2);
294     }
295
296     public synchronized void addStyle(DefaultSynthStyle style,
297                          String JavaDoc path, int type) throws PatternSyntaxException {
298         // GTK only supports * and ?, escape everything else.
299
int length = path.length();
300         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(length * 2);
301         for (int counter = 0; counter < length; counter++) {
302             char aChar = path.charAt(counter);
303
304             if (aChar == '*') {
305                 buffer.append(".*");
306             }
307             else if (aChar == '?') {
308                 buffer.append('.');
309             }
310             else if (Character.isLetterOrDigit(aChar)) {
311                 buffer.append(aChar);
312             }
313             else {
314                 buffer.append('\\');
315                 buffer.append(aChar);
316             }
317         }
318         path = buffer.toString();
319
320         switch (type) {
321         case WIDGET:
322             if (_widgetStyles == null) {
323                 _widgetStyles = new ArrayList(1);
324             }
325             _widgetStyles.add(StyleAssociation.createStyleAssociation(
326                                   path, style));
327             break;
328         case WIDGET_CLASS:
329             if (_widgetClassStyles == null) {
330                 _widgetClassStyles = new ArrayList(1);
331             }
332             _widgetClassStyles.add(StyleAssociation.createStyleAssociation(
333                                        path, style));
334             break;
335         case CLASS:
336             if (_classStyles == null) {
337                 _classStyles = new ArrayList(1);
338             }
339             _classStyles.add(StyleAssociation.createStyleAssociation(
340                                  path, style));
341             break;
342         default:
343             throw new IllegalArgumentException JavaDoc("type must be one of " +
344                                               "CLASS, WIDGET_CLASS or WIDGET");
345         }
346     }
347
348     /**
349      * Returns the <code>SynthStyle</code> to use based on the
350      * class name of a GtkWidget. This will throw an
351      * <code>IllegalArgumentException</code> if
352      * <code>gtkWidgetClassName</code> is not a valid Gtk class name.
353      *
354      * @param gtkWidget Class name of a GtkWidget.
355      * @throws IllegalArgumentException if <code>gtkWidgetClassName</code> is
356      * not a valid class name.
357      */

358     synchronized SynthStyle getStyle(String JavaDoc gtkWidgetClassName)
359                       throws IllegalArgumentException JavaDoc {
360         if (!GTK_CLASS_MAP.containsKey(gtkWidgetClassName)) {
361             throw new IllegalArgumentException JavaDoc("Invalid class name: " +
362                                                gtkWidgetClassName);
363         }
364         BakedArrayList matches = _tmpList;
365
366         matches.clear();
367         if (_classStyles != null) {
368             getClassMatches(matches, gtkWidgetClassName);
369         }
370         matches.add(_defaultStyle);
371
372         return getStyle(matches);
373     }
374
375     /**
376      * Returns the style for the specified Component.
377      *
378      * @param c Component asking for
379      * @param id ID of the Component
380      */

381     public synchronized SynthStyle getStyle(JComponent c, Region id) {
382         if ((id == Region.FORMATTED_TEXT_FIELD &&
383                c.getName() == "Spinner.formattedTextField") ||
384                (id == Region.ARROW_BUTTON &&
385                 (c.getName() == "Spinner.previousButton" ||
386                  c.getName() == "Spinner.nextButton"))){
387             // Force all the widgets of a spinner to be treated like a spinner
388
id = Region.SPINNER;
389             Container parent = c.getParent();
390             if (parent != null) {
391                 parent = parent.getParent();
392                 if (parent instanceof JSpinner) {
393                     c = (JComponent)parent;
394                 }
395             }
396         }
397         else if (id == Region.LABEL && c.getName() == "ComboBox.renderer") {
398             id = Region.TEXT_FIELD;
399         }
400         SynthStyle style = _getStyle(c, id);
401
402         if (isLabelBearing(id)) {
403             style = getMergedStyle(c, id, style);
404         }
405         return style;
406     }
407
408     private SynthStyle _getStyle(JComponent c, Region id) {
409         BakedArrayList matches = _tmpList;
410
411         matches.clear();
412         getMatchingStyles(matches, c, id);
413
414         return getStyle(matches);
415     }
416
417     private SynthStyle getStyle(BakedArrayList matches) {
418         // Use a cached Style if possible, otherwise create a new one.
419
matches.cacheHashCode();
420         SynthStyle style = getCachedStyle(matches);
421
422         if (style == null) {
423             style = mergeStyles(matches);
424
425             if (style != null) {
426                 cacheStyle(matches, style);
427             }
428         }
429         return style;
430     }
431
432     /**
433      * Fetches any styles that match the passed into arguments into
434      * <code>matches</code>.
435      */

436     private void getMatchingStyles(java.util.List JavaDoc matches, JComponent c,
437                                    Region id) {
438         // TableHeaderer.renderer is special cased as it descends from
439
// DefaultTableCellRenderer which does NOT pass along the property
440
// change that would trigger the style to be refetched.
441
if (c != null && (c.getParent() != null ||
442                           c.getName() == "TableHeader.renderer" ||
443                           c.getName() == "Slider.label") ||
444                           c.getName() == "ComboBox.list") {
445             // First match on WIDGET
446
if (_widgetStyles != null) {
447                 getMatches(getPath(WIDGET, c, id), _widgetStyles, matches, c,
448                            id);
449             }
450             // Then match on WIDGET_CLASS
451
if (_widgetClassStyles != null) {
452                 getMatches(getPath(WIDGET_CLASS, c, id), _widgetClassStyles,
453                            matches, c, id);
454             }
455             // Lastly match on CLASS
456
if (_classStyles != null) {
457                 getClassMatches(matches, c, id);
458             }
459         }
460         if (id == Region.TOOL_TIP) {
461             matches.add(getToolTipStyle());
462         }
463         else if (id == Region.PROGRESS_BAR && GTKLookAndFeel.is2_2()) {
464             matches.add(getProgressBarStyle());
465         }
466         else if ((id == Region.MENU || id == Region.MENU_ITEM ||
467                   id == Region.POPUP_MENU_SEPARATOR ||
468                   id == Region.CHECK_BOX_MENU_ITEM ||
469                   id == Region.RADIO_BUTTON_MENU_ITEM ||
470                   id == Region.MENU_ITEM_ACCELERATOR) &&
471                  GTKLookAndFeel.is2_2()) {
472             matches.add(getMenuItemStyle());
473         }
474         matches.add(_defaultStyle);
475     }
476
477     private void getMatches(CharSequence JavaDoc path, java.util.List JavaDoc styles,
478                             java.util.List JavaDoc matches, JComponent c, Region id) {
479         for (int counter = styles.size() - 1; counter >= 0; counter--){
480             StyleAssociation sa = (StyleAssociation)styles.get(counter);
481
482             if (sa.matches(path) && matches.indexOf(sa.getStyle()) == -1) {
483                 matches.add(sa.getStyle());
484             }
485         }
486     }
487
488     private void getClassMatches(java.util.List JavaDoc matches, JComponent c,
489                                  Region id) {
490         getClassMatches(matches, getClass(c, id));
491     }
492
493     private void getClassMatches(java.util.List JavaDoc matches, Object JavaDoc gtkClassName){
494         if (_depth == null) {
495             _depth = new int[4];
496         }
497         int[] sDepth = _depth;
498         int matched = 0;
499         int startMatchLength = matches.size();
500
501         for (int counter = _classStyles.size() - 1; counter >= 0; counter--){
502             StyleAssociation sa = (StyleAssociation)_classStyles.get(counter);
503             Object JavaDoc klass = gtkClassName;
504
505             while (klass != null) {
506                 if (sa.matches(getClassName(klass))) {
507                     int depth = 0;
508                     while ((klass = getSuperclass(klass)) != null) {
509                         depth++;
510                     }
511                     if (matched == 0) {
512                         sDepth[0] = depth;
513                         matches.add(sa.getStyle());
514                     }
515                     else {
516                         int sCounter = 0;
517                         while (sCounter < matched && depth < sDepth[sCounter]){
518                             sCounter++;
519                         }
520                         matches.add(sCounter + startMatchLength,
521                                        sa.getStyle());
522                         if (matched + 1 == sDepth.length) {
523                             int[] newDepth = new int[sDepth.length * 2];
524                             System.arraycopy(sDepth, 0, newDepth, 0,
525                                              sDepth.length);
526                             _depth = newDepth;
527                             sDepth = newDepth;
528                         }
529                         if (sCounter < matched) {
530                             System.arraycopy(sDepth, 0, sDepth, 0, sCounter);
531                             System.arraycopy(sDepth, sCounter, sDepth,
532                                              sCounter + 1, matched - sCounter);
533                         }
534                         sDepth[sCounter] = depth;
535                     }
536                     matched++;
537                     break;
538                 }
539                 klass = getSuperclass(klass);
540             }
541         }
542     }
543
544
545     /**
546      * Caches the specified style.
547      */

548     private void cacheStyle(java.util.List JavaDoc styles, SynthStyle style) {
549         BakedArrayList cachedStyles = new BakedArrayList(styles);
550
551         _resolvedStyles.put(cachedStyles, style);
552     }
553
554     /**
555      * Returns the cached style from the passed in arguments.
556      */

557     private SynthStyle getCachedStyle(java.util.List JavaDoc styles) {
558         if (styles.size() == 0) {
559             return null;
560         }
561         return (SynthStyle)_resolvedStyles.get(styles);
562     }
563
564     /**
565      * Creates a single Style from the passed in styles. The passed in List
566      * is reverse sorted, that is the most recently added style found to
567      * match will be first.
568      */

569     private SynthStyle mergeStyles(java.util.List JavaDoc styles) {
570         int size = styles.size();
571
572         if (size == 0) {
573             return null;
574         }
575         else if (size == 1) {
576             return (SynthStyle)((DefaultSynthStyle)styles.get(0)).clone();
577         }
578         // NOTE: merging is done backwards as DefaultSynthStyleFactory reverses
579
// order, that is, the most specific style is first.
580
DefaultSynthStyle style = (DefaultSynthStyle)styles.get(size - 1);
581
582         style = (DefaultSynthStyle)style.clone();
583         for (int counter = size - 2; counter >= 0; counter--) {
584             style = ((DefaultSynthStyle)styles.get(counter)).addTo(style);
585         }
586         return style;
587     }
588
589     /**
590      * Builds the path returning a CharSequence describing the path. A
591      * temporary StringBuffer is provided that should NOT be cached.
592      */

593     private CharSequence JavaDoc getPath(int type, Component c, Region id) {
594         _tmpPath.setLength(0);
595
596         if (type == WIDGET && id == Region.TOOL_TIP) {
597             if (c.getName() == null) {
598                 _tmpPath.append("gtk-tooltips");
599             }
600             else {
601                 _tmpPath.append(c.getName());
602             }
603         }
604         else {
605             _getPath(_tmpPath, type, c, id);
606         }
607
608         if (_isLabel) {
609             if (_tmpPath.length() > 0) {
610                 _tmpPath.append('.');
611             }
612             _tmpPath.append(getName(c, Region.LABEL));
613         }
614         return _tmpPath;
615     }
616
617     private void _getPath(StringBuffer JavaDoc path, int type, Component c,Region id) {
618         if (c instanceof JComponent) {
619             boolean isSubregion = (id != null && id.isSubregion());
620
621             if (isSubregion) {
622                 _getPath(path, type, c, null);
623             }
624             else {
625                 _getPath(path, type, c.getParent(), id);
626             }
627             String JavaDoc key = null;
628
629             if (type == WIDGET && !isSubregion) {
630                 key = c.getName();
631             }
632             if (key == null) {
633                 if (isSubregion) {
634                     key = getName(c, id);
635                 }
636                 else {
637                     Region region = SynthLookAndFeel.getRegion((JComponent)c);
638
639                     if (region != null) {
640                         key = getName(c, region);
641                     }
642                 }
643             }
644             if (path.length() > 0) {
645                 path.append('.');
646             }
647             path.append(key);
648         }
649     }
650
651
652     /**
653      * Returns a class identifer for <code>c</code>.
654      */

655     protected Object JavaDoc getClass(JComponent c, Region id) {
656         if (_isLabel) {
657             id = Region.LABEL;
658         }
659         else if (id == Region.ROOT_PANE) {
660             Object JavaDoc name = getRootPaneParentType(c);
661
662             if (name != null) {
663                 return name;
664             }
665         }
666         String JavaDoc klass = gtkClassFor(id);
667         if (klass == "GtkLabel") {
668             if (c.getName() == "TableHeader.renderer") {
669                 return "GtkButton";
670             }
671         }
672         return klass;
673     }
674
675     private SynthStyle getMergedStyle(JComponent c, Region id,
676                                       SynthStyle style) {
677         SynthStyle labelStyle;
678         try {
679             _isLabel = true;
680             labelStyle = (GTKStyle)_getStyle(c, id);
681         } finally {
682             _isLabel = false;
683         }
684         _labelStyleList.clear();
685         _labelStyleList.add(style);
686         _labelStyleList.add(labelStyle);
687         _labelStyleList.cacheHashCode();
688
689         GTKStyle mergedStyle = (GTKStyle)_mergedStyleMap.get(_labelStyleList);
690
691         if (mergedStyle == null) {
692             mergedStyle = (GTKStyle)((DefaultSynthStyle)style).clone();
693             mergedStyle.addLabelProperties((GTKStyle)labelStyle);
694             _mergedStyleMap.put(_labelStyleList, mergedStyle);
695             _labelStyleList = new BakedArrayList(2);
696         }
697         return mergedStyle;
698     }
699
700     /**
701      * Returns the super class of a klass as returned from
702      * <code>getClass</code>, or null if <code>klass</code> has no
703      * super classes.
704      */

705     private Object JavaDoc getSuperclass(Object JavaDoc klass) {
706         return gtkSuperclass((String JavaDoc)klass);
707     }
708
709     /**
710      * Returns the name of a class returned from <code>getClass</code>.
711      */

712     private String JavaDoc getClassName(Object JavaDoc klass) {
713         return (String JavaDoc)klass;
714     }
715
716     /**
717      * Returns the name of the Region.
718      */

719     private String JavaDoc getName(Component c, Region region) {
720         if (region == Region.ROOT_PANE && c != null) {
721             String JavaDoc name = getRootPaneParentType(c);
722
723             if (name != null) {
724                 return name;
725             }
726         }
727         return gtkClassFor(region);
728     }
729
730     private String JavaDoc getRootPaneParentType(Component c) {
731         Component parent = c.getParent();
732
733         if (parent instanceof Frame) {
734             return "GtkWindow";
735         }
736         else if (parent instanceof Dialog) {
737             return "GtkDialog";
738         }
739         else if (parent instanceof Window) {
740             return "GtkWindow";
741         }
742         else if (parent instanceof JInternalFrame) {
743             return "GtkFrame";
744         }
745         return null;
746     }
747
748     private GTKStyle getProgressBarStyle() {
749         if (_pbStyle == null) {
750             Color[] moColors = new Color[GTKColorType.MAX_COUNT];
751             Color[] normalColors = new Color[GTKColorType.MAX_COUNT];
752             moColors[GTKColorType.BACKGROUND.getID()] = new ColorUIResource(
753                 0x4B6983);
754             normalColors[GTKColorType.BACKGROUND.getID()] =
755                   new ColorUIResource(0xBAB5AB);
756             _pbStyle = new GTKStyle(new GTKStyle.GTKStateInfo[]
757                 { new GTKStyle.GTKStateInfo(SynthConstants.ENABLED,
758                                             null, normalColors, null),
759                   new GTKStyle.GTKStateInfo(SynthConstants.MOUSE_OVER,
760                                             null, moColors, null)
761                 }, null, null, GTKStyle.UNDEFINED_THICKNESS,
762                 GTKStyle.UNDEFINED_THICKNESS, null);
763         }
764         return _pbStyle;
765     }
766
767     private GTKStyle getMenuItemStyle() {
768         if (_menuItemStyle == null) {
769             Color[] moColors = new Color[GTKColorType.MAX_COUNT];
770             Color[] selectedColors = new Color[GTKColorType.MAX_COUNT];
771             moColors[GTKColorType.BACKGROUND.getID()] = new ColorUIResource(
772                 0x9db8d2);
773             moColors[GTKColorType.FOREGROUND.getID()] = GTKStyle.WHITE_COLOR;
774             moColors[GTKColorType.TEXT_FOREGROUND.getID()] =
775                                   new ColorUIResource(0xFFFFFF);
776             selectedColors[GTKColorType.TEXT_FOREGROUND.getID()] =
777                   new ColorUIResource(0xFFFFFF);
778             _menuItemStyle = new GTKStyle(new GTKStyle.GTKStateInfo[]
779                 {
780                   new GTKStyle.GTKStateInfo(SynthConstants.MOUSE_OVER,
781                                             null, moColors, null),
782                   new GTKStyle.GTKStateInfo(SynthConstants.SELECTED,
783                                             null, selectedColors, null),
784                 }, null, null, GTKStyle.UNDEFINED_THICKNESS,
785                 GTKStyle.UNDEFINED_THICKNESS, null);
786         }
787         return _menuItemStyle;
788     }
789
790     private GTKStyle getToolTipStyle() {
791         if (_tooltipStyle == null) {
792             Color[] ttColors = new Color[GTKColorType.MAX_COUNT];
793             if (GTKLookAndFeel.is2_2()) {
794                 ttColors[GTKColorType.BACKGROUND.getID()] =
795                                  new ColorUIResource(0xEEE1B3);
796                 ttColors[GTKColorType.FOREGROUND.getID()] =
797                                  new ColorUIResource(0x000000);
798             }
799             else {
800                 ttColors[GTKColorType.BACKGROUND.getID()] =
801                                  new ColorUIResource(0xFFFFC0);
802                 ttColors[GTKColorType.FOREGROUND.getID()] =
803                                  new ColorUIResource(0x000000);
804             }
805             _tooltipStyle = new GTKStyle(new GTKStyle.GTKStateInfo[] {
806                 new GTKStyle.GTKStateInfo(SynthConstants.ENABLED,
807                 null, ttColors, null)}, null, null,
808                 GTKStyle.UNDEFINED_THICKNESS, GTKStyle.UNDEFINED_THICKNESS,
809                 null);
810         }
811         return _tooltipStyle;
812     }
813 }
814
Popular Tags