View Javadoc
1   /*
2    * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  package javax.swing.plaf.synth;
26  
27  import java.awt.*;
28  import javax.swing.*;
29  import javax.swing.border.Border;
30  import javax.swing.plaf.UIResource;
31  import javax.swing.plaf.basic.BasicLookAndFeel;
32  import javax.swing.text.DefaultEditorKit;
33  import java.util.HashMap;
34  import java.util.Map;
35  import javax.swing.text.JTextComponent;
36  
37  /**
38   * <code>SynthStyle</code> is a set of style properties.
39   * Each <code>SynthUI</code> references at least one
40   * <code>SynthStyle</code> that is obtained using a
41   * <code>SynthStyleFactory</code>. You typically don't need to interact with
42   * this class directly, rather you will load a
43   * <a href="doc-files/synthFileFormat.html">Synth File Format file</a> into
44   * <code>SynthLookAndFeel</code> that will create a set of SynthStyles.
45   *
46   * @see SynthLookAndFeel
47   * @see SynthStyleFactory
48   *
49   * @since 1.5
50   * @author Scott Violet
51   */
52  public abstract class SynthStyle {
53      /**
54       * Contains the default values for certain properties.
55       */
56      private static Map<Object, Object> DEFAULT_VALUES;
57  
58      /**
59       * Shared SynthGraphics.
60       */
61      private static final SynthGraphicsUtils SYNTH_GRAPHICS =
62                                new SynthGraphicsUtils();
63  
64      /**
65       * Adds the default values that we know about to DEFAULT_VALUES.
66       */
67      private static void populateDefaultValues() {
68          Object buttonMap = new UIDefaults.LazyInputMap(new Object[] {
69                            "SPACE", "pressed",
70                   "released SPACE", "released"
71          });
72          DEFAULT_VALUES.put("Button.focusInputMap", buttonMap);
73          DEFAULT_VALUES.put("CheckBox.focusInputMap", buttonMap);
74          DEFAULT_VALUES.put("RadioButton.focusInputMap", buttonMap);
75          DEFAULT_VALUES.put("ToggleButton.focusInputMap", buttonMap);
76          DEFAULT_VALUES.put("SynthArrowButton.focusInputMap", buttonMap);
77          DEFAULT_VALUES.put("List.dropLineColor", Color.BLACK);
78          DEFAULT_VALUES.put("Tree.dropLineColor", Color.BLACK);
79          DEFAULT_VALUES.put("Table.dropLineColor", Color.BLACK);
80          DEFAULT_VALUES.put("Table.dropLineShortColor", Color.RED);
81  
82          Object multilineInputMap = new UIDefaults.LazyInputMap(new Object[] {
83                             "ctrl C", DefaultEditorKit.copyAction,
84                             "ctrl V", DefaultEditorKit.pasteAction,
85                             "ctrl X", DefaultEditorKit.cutAction,
86                               "COPY", DefaultEditorKit.copyAction,
87                              "PASTE", DefaultEditorKit.pasteAction,
88                                "CUT", DefaultEditorKit.cutAction,
89                     "control INSERT", DefaultEditorKit.copyAction,
90                       "shift INSERT", DefaultEditorKit.pasteAction,
91                       "shift DELETE", DefaultEditorKit.cutAction,
92                         "shift LEFT", DefaultEditorKit.selectionBackwardAction,
93                      "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
94                        "shift RIGHT", DefaultEditorKit.selectionForwardAction,
95                     "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
96                          "ctrl LEFT", DefaultEditorKit.previousWordAction,
97                       "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
98                         "ctrl RIGHT", DefaultEditorKit.nextWordAction,
99                      "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
100                   "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
101                "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
102                  "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
103               "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
104                            "ctrl A", DefaultEditorKit.selectAllAction,
105                              "HOME", DefaultEditorKit.beginLineAction,
106                               "END", DefaultEditorKit.endLineAction,
107                        "shift HOME", DefaultEditorKit.selectionBeginLineAction,
108                         "shift END", DefaultEditorKit.selectionEndLineAction,
109 
110                                "UP", DefaultEditorKit.upAction,
111                             "KP_UP", DefaultEditorKit.upAction,
112                              "DOWN", DefaultEditorKit.downAction,
113                           "KP_DOWN", DefaultEditorKit.downAction,
114                           "PAGE_UP", DefaultEditorKit.pageUpAction,
115                         "PAGE_DOWN", DefaultEditorKit.pageDownAction,
116                     "shift PAGE_UP", "selection-page-up",
117                   "shift PAGE_DOWN", "selection-page-down",
118                "ctrl shift PAGE_UP", "selection-page-left",
119              "ctrl shift PAGE_DOWN", "selection-page-right",
120                          "shift UP", DefaultEditorKit.selectionUpAction,
121                       "shift KP_UP", DefaultEditorKit.selectionUpAction,
122                        "shift DOWN", DefaultEditorKit.selectionDownAction,
123                     "shift KP_DOWN", DefaultEditorKit.selectionDownAction,
124                             "ENTER", DefaultEditorKit.insertBreakAction,
125                        "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
126                  "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
127                            "ctrl H", DefaultEditorKit.deletePrevCharAction,
128                            "DELETE", DefaultEditorKit.deleteNextCharAction,
129                       "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
130                   "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
131                             "RIGHT", DefaultEditorKit.forwardAction,
132                              "LEFT", DefaultEditorKit.backwardAction,
133                          "KP_RIGHT", DefaultEditorKit.forwardAction,
134                           "KP_LEFT", DefaultEditorKit.backwardAction,
135                               "TAB", DefaultEditorKit.insertTabAction,
136                   "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
137                         "ctrl HOME", DefaultEditorKit.beginAction,
138                          "ctrl END", DefaultEditorKit.endAction,
139                   "ctrl shift HOME", DefaultEditorKit.selectionBeginAction,
140                    "ctrl shift END", DefaultEditorKit.selectionEndAction,
141                            "ctrl T", "next-link-action",
142                      "ctrl shift T", "previous-link-action",
143                        "ctrl SPACE", "activate-link-action",
144                    "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
145         });
146         DEFAULT_VALUES.put("EditorPane.focusInputMap", multilineInputMap);
147         DEFAULT_VALUES.put("TextArea.focusInputMap", multilineInputMap);
148         DEFAULT_VALUES.put("TextPane.focusInputMap", multilineInputMap);
149 
150         Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[] {
151                            "ctrl C", DefaultEditorKit.copyAction,
152                            "ctrl V", DefaultEditorKit.pasteAction,
153                            "ctrl X", DefaultEditorKit.cutAction,
154                              "COPY", DefaultEditorKit.copyAction,
155                             "PASTE", DefaultEditorKit.pasteAction,
156                               "CUT", DefaultEditorKit.cutAction,
157                    "control INSERT", DefaultEditorKit.copyAction,
158                      "shift INSERT", DefaultEditorKit.pasteAction,
159                      "shift DELETE", DefaultEditorKit.cutAction,
160                        "shift LEFT", DefaultEditorKit.selectionBackwardAction,
161                     "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
162                       "shift RIGHT", DefaultEditorKit.selectionForwardAction,
163                    "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
164                         "ctrl LEFT", DefaultEditorKit.previousWordAction,
165                      "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
166                        "ctrl RIGHT", DefaultEditorKit.nextWordAction,
167                     "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
168                   "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
169                "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
170                  "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
171               "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
172                            "ctrl A", DefaultEditorKit.selectAllAction,
173                              "HOME", DefaultEditorKit.beginLineAction,
174                               "END", DefaultEditorKit.endLineAction,
175                        "shift HOME", DefaultEditorKit.selectionBeginLineAction,
176                         "shift END", DefaultEditorKit.selectionEndLineAction,
177                        "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
178                  "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
179                            "ctrl H", DefaultEditorKit.deletePrevCharAction,
180                            "DELETE", DefaultEditorKit.deleteNextCharAction,
181                       "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
182                   "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
183                             "RIGHT", DefaultEditorKit.forwardAction,
184                              "LEFT", DefaultEditorKit.backwardAction,
185                          "KP_RIGHT", DefaultEditorKit.forwardAction,
186                           "KP_LEFT", DefaultEditorKit.backwardAction,
187                             "ENTER", JTextField.notifyAction,
188                   "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
189                    "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
190         });
191         DEFAULT_VALUES.put("TextField.focusInputMap", fieldInputMap);
192         DEFAULT_VALUES.put("PasswordField.focusInputMap", fieldInputMap);
193 
194 
195         DEFAULT_VALUES.put("ComboBox.ancestorInputMap",
196                   new UIDefaults.LazyInputMap(new Object[] {
197                      "ESCAPE", "hidePopup",
198                     "PAGE_UP", "pageUpPassThrough",
199                   "PAGE_DOWN", "pageDownPassThrough",
200                        "HOME", "homePassThrough",
201                         "END", "endPassThrough",
202                        "DOWN", "selectNext",
203                     "KP_DOWN", "selectNext",
204                    "alt DOWN", "togglePopup",
205                 "alt KP_DOWN", "togglePopup",
206                      "alt UP", "togglePopup",
207                   "alt KP_UP", "togglePopup",
208                       "SPACE", "spacePopup",
209                      "ENTER", "enterPressed",
210                          "UP", "selectPrevious",
211                       "KP_UP", "selectPrevious"
212                   }));
213 
214         DEFAULT_VALUES.put("Desktop.ancestorInputMap",
215                new UIDefaults.LazyInputMap(new Object[] {
216                  "ctrl F5", "restore",
217                  "ctrl F4", "close",
218                  "ctrl F7", "move",
219                  "ctrl F8", "resize",
220                    "RIGHT", "right",
221                 "KP_RIGHT", "right",
222              "shift RIGHT", "shrinkRight",
223           "shift KP_RIGHT", "shrinkRight",
224                     "LEFT", "left",
225                  "KP_LEFT", "left",
226               "shift LEFT", "shrinkLeft",
227            "shift KP_LEFT", "shrinkLeft",
228                       "UP", "up",
229                    "KP_UP", "up",
230                 "shift UP", "shrinkUp",
231              "shift KP_UP", "shrinkUp",
232                     "DOWN", "down",
233                  "KP_DOWN", "down",
234               "shift DOWN", "shrinkDown",
235            "shift KP_DOWN", "shrinkDown",
236                   "ESCAPE", "escape",
237                  "ctrl F9", "minimize",
238                 "ctrl F10", "maximize",
239                  "ctrl F6", "selectNextFrame",
240                 "ctrl TAB", "selectNextFrame",
241              "ctrl alt F6", "selectNextFrame",
242        "shift ctrl alt F6", "selectPreviousFrame",
243                 "ctrl F12", "navigateNext",
244            "shift ctrl F12", "navigatePrevious"
245                }));
246 
247         DEFAULT_VALUES.put("FileChooser.ancestorInputMap",
248                new UIDefaults.LazyInputMap(new Object[] {
249                      "ESCAPE", "cancelSelection",
250                      "F2", "editFileName",
251                      "F5", "refresh",
252                      "BACK_SPACE", "Go Up",
253                      "ENTER", "approveSelection",
254                 "ctrl ENTER", "approveSelection"
255                }));
256 
257         DEFAULT_VALUES.put("FormattedTextField.focusInputMap",
258               new UIDefaults.LazyInputMap(new Object[] {
259                            "ctrl C", DefaultEditorKit.copyAction,
260                            "ctrl V", DefaultEditorKit.pasteAction,
261                            "ctrl X", DefaultEditorKit.cutAction,
262                              "COPY", DefaultEditorKit.copyAction,
263                             "PASTE", DefaultEditorKit.pasteAction,
264                               "CUT", DefaultEditorKit.cutAction,
265                    "control INSERT", DefaultEditorKit.copyAction,
266                      "shift INSERT", DefaultEditorKit.pasteAction,
267                      "shift DELETE", DefaultEditorKit.cutAction,
268                        "shift LEFT", DefaultEditorKit.selectionBackwardAction,
269                     "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
270                       "shift RIGHT", DefaultEditorKit.selectionForwardAction,
271                    "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
272                         "ctrl LEFT", DefaultEditorKit.previousWordAction,
273                      "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
274                        "ctrl RIGHT", DefaultEditorKit.nextWordAction,
275                     "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
276                   "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
277                "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
278                  "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
279               "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
280                            "ctrl A", DefaultEditorKit.selectAllAction,
281                              "HOME", DefaultEditorKit.beginLineAction,
282                               "END", DefaultEditorKit.endLineAction,
283                        "shift HOME", DefaultEditorKit.selectionBeginLineAction,
284                         "shift END", DefaultEditorKit.selectionEndLineAction,
285                        "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
286                  "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
287                            "ctrl H", DefaultEditorKit.deletePrevCharAction,
288                            "DELETE", DefaultEditorKit.deleteNextCharAction,
289                       "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
290                   "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
291                             "RIGHT", DefaultEditorKit.forwardAction,
292                              "LEFT", DefaultEditorKit.backwardAction,
293                          "KP_RIGHT", DefaultEditorKit.forwardAction,
294                           "KP_LEFT", DefaultEditorKit.backwardAction,
295                             "ENTER", JTextField.notifyAction,
296                   "ctrl BACK_SLASH", "unselect",
297                    "control shift O", "toggle-componentOrientation",
298                            "ESCAPE", "reset-field-edit",
299                                "UP", "increment",
300                             "KP_UP", "increment",
301                              "DOWN", "decrement",
302                           "KP_DOWN", "decrement",
303               }));
304 
305         DEFAULT_VALUES.put("InternalFrame.icon",
306                            LookAndFeel.makeIcon(BasicLookAndFeel.class,
307                                                     "icons/JavaCup16.png"));
308 
309         DEFAULT_VALUES.put("InternalFrame.windowBindings",
310             new Object[] {
311               "shift ESCAPE", "showSystemMenu",
312                 "ctrl SPACE", "showSystemMenu",
313               "ESCAPE", "hideSystemMenu"});
314 
315         DEFAULT_VALUES.put("List.focusInputMap",
316                new UIDefaults.LazyInputMap(new Object[] {
317                            "ctrl C", "copy",
318                            "ctrl V", "paste",
319                            "ctrl X", "cut",
320                              "COPY", "copy",
321                             "PASTE", "paste",
322                               "CUT", "cut",
323                    "control INSERT", "copy",
324                      "shift INSERT", "paste",
325                      "shift DELETE", "cut",
326                                "UP", "selectPreviousRow",
327                             "KP_UP", "selectPreviousRow",
328                          "shift UP", "selectPreviousRowExtendSelection",
329                       "shift KP_UP", "selectPreviousRowExtendSelection",
330                     "ctrl shift UP", "selectPreviousRowExtendSelection",
331                  "ctrl shift KP_UP", "selectPreviousRowExtendSelection",
332                           "ctrl UP", "selectPreviousRowChangeLead",
333                        "ctrl KP_UP", "selectPreviousRowChangeLead",
334                              "DOWN", "selectNextRow",
335                           "KP_DOWN", "selectNextRow",
336                        "shift DOWN", "selectNextRowExtendSelection",
337                     "shift KP_DOWN", "selectNextRowExtendSelection",
338                   "ctrl shift DOWN", "selectNextRowExtendSelection",
339                "ctrl shift KP_DOWN", "selectNextRowExtendSelection",
340                         "ctrl DOWN", "selectNextRowChangeLead",
341                      "ctrl KP_DOWN", "selectNextRowChangeLead",
342                              "LEFT", "selectPreviousColumn",
343                           "KP_LEFT", "selectPreviousColumn",
344                        "shift LEFT", "selectPreviousColumnExtendSelection",
345                     "shift KP_LEFT", "selectPreviousColumnExtendSelection",
346                   "ctrl shift LEFT", "selectPreviousColumnExtendSelection",
347                "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection",
348                         "ctrl LEFT", "selectPreviousColumnChangeLead",
349                      "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
350                             "RIGHT", "selectNextColumn",
351                          "KP_RIGHT", "selectNextColumn",
352                       "shift RIGHT", "selectNextColumnExtendSelection",
353                    "shift KP_RIGHT", "selectNextColumnExtendSelection",
354                  "ctrl shift RIGHT", "selectNextColumnExtendSelection",
355               "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection",
356                        "ctrl RIGHT", "selectNextColumnChangeLead",
357                     "ctrl KP_RIGHT", "selectNextColumnChangeLead",
358                              "HOME", "selectFirstRow",
359                        "shift HOME", "selectFirstRowExtendSelection",
360                   "ctrl shift HOME", "selectFirstRowExtendSelection",
361                         "ctrl HOME", "selectFirstRowChangeLead",
362                               "END", "selectLastRow",
363                         "shift END", "selectLastRowExtendSelection",
364                    "ctrl shift END", "selectLastRowExtendSelection",
365                          "ctrl END", "selectLastRowChangeLead",
366                           "PAGE_UP", "scrollUp",
367                     "shift PAGE_UP", "scrollUpExtendSelection",
368                "ctrl shift PAGE_UP", "scrollUpExtendSelection",
369                      "ctrl PAGE_UP", "scrollUpChangeLead",
370                         "PAGE_DOWN", "scrollDown",
371                   "shift PAGE_DOWN", "scrollDownExtendSelection",
372              "ctrl shift PAGE_DOWN", "scrollDownExtendSelection",
373                    "ctrl PAGE_DOWN", "scrollDownChangeLead",
374                            "ctrl A", "selectAll",
375                        "ctrl SLASH", "selectAll",
376                   "ctrl BACK_SLASH", "clearSelection",
377                             "SPACE", "addToSelection",
378                        "ctrl SPACE", "toggleAndAnchor",
379                       "shift SPACE", "extendTo",
380                  "ctrl shift SPACE", "moveSelectionTo"
381                }));
382 
383         DEFAULT_VALUES.put("List.focusInputMap.RightToLeft",
384                new UIDefaults.LazyInputMap(new Object[] {
385                              "LEFT", "selectNextColumn",
386                           "KP_LEFT", "selectNextColumn",
387                        "shift LEFT", "selectNextColumnExtendSelection",
388                     "shift KP_LEFT", "selectNextColumnExtendSelection",
389                   "ctrl shift LEFT", "selectNextColumnExtendSelection",
390                "ctrl shift KP_LEFT", "selectNextColumnExtendSelection",
391                         "ctrl LEFT", "selectNextColumnChangeLead",
392                      "ctrl KP_LEFT", "selectNextColumnChangeLead",
393                             "RIGHT", "selectPreviousColumn",
394                          "KP_RIGHT", "selectPreviousColumn",
395                       "shift RIGHT", "selectPreviousColumnExtendSelection",
396                    "shift KP_RIGHT", "selectPreviousColumnExtendSelection",
397                  "ctrl shift RIGHT", "selectPreviousColumnExtendSelection",
398               "ctrl shift KP_RIGHT", "selectPreviousColumnExtendSelection",
399                        "ctrl RIGHT", "selectPreviousColumnChangeLead",
400                     "ctrl KP_RIGHT", "selectPreviousColumnChangeLead",
401                }));
402 
403         DEFAULT_VALUES.put("MenuBar.windowBindings",
404                                 new Object[] { "F10", "takeFocus" });
405 
406         DEFAULT_VALUES.put("OptionPane.windowBindings",
407                  new Object[] { "ESCAPE", "close" });
408 
409         DEFAULT_VALUES.put("RootPane.defaultButtonWindowKeyBindings",
410                  new Object[] {
411                              "ENTER", "press",
412                     "released ENTER", "release",
413                         "ctrl ENTER", "press",
414                "ctrl released ENTER", "release"
415                  });
416 
417         DEFAULT_VALUES.put("RootPane.ancestorInputMap",
418                new UIDefaults.LazyInputMap(new Object[] {
419                     "shift F10", "postPopup"
420                }));
421 
422         DEFAULT_VALUES.put("ScrollBar.anecstorInputMap",
423                new UIDefaults.LazyInputMap(new Object[] {
424                        "RIGHT", "positiveUnitIncrement",
425                     "KP_RIGHT", "positiveUnitIncrement",
426                         "DOWN", "positiveUnitIncrement",
427                      "KP_DOWN", "positiveUnitIncrement",
428                    "PAGE_DOWN", "positiveBlockIncrement",
429                         "LEFT", "negativeUnitIncrement",
430                      "KP_LEFT", "negativeUnitIncrement",
431                           "UP", "negativeUnitIncrement",
432                        "KP_UP", "negativeUnitIncrement",
433                      "PAGE_UP", "negativeBlockIncrement",
434                         "HOME", "minScroll",
435                          "END", "maxScroll"
436                }));
437 
438         DEFAULT_VALUES.put("ScrollBar.ancestorInputMap.RightToLeft",
439                new UIDefaults.LazyInputMap(new Object[] {
440                        "RIGHT", "negativeUnitIncrement",
441                     "KP_RIGHT", "negativeUnitIncrement",
442                         "LEFT", "positiveUnitIncrement",
443                      "KP_LEFT", "positiveUnitIncrement",
444                }));
445 
446         DEFAULT_VALUES.put("ScrollPane.ancestorInputMap",
447                new UIDefaults.LazyInputMap(new Object[] {
448                            "RIGHT", "unitScrollRight",
449                         "KP_RIGHT", "unitScrollRight",
450                             "DOWN", "unitScrollDown",
451                          "KP_DOWN", "unitScrollDown",
452                             "LEFT", "unitScrollLeft",
453                          "KP_LEFT", "unitScrollLeft",
454                               "UP", "unitScrollUp",
455                            "KP_UP", "unitScrollUp",
456                          "PAGE_UP", "scrollUp",
457                        "PAGE_DOWN", "scrollDown",
458                     "ctrl PAGE_UP", "scrollLeft",
459                   "ctrl PAGE_DOWN", "scrollRight",
460                        "ctrl HOME", "scrollHome",
461                         "ctrl END", "scrollEnd"
462                }));
463         DEFAULT_VALUES.put("ScrollPane.ancestorInputMap.RightToLeft",
464                new UIDefaults.LazyInputMap(new Object[] {
465                     "ctrl PAGE_UP", "scrollRight",
466                   "ctrl PAGE_DOWN", "scrollLeft",
467                }));
468 
469         DEFAULT_VALUES.put("SplitPane.ancestorInputMap",
470                new UIDefaults.LazyInputMap(new Object[] {
471                         "UP", "negativeIncrement",
472                       "DOWN", "positiveIncrement",
473                       "LEFT", "negativeIncrement",
474                      "RIGHT", "positiveIncrement",
475                      "KP_UP", "negativeIncrement",
476                    "KP_DOWN", "positiveIncrement",
477                    "KP_LEFT", "negativeIncrement",
478                   "KP_RIGHT", "positiveIncrement",
479                       "HOME", "selectMin",
480                        "END", "selectMax",
481                         "F8", "startResize",
482                         "F6", "toggleFocus",
483                   "ctrl TAB", "focusOutForward",
484             "ctrl shift TAB", "focusOutBackward"
485                }));
486 
487         DEFAULT_VALUES.put("Spinner.ancestorInputMap",
488                new UIDefaults.LazyInputMap(new Object[] {
489                           "UP", "increment",
490                        "KP_UP", "increment",
491                         "DOWN", "decrement",
492                      "KP_DOWN", "decrement"
493                }));
494 
495         DEFAULT_VALUES.put("Slider.focusInputMap",
496                new UIDefaults.LazyInputMap(new Object[] {
497                        "RIGHT", "positiveUnitIncrement",
498                     "KP_RIGHT", "positiveUnitIncrement",
499                         "DOWN", "negativeUnitIncrement",
500                      "KP_DOWN", "negativeUnitIncrement",
501                    "PAGE_DOWN", "negativeBlockIncrement",
502               "ctrl PAGE_DOWN", "negativeBlockIncrement",
503                         "LEFT", "negativeUnitIncrement",
504                      "KP_LEFT", "negativeUnitIncrement",
505                           "UP", "positiveUnitIncrement",
506                        "KP_UP", "positiveUnitIncrement",
507                      "PAGE_UP", "positiveBlockIncrement",
508                 "ctrl PAGE_UP", "positiveBlockIncrement",
509                         "HOME", "minScroll",
510                          "END", "maxScroll"
511                }));
512 
513         DEFAULT_VALUES.put("Slider.focusInputMap.RightToLeft",
514                new UIDefaults.LazyInputMap(new Object[] {
515                        "RIGHT", "negativeUnitIncrement",
516                     "KP_RIGHT", "negativeUnitIncrement",
517                         "LEFT", "positiveUnitIncrement",
518                      "KP_LEFT", "positiveUnitIncrement",
519                }));
520 
521         DEFAULT_VALUES.put("TabbedPane.ancestorInputMap",
522                new UIDefaults.LazyInputMap(new Object[] {
523                    "ctrl PAGE_DOWN", "navigatePageDown",
524                      "ctrl PAGE_UP", "navigatePageUp",
525                           "ctrl UP", "requestFocus",
526                        "ctrl KP_UP", "requestFocus",
527                }));
528 
529         DEFAULT_VALUES.put("TabbedPane.focusInputMap",
530               new UIDefaults.LazyInputMap(new Object[] {
531                          "RIGHT", "navigateRight",
532                       "KP_RIGHT", "navigateRight",
533                           "LEFT", "navigateLeft",
534                        "KP_LEFT", "navigateLeft",
535                             "UP", "navigateUp",
536                          "KP_UP", "navigateUp",
537                           "DOWN", "navigateDown",
538                        "KP_DOWN", "navigateDown",
539                      "ctrl DOWN", "requestFocusForVisibleComponent",
540                   "ctrl KP_DOWN", "requestFocusForVisibleComponent",
541               }));
542 
543         DEFAULT_VALUES.put("Table.ancestorInputMap",
544                new UIDefaults.LazyInputMap(new Object[] {
545                                "ctrl C", "copy",
546                                "ctrl V", "paste",
547                                "ctrl X", "cut",
548                                  "COPY", "copy",
549                                 "PASTE", "paste",
550                                   "CUT", "cut",
551                        "control INSERT", "copy",
552                          "shift INSERT", "paste",
553                          "shift DELETE", "cut",
554                                 "RIGHT", "selectNextColumn",
555                              "KP_RIGHT", "selectNextColumn",
556                           "shift RIGHT", "selectNextColumnExtendSelection",
557                        "shift KP_RIGHT", "selectNextColumnExtendSelection",
558                      "ctrl shift RIGHT", "selectNextColumnExtendSelection",
559                   "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection",
560                            "ctrl RIGHT", "selectNextColumnChangeLead",
561                         "ctrl KP_RIGHT", "selectNextColumnChangeLead",
562                                  "LEFT", "selectPreviousColumn",
563                               "KP_LEFT", "selectPreviousColumn",
564                            "shift LEFT", "selectPreviousColumnExtendSelection",
565                         "shift KP_LEFT", "selectPreviousColumnExtendSelection",
566                       "ctrl shift LEFT", "selectPreviousColumnExtendSelection",
567                    "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection",
568                             "ctrl LEFT", "selectPreviousColumnChangeLead",
569                          "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
570                                  "DOWN", "selectNextRow",
571                               "KP_DOWN", "selectNextRow",
572                            "shift DOWN", "selectNextRowExtendSelection",
573                         "shift KP_DOWN", "selectNextRowExtendSelection",
574                       "ctrl shift DOWN", "selectNextRowExtendSelection",
575                    "ctrl shift KP_DOWN", "selectNextRowExtendSelection",
576                             "ctrl DOWN", "selectNextRowChangeLead",
577                          "ctrl KP_DOWN", "selectNextRowChangeLead",
578                                    "UP", "selectPreviousRow",
579                                 "KP_UP", "selectPreviousRow",
580                              "shift UP", "selectPreviousRowExtendSelection",
581                           "shift KP_UP", "selectPreviousRowExtendSelection",
582                         "ctrl shift UP", "selectPreviousRowExtendSelection",
583                      "ctrl shift KP_UP", "selectPreviousRowExtendSelection",
584                               "ctrl UP", "selectPreviousRowChangeLead",
585                            "ctrl KP_UP", "selectPreviousRowChangeLead",
586                                  "HOME", "selectFirstColumn",
587                            "shift HOME", "selectFirstColumnExtendSelection",
588                       "ctrl shift HOME", "selectFirstRowExtendSelection",
589                             "ctrl HOME", "selectFirstRow",
590                                   "END", "selectLastColumn",
591                             "shift END", "selectLastColumnExtendSelection",
592                        "ctrl shift END", "selectLastRowExtendSelection",
593                              "ctrl END", "selectLastRow",
594                               "PAGE_UP", "scrollUpChangeSelection",
595                         "shift PAGE_UP", "scrollUpExtendSelection",
596                    "ctrl shift PAGE_UP", "scrollLeftExtendSelection",
597                          "ctrl PAGE_UP", "scrollLeftChangeSelection",
598                             "PAGE_DOWN", "scrollDownChangeSelection",
599                       "shift PAGE_DOWN", "scrollDownExtendSelection",
600                  "ctrl shift PAGE_DOWN", "scrollRightExtendSelection",
601                        "ctrl PAGE_DOWN", "scrollRightChangeSelection",
602                                   "TAB", "selectNextColumnCell",
603                             "shift TAB", "selectPreviousColumnCell",
604                                 "ENTER", "selectNextRowCell",
605                           "shift ENTER", "selectPreviousRowCell",
606                                "ctrl A", "selectAll",
607                            "ctrl SLASH", "selectAll",
608                       "ctrl BACK_SLASH", "clearSelection",
609                                "ESCAPE", "cancel",
610                                    "F2", "startEditing",
611                                 "SPACE", "addToSelection",
612                            "ctrl SPACE", "toggleAndAnchor",
613                           "shift SPACE", "extendTo",
614                      "ctrl shift SPACE", "moveSelectionTo",
615                                    "F8", "focusHeader"
616                }));
617 
618        DEFAULT_VALUES.put("TableHeader.ancestorInputMap",
619                new UIDefaults.LazyInputMap(new Object[] {
620                                 "SPACE", "toggleSortOrder",
621                                  "LEFT", "selectColumnToLeft",
622                               "KP_LEFT", "selectColumnToLeft",
623                                 "RIGHT", "selectColumnToRight",
624                              "KP_RIGHT", "selectColumnToRight",
625                              "alt LEFT", "moveColumnLeft",
626                           "alt KP_LEFT", "moveColumnLeft",
627                             "alt RIGHT", "moveColumnRight",
628                          "alt KP_RIGHT", "moveColumnRight",
629                        "alt shift LEFT", "resizeLeft",
630                     "alt shift KP_LEFT", "resizeLeft",
631                       "alt shift RIGHT", "resizeRight",
632                    "alt shift KP_RIGHT", "resizeRight",
633                                "ESCAPE", "focusTable",
634                }));
635 
636         DEFAULT_VALUES.put("Tree.ancestorInputMap",
637                new UIDefaults.LazyInputMap(new Object[] {
638                      "ESCAPE", "cancel"
639                }));
640         DEFAULT_VALUES.put("Tree.focusInputMap",
641                new UIDefaults.LazyInputMap(new Object[] {
642                                     "ADD", "expand",
643                                "SUBTRACT", "collapse",
644                                  "ctrl C", "copy",
645                                  "ctrl V", "paste",
646                                  "ctrl X", "cut",
647                                    "COPY", "copy",
648                                   "PASTE", "paste",
649                                     "CUT", "cut",
650                          "control INSERT", "copy",
651                            "shift INSERT", "paste",
652                            "shift DELETE", "cut",
653                                      "UP", "selectPrevious",
654                                   "KP_UP", "selectPrevious",
655                                "shift UP", "selectPreviousExtendSelection",
656                             "shift KP_UP", "selectPreviousExtendSelection",
657                           "ctrl shift UP", "selectPreviousExtendSelection",
658                        "ctrl shift KP_UP", "selectPreviousExtendSelection",
659                                 "ctrl UP", "selectPreviousChangeLead",
660                              "ctrl KP_UP", "selectPreviousChangeLead",
661                                    "DOWN", "selectNext",
662                                 "KP_DOWN", "selectNext",
663                              "shift DOWN", "selectNextExtendSelection",
664                           "shift KP_DOWN", "selectNextExtendSelection",
665                         "ctrl shift DOWN", "selectNextExtendSelection",
666                      "ctrl shift KP_DOWN", "selectNextExtendSelection",
667                               "ctrl DOWN", "selectNextChangeLead",
668                            "ctrl KP_DOWN", "selectNextChangeLead",
669                                   "RIGHT", "selectChild",
670                                "KP_RIGHT", "selectChild",
671                                    "LEFT", "selectParent",
672                                 "KP_LEFT", "selectParent",
673                                 "PAGE_UP", "scrollUpChangeSelection",
674                           "shift PAGE_UP", "scrollUpExtendSelection",
675                      "ctrl shift PAGE_UP", "scrollUpExtendSelection",
676                            "ctrl PAGE_UP", "scrollUpChangeLead",
677                               "PAGE_DOWN", "scrollDownChangeSelection",
678                         "shift PAGE_DOWN", "scrollDownExtendSelection",
679                    "ctrl shift PAGE_DOWN", "scrollDownExtendSelection",
680                          "ctrl PAGE_DOWN", "scrollDownChangeLead",
681                                    "HOME", "selectFirst",
682                              "shift HOME", "selectFirstExtendSelection",
683                         "ctrl shift HOME", "selectFirstExtendSelection",
684                               "ctrl HOME", "selectFirstChangeLead",
685                                     "END", "selectLast",
686                               "shift END", "selectLastExtendSelection",
687                          "ctrl shift END", "selectLastExtendSelection",
688                                "ctrl END", "selectLastChangeLead",
689                                      "F2", "startEditing",
690                                  "ctrl A", "selectAll",
691                              "ctrl SLASH", "selectAll",
692                         "ctrl BACK_SLASH", "clearSelection",
693                               "ctrl LEFT", "scrollLeft",
694                            "ctrl KP_LEFT", "scrollLeft",
695                              "ctrl RIGHT", "scrollRight",
696                           "ctrl KP_RIGHT", "scrollRight",
697                                   "SPACE", "addToSelection",
698                              "ctrl SPACE", "toggleAndAnchor",
699                             "shift SPACE", "extendTo",
700                        "ctrl shift SPACE", "moveSelectionTo"
701                }));
702         DEFAULT_VALUES.put("Tree.focusInputMap.RightToLeft",
703                new UIDefaults.LazyInputMap(new Object[] {
704                                   "RIGHT", "selectParent",
705                                "KP_RIGHT", "selectParent",
706                                    "LEFT", "selectChild",
707                                 "KP_LEFT", "selectChild",
708                }));
709     }
710 
711     /**
712      * Returns the default value for the specified property, or null if there
713      * is no default for the specified value.
714      */
715     private static Object getDefaultValue(Object key) {
716         synchronized(SynthStyle.class) {
717             if (DEFAULT_VALUES == null) {
718                 DEFAULT_VALUES = new HashMap<Object, Object>();
719                 populateDefaultValues();
720             }
721             Object value = DEFAULT_VALUES.get(key);
722             if (value instanceof UIDefaults.LazyValue) {
723                 value = ((UIDefaults.LazyValue)value).createValue(null);
724                 DEFAULT_VALUES.put(key, value);
725             }
726             return value;
727         }
728     }
729 
730     /**
731      * Constructs a SynthStyle.
732      */
733     public SynthStyle() {
734     }
735 
736     /**
737      * Returns the <code>SynthGraphicUtils</code> for the specified context.
738      *
739      * @param context SynthContext identifying requester
740      * @return SynthGraphicsUtils
741      */
742     public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
743         return SYNTH_GRAPHICS;
744     }
745 
746     /**
747      * Returns the color for the specified state. This gives precedence to
748      * foreground and background of the <code>JComponent</code>. If the
749      * <code>Color</code> from the <code>JComponent</code> is not appropriate,
750      * or not used, this will invoke <code>getColorForState</code>. Subclasses
751      * should generally not have to override this, instead override
752      * {@link #getColorForState}.
753      *
754      * @param context SynthContext identifying requester
755      * @param type Type of color being requested.
756      * @return Color
757      */
758     public Color getColor(SynthContext context, ColorType type) {
759         JComponent c = context.getComponent();
760         Region id = context.getRegion();
761 
762         if ((context.getComponentState() & SynthConstants.DISABLED) != 0) {
763             //This component is disabled, so return the disabled color.
764             //In some cases this means ignoring the color specified by the
765             //developer on the component. In other cases it means using a
766             //specified disabledTextColor, such as on JTextComponents.
767             //For example, JLabel doesn't specify a disabled color that the
768             //developer can set, yet it should have a disabled color to the
769             //text when the label is disabled. This code allows for that.
770             if (c instanceof JTextComponent) {
771                 JTextComponent txt = (JTextComponent)c;
772                 Color disabledColor = txt.getDisabledTextColor();
773                 if (disabledColor == null || disabledColor instanceof UIResource) {
774                     return getColorForState(context, type);
775                 }
776             } else if (c instanceof JLabel &&
777                             (type == ColorType.FOREGROUND ||
778                              type == ColorType.TEXT_FOREGROUND)) {
779                 return getColorForState(context, type);
780             }
781         }
782 
783         // If the developer has specified a color, prefer it. Otherwise, get
784         // the color for the state.
785         Color color = null;
786         if (!id.isSubregion()) {
787             if (type == ColorType.BACKGROUND) {
788                 color = c.getBackground();
789             }
790             else if (type == ColorType.FOREGROUND) {
791                 color = c.getForeground();
792             }
793             else if (type == ColorType.TEXT_FOREGROUND) {
794                 color = c.getForeground();
795             }
796         }
797 
798         if (color == null || color instanceof UIResource) {
799             // Then use what we've locally defined
800             color = getColorForState(context, type);
801         }
802 
803         if (color == null) {
804             // No color, fallback to that of the widget.
805             if (type == ColorType.BACKGROUND ||
806                         type == ColorType.TEXT_BACKGROUND) {
807                 return c.getBackground();
808             }
809             else if (type == ColorType.FOREGROUND ||
810                      type == ColorType.TEXT_FOREGROUND) {
811                 return c.getForeground();
812             }
813         }
814         return color;
815     }
816 
817     /**
818      * Returns the color for the specified state. This should NOT call any
819      * methods on the <code>JComponent</code>.
820      *
821      * @param context SynthContext identifying requester
822      * @param type Type of color being requested.
823      * @return Color to render with
824      */
825     protected abstract Color getColorForState(SynthContext context,
826                                               ColorType type);
827 
828     /**
829      * Returns the Font for the specified state. This redirects to the
830      * <code>JComponent</code> from the <code>context</code> as necessary.
831      * If this does not redirect
832      * to the JComponent {@link #getFontForState} is invoked.
833      *
834      * @param context SynthContext identifying requester
835      * @return Font to render with
836      */
837     public Font getFont(SynthContext context) {
838         JComponent c = context.getComponent();
839         if (context.getComponentState() == SynthConstants.ENABLED) {
840             return c.getFont();
841         }
842         Font cFont = c.getFont();
843         if (cFont != null && !(cFont instanceof UIResource)) {
844             return cFont;
845         }
846         return getFontForState(context);
847     }
848 
849     /**
850      * Returns the font for the specified state. This should NOT call any
851      * method on the <code>JComponent</code>.
852      *
853      * @param context SynthContext identifying requester
854      * @return Font to render with
855      */
856     protected abstract Font getFontForState(SynthContext context);
857 
858     /**
859      * Returns the Insets that are used to calculate sizing information.
860      *
861      * @param context SynthContext identifying requester
862      * @param insets Insets to place return value in.
863      * @return Sizing Insets.
864      */
865     public Insets getInsets(SynthContext context, Insets insets) {
866         if (insets == null) {
867             insets = new Insets(0, 0, 0, 0);
868         }
869         insets.top = insets.bottom = insets.left = insets.right = 0;
870         return insets;
871     }
872 
873     /**
874      * Returns the <code>SynthPainter</code> that will be used for painting.
875      * This may return null.
876      *
877      * @param context SynthContext identifying requester
878      * @return SynthPainter to use
879      */
880     public SynthPainter getPainter(SynthContext context) {
881         return null;
882     }
883 
884     /**
885      * Returns true if the region is opaque.
886      *
887      * @param context SynthContext identifying requester
888      * @return true if region is opaque.
889      */
890     public boolean isOpaque(SynthContext context) {
891         return true;
892     }
893 
894     /**
895      * Getter for a region specific style property.
896      *
897      * @param context SynthContext identifying requester
898      * @param key Property being requested.
899      * @return Value of the named property
900      */
901     public Object get(SynthContext context, Object key) {
902         return getDefaultValue(key);
903     }
904 
905     void installDefaults(SynthContext context, SynthUI ui) {
906         // Special case the Border as this will likely change when the LAF
907         // can have more control over this.
908         if (!context.isSubregion()) {
909             JComponent c = context.getComponent();
910             Border border = c.getBorder();
911 
912             if (border == null || border instanceof UIResource) {
913                 c.setBorder(new SynthBorder(ui, getInsets(context, null)));
914             }
915         }
916         installDefaults(context);
917     }
918 
919     /**
920      * Installs the necessary state from this Style on the
921      * <code>JComponent</code> from <code>context</code>.
922      *
923      * @param context SynthContext identifying component to install properties
924      *        to.
925      */
926     public void installDefaults(SynthContext context) {
927         if (!context.isSubregion()) {
928             JComponent c = context.getComponent();
929             Region region = context.getRegion();
930             Font font = c.getFont();
931 
932             if (font == null || (font instanceof UIResource)) {
933                 c.setFont(getFontForState(context));
934             }
935             Color background = c.getBackground();
936             if (background == null || (background instanceof UIResource)) {
937                 c.setBackground(getColorForState(context,
938                                                  ColorType.BACKGROUND));
939             }
940             Color foreground = c.getForeground();
941             if (foreground == null || (foreground instanceof UIResource)) {
942                 c.setForeground(getColorForState(context,
943                          ColorType.FOREGROUND));
944             }
945             LookAndFeel.installProperty(c, "opaque", Boolean.valueOf(isOpaque(context)));
946         }
947     }
948 
949     /**
950      * Uninstalls any state that this style installed on
951      * the <code>JComponent</code> from <code>context</code>.
952      * <p>
953      * Styles should NOT depend upon this being called, in certain cases
954      * it may never be called.
955      *
956      * @param context SynthContext identifying component to install properties
957      *        to.
958      */
959     public void uninstallDefaults(SynthContext context) {
960         if (!context.isSubregion()) {
961             // NOTE: because getForeground, getBackground and getFont will look
962             // at the parent Container, if we set them to null it may
963             // mean we they return a non-null and non-UIResource value
964             // preventing install from correctly settings its colors/font. For
965             // this reason we do not uninstall the fg/bg/font.
966 
967             JComponent c = context.getComponent();
968             Border border = c.getBorder();
969 
970             if (border instanceof UIResource) {
971                 c.setBorder(null);
972             }
973         }
974     }
975 
976     /**
977      * Convenience method to get a specific style property whose value is
978      * a <code>Number</code>. If the value is a <code>Number</code>,
979      * <code>intValue</code> is returned, otherwise <code>defaultValue</code>
980      * is returned.
981      *
982      * @param context SynthContext identifying requester
983      * @param key Property being requested.
984      * @param defaultValue Value to return if the property has not been
985      *        specified, or is not a Number
986      * @return Value of the named property
987      */
988     public int getInt(SynthContext context, Object key, int defaultValue) {
989         Object value = get(context, key);
990 
991         if (value instanceof Number) {
992             return ((Number)value).intValue();
993         }
994         return defaultValue;
995     }
996 
997     /**
998      * Convenience method to get a specific style property whose value is
999      * an Boolean.
1000      *
1001      * @param context SynthContext identifying requester
1002      * @param key Property being requested.
1003      * @param defaultValue Value to return if the property has not been
1004      *        specified, or is not a Boolean
1005      * @return Value of the named property
1006      */
1007     public boolean getBoolean(SynthContext context, Object key,
1008                               boolean defaultValue) {
1009         Object value = get(context, key);
1010 
1011         if (value instanceof Boolean) {
1012             return ((Boolean)value).booleanValue();
1013         }
1014         return defaultValue;
1015     }
1016 
1017     /**
1018      * Convenience method to get a specific style property whose value is
1019      * an Icon.
1020      *
1021      * @param context SynthContext identifying requester
1022      * @param key Property being requested.
1023      * @return Value of the named property, or null if not specified
1024      */
1025     public Icon getIcon(SynthContext context, Object key) {
1026         Object value = get(context, key);
1027 
1028         if (value instanceof Icon) {
1029             return (Icon)value;
1030         }
1031         return null;
1032     }
1033 
1034     /**
1035      * Convenience method to get a specific style property whose value is
1036      * a String.
1037      *
1038      * @param context SynthContext identifying requester
1039      * @param key Property being requested.
1040      * @param defaultValue Value to return if the property has not been
1041      *        specified, or is not a String
1042      * @return Value of the named property
1043      */
1044     public String getString(SynthContext context, Object key,
1045                               String defaultValue) {
1046         Object value = get(context, key);
1047 
1048         if (value instanceof String) {
1049             return (String)value;
1050         }
1051         return defaultValue;
1052     }
1053 }