1/*
2 * Copyright (c) 2002, 2017, 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
26package com.sun.java.swing.plaf.gtk;
27
28import java.awt.*;
29import java.beans.*;
30import java.io.File;
31import java.lang.ref.*;
32import java.security.AccessController;
33import java.security.PrivilegedAction;
34import java.util.Locale;
35import javax.swing.*;
36import javax.swing.colorchooser.*;
37import javax.swing.plaf.*;
38import javax.swing.plaf.synth.*;
39import javax.swing.text.DefaultEditorKit;
40
41import com.sun.java.swing.plaf.gtk.GTKConstants.PositionType;
42import com.sun.java.swing.plaf.gtk.GTKConstants.StateType;
43import java.util.HashMap;
44import java.util.Map;
45import sun.awt.SunToolkit;
46import sun.awt.UNIXToolkit;
47import sun.awt.OSInfo;
48import sun.security.action.GetPropertyAction;
49import sun.swing.DefaultLayoutStyle;
50import sun.swing.SwingAccessor;
51import sun.swing.SwingUtilities2;
52
53/**
54 * @author Scott Violet
55 */
56@SuppressWarnings("serial") // Superclass not serializable
57public class GTKLookAndFeel extends SynthLookAndFeel {
58    private static boolean IS_22;
59    private static boolean IS_3;
60
61    /**
62     * Whether or not text is drawn antialiased.  This keys off the
63     * desktop property 'gnome.Xft/Antialias' and 'gnome.Xft/RGBA'
64     * We should assume ON - or some variation of ON as no GTK desktop
65     * ships with it OFF.
66     */
67    static Map<Object, Object> aaTextInfo;
68
69    /*
70     * Used to override if system (desktop) text anti-aliasing settings should
71     * be used. The reasons for this are are is that currently its "off"
72     * for CJK locales which is not likely to be a good universal answer, and
73     * also its off for remote display. So this provides an unsupported
74     * way to explicitly request that it be "on".
75     */
76    private static boolean gtkAAFontSettingsCond;
77
78    /**
79     * Font to use in places where there is no widget.
80     */
81    private Font fallbackFont;
82
83    /**
84     * If true, GTKLookAndFeel is inside the <code>initialize</code>
85     * method.
86     */
87    private boolean inInitialize;
88
89    /**
90     * If true, PropertyChangeListeners have been installed for the
91     * Toolkit.
92     */
93    private boolean pclInstalled;
94
95    /**
96     * StyleFactory needs to be created only the first time.
97     */
98    private GTKStyleFactory styleFactory;
99
100    /**
101     * Cached theme name. Used by GTKGraphicsUtils
102     */
103    private static String gtkThemeName = "Default";
104
105    /**
106     * Returns true if running on system containing at least 2.2.
107     */
108    static boolean is2_2() {
109        // NOTE: We're currently hard coding to use 2.2.
110        // If we want to support both GTK 2.0 and 2.2, we'll
111        // need to get the major/minor/micro version from the .so.
112        // Refer to bug 4912613 for details.
113        return IS_22;
114    }
115
116    static boolean is3() {
117        return IS_3;
118    }
119
120    /**
121     * Maps a swing constant to a GTK constant.
122     */
123    static PositionType SwingOrientationConstantToGTK(int side) {
124        switch (side) {
125        case SwingConstants.LEFT:
126            return PositionType.LEFT;
127        case SwingConstants.RIGHT:
128            return PositionType.RIGHT;
129        case SwingConstants.TOP:
130            return PositionType.TOP;
131        case SwingConstants.BOTTOM:
132            return PositionType.BOTTOM;
133        }
134        assert false : "Unknown orientation: " + side;
135        return PositionType.TOP;
136    }
137
138    /**
139     * Maps from Synth state to native GTK state using typesafe enumeration
140     * StateType.  This is only used by GTKEngine.
141     */
142    static StateType synthStateToGTKStateType(int state) {
143        StateType result;
144        switch (state) {
145            case SynthConstants.PRESSED:
146                result = StateType.ACTIVE;
147                break;
148            case SynthConstants.MOUSE_OVER:
149                result = StateType.PRELIGHT;
150                break;
151            case SynthConstants.SELECTED:
152                result = StateType.SELECTED;
153                break;
154            case SynthConstants.DISABLED:
155                result = StateType.INSENSITIVE;
156                break;
157            case SynthConstants.ENABLED:
158            default:
159                result = StateType.NORMAL;
160                break;
161        }
162        return result;
163    }
164
165    /**
166     * Maps from a Synth state to the corresponding GTK state.
167     * The GTK states are named differently than Synth's states, the
168     * following gives the mapping:
169     * <table><tr><td>Synth<td>GTK
170     * <tr><td>SynthConstants.PRESSED<td>ACTIVE
171     * <tr><td>SynthConstants.SELECTED<td>SELECTED
172     * <tr><td>SynthConstants.MOUSE_OVER<td>PRELIGHT
173     * <tr><td>SynthConstants.DISABLED<td>INSENSITIVE
174     * <tr><td>SynthConstants.ENABLED<td>NORMAL
175     * </table>
176     * Additionally some widgets are special cased.
177     */
178    static int synthStateToGTKState(Region region, int state) {
179        if ((state & SynthConstants.PRESSED) != 0) {
180            if (region == Region.RADIO_BUTTON
181                    || region == Region.CHECK_BOX
182                    || region == Region.MENU
183                    || region == Region.MENU_ITEM
184                    || region == Region.RADIO_BUTTON_MENU_ITEM
185                    || region == Region.CHECK_BOX_MENU_ITEM
186                    || region == Region.SPLIT_PANE) {
187                state = SynthConstants.MOUSE_OVER;
188            } else {
189                state = SynthConstants.PRESSED;
190            }
191
192        } else if (region == Region.TABBED_PANE_TAB) {
193            if ((state & SynthConstants.DISABLED) != 0) {
194                state = SynthConstants.DISABLED;
195            }
196            else if ((state & SynthConstants.SELECTED) != 0) {
197                state = SynthConstants.ENABLED;
198            } else {
199                state = SynthConstants.PRESSED;
200            }
201
202        } else if ((state & SynthConstants.SELECTED) != 0) {
203            if (region == Region.MENU) {
204                state = SynthConstants.MOUSE_OVER;
205            } else if (region == Region.RADIO_BUTTON ||
206                          region == Region.TOGGLE_BUTTON ||
207                          region == Region.RADIO_BUTTON_MENU_ITEM ||
208                          region == Region.CHECK_BOX_MENU_ITEM ||
209                          region == Region.CHECK_BOX ||
210                          region == Region.BUTTON) {
211                if ((state & SynthConstants.DISABLED) != 0) {
212                    state = SynthConstants.DISABLED;
213                }
214                // If the button is SELECTED and is PRELIGHT we need to
215                // make the state MOUSE_OVER otherwise we don't paint the
216                // PRELIGHT.
217                else if ((state & SynthConstants.MOUSE_OVER) != 0) {
218                    state = SynthConstants.MOUSE_OVER;
219                } else {
220                    state = SynthConstants.PRESSED;
221                }
222            } else {
223                state = SynthConstants.SELECTED;
224            }
225        }
226
227        else if ((state & SynthConstants.MOUSE_OVER) != 0) {
228            state = SynthConstants.MOUSE_OVER;
229        }
230        else if ((state & SynthConstants.DISABLED) != 0) {
231            state = SynthConstants.DISABLED;
232        }
233        else {
234            if (region == Region.SLIDER_TRACK) {
235                state = SynthConstants.PRESSED;
236            } else {
237                state = SynthConstants.ENABLED;
238            }
239        }
240        return state;
241    }
242
243    static boolean isText(Region region) {
244        // These Regions treat FOREGROUND as TEXT.
245        return (region == Region.TEXT_FIELD ||
246                region == Region.FORMATTED_TEXT_FIELD ||
247                region == Region.LIST ||
248                region == Region.PASSWORD_FIELD ||
249                region == Region.SPINNER ||
250                region == Region.TABLE ||
251                region == Region.TEXT_AREA ||
252                region == Region.TEXT_FIELD ||
253                region == Region.TEXT_PANE ||
254                region == Region.TREE);
255    }
256
257    public UIDefaults getDefaults() {
258        // We need to call super for basic's properties file.
259        UIDefaults table = super.getDefaults();
260
261        // SynthTabbedPaneUI supports rollover on tabs, GTK does not
262        table.put("TabbedPane.isTabRollover", Boolean.FALSE);
263
264        // Prevents Synth from setting text AA by itself
265        table.put("Synth.doNotSetTextAA", true);
266
267        initResourceBundle(table);
268        // For compatibility with apps expecting certain defaults we'll
269        // populate the table with the values from basic.
270        initSystemColorDefaults(table);
271        initComponentDefaults(table);
272        installPropertyChangeListeners();
273        return table;
274    }
275
276    private void installPropertyChangeListeners() {
277        if(!pclInstalled) {
278            Toolkit kit = Toolkit.getDefaultToolkit();
279            WeakPCL pcl = new WeakPCL(this, kit, "gnome.Net/ThemeName");
280            kit.addPropertyChangeListener(pcl.getKey(), pcl);
281            pcl = new WeakPCL(this, kit, "gnome.Gtk/FontName");
282            kit.addPropertyChangeListener(pcl.getKey(), pcl);
283            pcl = new WeakPCL(this, kit, "gnome.Xft/DPI");
284            kit.addPropertyChangeListener(pcl.getKey(), pcl);
285
286            flushUnreferenced();
287            pclInstalled = true;
288        }
289    }
290
291    private void initResourceBundle(UIDefaults table) {
292        SwingAccessor.getUIDefaultsAccessor()
293                     .addInternalBundle(table,
294                             "com.sun.java.swing.plaf.gtk.resources.gtk");
295    }
296
297    protected void initComponentDefaults(UIDefaults table) {
298        // For compatibility with apps expecting certain defaults we'll
299        // populate the table with the values from basic.
300        super.initComponentDefaults(table);
301
302        UIDefaults.LazyValue zeroBorder =
303            t -> new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0);
304
305        Object focusBorder = new GTKStyle.GTKLazyValue(
306            "com.sun.java.swing.plaf.gtk.GTKPainter$ListTableFocusBorder",
307            "getUnselectedCellBorder");
308        Object focusSelectedBorder = new GTKStyle.GTKLazyValue(
309            "com.sun.java.swing.plaf.gtk.GTKPainter$ListTableFocusBorder",
310            "getSelectedCellBorder");
311        Object noFocusBorder = new GTKStyle.GTKLazyValue(
312            "com.sun.java.swing.plaf.gtk.GTKPainter$ListTableFocusBorder",
313            "getNoFocusCellBorder");
314
315        GTKStyleFactory factory = (GTKStyleFactory)getStyleFactory();
316        GTKStyle tableStyle = (GTKStyle)factory.getStyle(null, Region.TREE);
317        Color tableBg = tableStyle.getGTKColor(SynthConstants.ENABLED,
318                GTKColorType.TEXT_BACKGROUND);
319        Color tableFocusCellBg = tableStyle.getGTKColor(SynthConstants.ENABLED,
320                GTKColorType.BACKGROUND);
321        Color tableFocusCellFg = tableStyle.getGTKColor(SynthConstants.ENABLED,
322                GTKColorType.FOREGROUND);
323
324        // The following progress bar size calculations come from
325        // gtkprogressbar.c (version 2.8.20), see MIN_* constants and
326        // the gtk_progress_bar_size_request() method.
327        GTKStyle progStyle = (GTKStyle)
328            factory.getStyle(null, Region.PROGRESS_BAR);
329        int progXThickness = progStyle.getXThickness();
330        int progYThickness = progStyle.getYThickness();
331        int hProgWidth  = 150 - (progXThickness * 2);
332        int hProgHeight =  20 - (progYThickness * 2);
333        int vProgWidth  =  22 - (progXThickness * 2);
334        int vProgHeight =  80 - (progYThickness * 2);
335
336        Integer caretBlinkRate;
337        if (Boolean.FALSE.equals(GTKEngine.INSTANCE.getSetting(
338                GTKEngine.Settings.GTK_CURSOR_BLINK))) {
339            caretBlinkRate = Integer.valueOf(0);
340        } else {
341            caretBlinkRate = (Integer) GTKEngine.INSTANCE.getSetting(
342                    GTKEngine.Settings.GTK_CURSOR_BLINK_TIME);
343            if (caretBlinkRate == null) {
344                caretBlinkRate = Integer.valueOf(500);
345            }
346        }
347        Insets zeroInsets = new InsetsUIResource(0, 0, 0, 0);
348
349        Double defaultCaretAspectRatio = Double.valueOf(0.025);
350        Color caretColor = table.getColor("caretColor");
351        Color controlText = table.getColor("controlText");
352
353        Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[] {
354                       "ctrl C", DefaultEditorKit.copyAction,
355                       "ctrl V", DefaultEditorKit.pasteAction,
356                       "ctrl X", DefaultEditorKit.cutAction,
357                         "COPY", DefaultEditorKit.copyAction,
358                        "PASTE", DefaultEditorKit.pasteAction,
359                          "CUT", DefaultEditorKit.cutAction,
360               "control INSERT", DefaultEditorKit.copyAction,
361                 "shift INSERT", DefaultEditorKit.pasteAction,
362                 "shift DELETE", DefaultEditorKit.cutAction,
363                   "shift LEFT", DefaultEditorKit.selectionBackwardAction,
364                "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
365                  "shift RIGHT", DefaultEditorKit.selectionForwardAction,
366               "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
367                    "ctrl LEFT", DefaultEditorKit.previousWordAction,
368                 "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
369                   "ctrl RIGHT", DefaultEditorKit.nextWordAction,
370                "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
371              "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
372           "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
373             "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
374          "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
375                       "ctrl A", DefaultEditorKit.selectAllAction,
376                         "HOME", DefaultEditorKit.beginLineAction,
377                          "END", DefaultEditorKit.endLineAction,
378                   "shift HOME", DefaultEditorKit.selectionBeginLineAction,
379                    "shift END", DefaultEditorKit.selectionEndLineAction,
380                   "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
381             "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
382                       "ctrl H", DefaultEditorKit.deletePrevCharAction,
383                       "DELETE", DefaultEditorKit.deleteNextCharAction,
384                  "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
385              "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
386                        "RIGHT", DefaultEditorKit.forwardAction,
387                         "LEFT", DefaultEditorKit.backwardAction,
388                     "KP_RIGHT", DefaultEditorKit.forwardAction,
389                      "KP_LEFT", DefaultEditorKit.backwardAction,
390                        "ENTER", JTextField.notifyAction,
391              "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
392               "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
393            });
394
395        Object passwordInputMap = new UIDefaults.LazyInputMap(new Object[] {
396                       "ctrl C", DefaultEditorKit.copyAction,
397                       "ctrl V", DefaultEditorKit.pasteAction,
398                       "ctrl X", DefaultEditorKit.cutAction,
399                         "COPY", DefaultEditorKit.copyAction,
400                        "PASTE", DefaultEditorKit.pasteAction,
401                          "CUT", DefaultEditorKit.cutAction,
402               "control INSERT", DefaultEditorKit.copyAction,
403                 "shift INSERT", DefaultEditorKit.pasteAction,
404                 "shift DELETE", DefaultEditorKit.cutAction,
405                   "shift LEFT", DefaultEditorKit.selectionBackwardAction,
406                "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
407                  "shift RIGHT", DefaultEditorKit.selectionForwardAction,
408               "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
409                    "ctrl LEFT", DefaultEditorKit.beginLineAction,
410                 "ctrl KP_LEFT", DefaultEditorKit.beginLineAction,
411                   "ctrl RIGHT", DefaultEditorKit.endLineAction,
412                "ctrl KP_RIGHT", DefaultEditorKit.endLineAction,
413              "ctrl shift LEFT", DefaultEditorKit.selectionBeginLineAction,
414           "ctrl shift KP_LEFT", DefaultEditorKit.selectionBeginLineAction,
415             "ctrl shift RIGHT", DefaultEditorKit.selectionEndLineAction,
416          "ctrl shift KP_RIGHT", DefaultEditorKit.selectionEndLineAction,
417                       "ctrl A", DefaultEditorKit.selectAllAction,
418                         "HOME", DefaultEditorKit.beginLineAction,
419                          "END", DefaultEditorKit.endLineAction,
420                   "shift HOME", DefaultEditorKit.selectionBeginLineAction,
421                    "shift END", DefaultEditorKit.selectionEndLineAction,
422                   "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
423             "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
424                       "ctrl H", DefaultEditorKit.deletePrevCharAction,
425                       "DELETE", DefaultEditorKit.deleteNextCharAction,
426                        "RIGHT", DefaultEditorKit.forwardAction,
427                         "LEFT", DefaultEditorKit.backwardAction,
428                     "KP_RIGHT", DefaultEditorKit.forwardAction,
429                      "KP_LEFT", DefaultEditorKit.backwardAction,
430                        "ENTER", JTextField.notifyAction,
431              "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
432               "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
433            });
434
435        Object editorMargin = new InsetsUIResource(3,3,3,3);
436
437        Object multilineInputMap = new UIDefaults.LazyInputMap(new Object[] {
438                           "ctrl C", DefaultEditorKit.copyAction,
439                           "ctrl V", DefaultEditorKit.pasteAction,
440                           "ctrl X", DefaultEditorKit.cutAction,
441                             "COPY", DefaultEditorKit.copyAction,
442                            "PASTE", DefaultEditorKit.pasteAction,
443                              "CUT", DefaultEditorKit.cutAction,
444                   "control INSERT", DefaultEditorKit.copyAction,
445                     "shift INSERT", DefaultEditorKit.pasteAction,
446                     "shift DELETE", DefaultEditorKit.cutAction,
447                       "shift LEFT", DefaultEditorKit.selectionBackwardAction,
448                    "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
449                      "shift RIGHT", DefaultEditorKit.selectionForwardAction,
450                   "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
451                        "ctrl LEFT", DefaultEditorKit.previousWordAction,
452                     "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
453                       "ctrl RIGHT", DefaultEditorKit.nextWordAction,
454                    "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
455                  "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
456               "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
457                 "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
458              "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
459                           "ctrl A", DefaultEditorKit.selectAllAction,
460                             "HOME", DefaultEditorKit.beginLineAction,
461                              "END", DefaultEditorKit.endLineAction,
462                       "shift HOME", DefaultEditorKit.selectionBeginLineAction,
463                        "shift END", DefaultEditorKit.selectionEndLineAction,
464
465                               "UP", DefaultEditorKit.upAction,
466                            "KP_UP", DefaultEditorKit.upAction,
467                             "DOWN", DefaultEditorKit.downAction,
468                          "KP_DOWN", DefaultEditorKit.downAction,
469                          "PAGE_UP", DefaultEditorKit.pageUpAction,
470                        "PAGE_DOWN", DefaultEditorKit.pageDownAction,
471                    "shift PAGE_UP", "selection-page-up",
472                  "shift PAGE_DOWN", "selection-page-down",
473               "ctrl shift PAGE_UP", "selection-page-left",
474             "ctrl shift PAGE_DOWN", "selection-page-right",
475                         "shift UP", DefaultEditorKit.selectionUpAction,
476                      "shift KP_UP", DefaultEditorKit.selectionUpAction,
477                       "shift DOWN", DefaultEditorKit.selectionDownAction,
478                    "shift KP_DOWN", DefaultEditorKit.selectionDownAction,
479                            "ENTER", DefaultEditorKit.insertBreakAction,
480                       "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
481                 "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
482                           "ctrl H", DefaultEditorKit.deletePrevCharAction,
483                           "DELETE", DefaultEditorKit.deleteNextCharAction,
484                      "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
485                  "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
486                            "RIGHT", DefaultEditorKit.forwardAction,
487                             "LEFT", DefaultEditorKit.backwardAction,
488                         "KP_RIGHT", DefaultEditorKit.forwardAction,
489                          "KP_LEFT", DefaultEditorKit.backwardAction,
490                              "TAB", DefaultEditorKit.insertTabAction,
491                  "ctrl BACK_SLASH", "unselect"/*DefaultEditorKit.unselectAction*/,
492                        "ctrl HOME", DefaultEditorKit.beginAction,
493                         "ctrl END", DefaultEditorKit.endAction,
494                  "ctrl shift HOME", DefaultEditorKit.selectionBeginAction,
495                   "ctrl shift END", DefaultEditorKit.selectionEndAction,
496                           "ctrl T", "next-link-action",
497                     "ctrl shift T", "previous-link-action",
498                       "ctrl SPACE", "activate-link-action",
499                   "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/
500            });
501
502        class FontLazyValue implements UIDefaults.LazyValue {
503            private Region region;
504            FontLazyValue(Region region) {
505                this.region = region;
506            }
507            public Object createValue(UIDefaults table) {
508                GTKStyleFactory factory = (GTKStyleFactory)getStyleFactory();
509                GTKStyle style = (GTKStyle)factory.getStyle(null, region);
510                return style.getDefaultFont();
511            }
512        }
513
514        Object[] defaults = new Object[] {
515            "ArrowButton.size", Integer.valueOf(13),
516
517
518            "Button.defaultButtonFollowsFocus", Boolean.FALSE,
519            "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] {
520                         "SPACE", "pressed",
521                "released SPACE", "released",
522                         "ENTER", "pressed",
523                "released ENTER", "released"
524              }),
525            "Button.font", new FontLazyValue(Region.BUTTON),
526            "Button.margin", zeroInsets,
527
528
529            "CheckBox.focusInputMap", new UIDefaults.LazyInputMap(new Object[]{
530                         "SPACE", "pressed",
531                "released SPACE", "released"
532              }),
533            "CheckBox.icon", new GTKStyle.GTKLazyValue(
534                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
535                              "getCheckBoxIcon"),
536            "CheckBox.font", new FontLazyValue(Region.CHECK_BOX),
537            "CheckBox.margin", zeroInsets,
538
539
540            "CheckBoxMenuItem.arrowIcon", null,
541            "CheckBoxMenuItem.checkIcon", new GTKStyle.GTKLazyValue(
542                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
543                              "getCheckBoxMenuItemCheckIcon"),
544            "CheckBoxMenuItem.font",
545                new FontLazyValue(Region.CHECK_BOX_MENU_ITEM),
546            "CheckBoxMenuItem.margin", zeroInsets,
547            "CheckBoxMenuItem.alignAcceleratorText", Boolean.FALSE,
548
549
550            "ColorChooser.showPreviewPanelText", Boolean.FALSE,
551            "ColorChooser.panels", new UIDefaults.ActiveValue() {
552                public Object createValue(UIDefaults table) {
553                    return new AbstractColorChooserPanel[] {
554                                       new GTKColorChooserPanel() };
555                }
556            },
557            "ColorChooser.font", new FontLazyValue(Region.COLOR_CHOOSER),
558
559
560            "ComboBox.ancestorInputMap",
561               new UIDefaults.LazyInputMap(new Object[] {
562                     "ESCAPE", "hidePopup",
563                    "PAGE_UP", "pageUpPassThrough",
564                  "PAGE_DOWN", "pageDownPassThrough",
565                       "HOME", "homePassThrough",
566                        "END", "endPassThrough",
567                       "DOWN", "selectNext",
568                    "KP_DOWN", "selectNext",
569                   "alt DOWN", "togglePopup",
570                "alt KP_DOWN", "togglePopup",
571                     "alt UP", "togglePopup",
572                  "alt KP_UP", "togglePopup",
573                      "SPACE", "spacePopup",
574                      "ENTER", "enterPressed",
575                         "UP", "selectPrevious",
576                      "KP_UP", "selectPrevious"
577
578                 }),
579            "ComboBox.font", new FontLazyValue(Region.COMBO_BOX),
580            "ComboBox.isEnterSelectablePopup", Boolean.TRUE,
581
582
583            "EditorPane.caretForeground", caretColor,
584            "EditorPane.caretAspectRatio", defaultCaretAspectRatio,
585            "EditorPane.caretBlinkRate", caretBlinkRate,
586            "EditorPane.margin", editorMargin,
587            "EditorPane.focusInputMap", multilineInputMap,
588            "EditorPane.font", new FontLazyValue(Region.EDITOR_PANE),
589
590
591            "FileChooser.ancestorInputMap",
592               new UIDefaults.LazyInputMap(new Object[] {
593                     "ESCAPE", "cancelSelection",
594                 "ctrl ENTER", "approveSelection"
595                 }),
596            "FileChooserUI", "com.sun.java.swing.plaf.gtk.GTKLookAndFeel",
597
598
599            "FormattedTextField.caretForeground", caretColor,
600            "FormattedTextField.caretAspectRatio", defaultCaretAspectRatio,
601            "FormattedTextField.caretBlinkRate", caretBlinkRate,
602            "FormattedTextField.focusInputMap",
603              new UIDefaults.LazyInputMap(new Object[] {
604                           "ctrl C", DefaultEditorKit.copyAction,
605                           "ctrl V", DefaultEditorKit.pasteAction,
606                           "ctrl X", DefaultEditorKit.cutAction,
607                             "COPY", DefaultEditorKit.copyAction,
608                            "PASTE", DefaultEditorKit.pasteAction,
609                              "CUT", DefaultEditorKit.cutAction,
610                   "control INSERT", DefaultEditorKit.copyAction,
611                     "shift INSERT", DefaultEditorKit.pasteAction,
612                     "shift DELETE", DefaultEditorKit.cutAction,
613                       "shift LEFT", DefaultEditorKit.selectionBackwardAction,
614                    "shift KP_LEFT", DefaultEditorKit.selectionBackwardAction,
615                      "shift RIGHT", DefaultEditorKit.selectionForwardAction,
616                   "shift KP_RIGHT", DefaultEditorKit.selectionForwardAction,
617                        "ctrl LEFT", DefaultEditorKit.previousWordAction,
618                     "ctrl KP_LEFT", DefaultEditorKit.previousWordAction,
619                       "ctrl RIGHT", DefaultEditorKit.nextWordAction,
620                    "ctrl KP_RIGHT", DefaultEditorKit.nextWordAction,
621                  "ctrl shift LEFT", DefaultEditorKit.selectionPreviousWordAction,
622               "ctrl shift KP_LEFT", DefaultEditorKit.selectionPreviousWordAction,
623                 "ctrl shift RIGHT", DefaultEditorKit.selectionNextWordAction,
624              "ctrl shift KP_RIGHT", DefaultEditorKit.selectionNextWordAction,
625                           "ctrl A", DefaultEditorKit.selectAllAction,
626                             "HOME", DefaultEditorKit.beginLineAction,
627                              "END", DefaultEditorKit.endLineAction,
628                       "shift HOME", DefaultEditorKit.selectionBeginLineAction,
629                        "shift END", DefaultEditorKit.selectionEndLineAction,
630                       "BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
631                 "shift BACK_SPACE", DefaultEditorKit.deletePrevCharAction,
632                           "ctrl H", DefaultEditorKit.deletePrevCharAction,
633                           "DELETE", DefaultEditorKit.deleteNextCharAction,
634                      "ctrl DELETE", DefaultEditorKit.deleteNextWordAction,
635                  "ctrl BACK_SPACE", DefaultEditorKit.deletePrevWordAction,
636                            "RIGHT", DefaultEditorKit.forwardAction,
637                             "LEFT", DefaultEditorKit.backwardAction,
638                         "KP_RIGHT", DefaultEditorKit.forwardAction,
639                          "KP_LEFT", DefaultEditorKit.backwardAction,
640                            "ENTER", JTextField.notifyAction,
641                  "ctrl BACK_SLASH", "unselect",
642                  "control shift O", "toggle-componentOrientation",
643                           "ESCAPE", "reset-field-edit",
644                               "UP", "increment",
645                            "KP_UP", "increment",
646                             "DOWN", "decrement",
647                          "KP_DOWN", "decrement",
648              }),
649            "FormattedTextField.font",
650                new FontLazyValue(Region.FORMATTED_TEXT_FIELD),
651
652
653            "InternalFrameTitlePane.titlePaneLayout",
654                                new GTKStyle.GTKLazyValue("com.sun.java.swing.plaf.gtk.Metacity",
655                                                 "getTitlePaneLayout"),
656            "InternalFrame.windowBindings", new Object[] {
657                  "shift ESCAPE", "showSystemMenu",
658                    "ctrl SPACE", "showSystemMenu",
659                        "ESCAPE", "hideSystemMenu" },
660            "InternalFrame.layoutTitlePaneAtOrigin", Boolean.TRUE,
661            "InternalFrame.useTaskBar", Boolean.TRUE,
662
663            "InternalFrameTitlePane.iconifyButtonOpacity", null,
664            "InternalFrameTitlePane.maximizeButtonOpacity", null,
665            "InternalFrameTitlePane.closeButtonOpacity", null,
666
667            "Label.font", new FontLazyValue(Region.LABEL),
668
669            "List.background", tableBg,
670            "List.focusCellHighlightBorder", focusBorder,
671            "List.focusSelectedCellHighlightBorder", focusSelectedBorder,
672            "List.noFocusBorder", noFocusBorder,
673            "List.focusInputMap",
674               new UIDefaults.LazyInputMap(new Object[] {
675                           "ctrl C", "copy",
676                           "ctrl V", "paste",
677                           "ctrl X", "cut",
678                             "COPY", "copy",
679                            "PASTE", "paste",
680                              "CUT", "cut",
681                   "control INSERT", "copy",
682                     "shift INSERT", "paste",
683                     "shift DELETE", "cut",
684                               "UP", "selectPreviousRow",
685                            "KP_UP", "selectPreviousRow",
686                         "shift UP", "selectPreviousRowExtendSelection",
687                      "shift KP_UP", "selectPreviousRowExtendSelection",
688                    "ctrl shift UP", "selectPreviousRowExtendSelection",
689                 "ctrl shift KP_UP", "selectPreviousRowExtendSelection",
690                          "ctrl UP", "selectPreviousRowChangeLead",
691                       "ctrl KP_UP", "selectPreviousRowChangeLead",
692                             "DOWN", "selectNextRow",
693                          "KP_DOWN", "selectNextRow",
694                       "shift DOWN", "selectNextRowExtendSelection",
695                    "shift KP_DOWN", "selectNextRowExtendSelection",
696                  "ctrl shift DOWN", "selectNextRowExtendSelection",
697               "ctrl shift KP_DOWN", "selectNextRowExtendSelection",
698                        "ctrl DOWN", "selectNextRowChangeLead",
699                     "ctrl KP_DOWN", "selectNextRowChangeLead",
700                             "LEFT", "selectPreviousColumn",
701                          "KP_LEFT", "selectPreviousColumn",
702                       "shift LEFT", "selectPreviousColumnExtendSelection",
703                    "shift KP_LEFT", "selectPreviousColumnExtendSelection",
704                  "ctrl shift LEFT", "selectPreviousColumnExtendSelection",
705               "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection",
706                        "ctrl LEFT", "selectPreviousColumnChangeLead",
707                     "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
708                            "RIGHT", "selectNextColumn",
709                         "KP_RIGHT", "selectNextColumn",
710                      "shift RIGHT", "selectNextColumnExtendSelection",
711                   "shift KP_RIGHT", "selectNextColumnExtendSelection",
712                 "ctrl shift RIGHT", "selectNextColumnExtendSelection",
713              "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection",
714                       "ctrl RIGHT", "selectNextColumnChangeLead",
715                    "ctrl KP_RIGHT", "selectNextColumnChangeLead",
716                             "HOME", "selectFirstRow",
717                       "shift HOME", "selectFirstRowExtendSelection",
718                  "ctrl shift HOME", "selectFirstRowExtendSelection",
719                        "ctrl HOME", "selectFirstRowChangeLead",
720                              "END", "selectLastRow",
721                        "shift END", "selectLastRowExtendSelection",
722                   "ctrl shift END", "selectLastRowExtendSelection",
723                         "ctrl END", "selectLastRowChangeLead",
724                          "PAGE_UP", "scrollUp",
725                    "shift PAGE_UP", "scrollUpExtendSelection",
726               "ctrl shift PAGE_UP", "scrollUpExtendSelection",
727                     "ctrl PAGE_UP", "scrollUpChangeLead",
728                        "PAGE_DOWN", "scrollDown",
729                  "shift PAGE_DOWN", "scrollDownExtendSelection",
730             "ctrl shift PAGE_DOWN", "scrollDownExtendSelection",
731                   "ctrl PAGE_DOWN", "scrollDownChangeLead",
732                           "ctrl A", "selectAll",
733                       "ctrl SLASH", "selectAll",
734                  "ctrl BACK_SLASH", "clearSelection",
735                            "SPACE", "addToSelection",
736                       "ctrl SPACE", "toggleAndAnchor",
737                      "shift SPACE", "extendTo",
738                 "ctrl shift SPACE", "moveSelectionTo"
739                 }),
740            "List.focusInputMap.RightToLeft",
741               new UIDefaults.LazyInputMap(new Object[] {
742                             "LEFT", "selectNextColumn",
743                          "KP_LEFT", "selectNextColumn",
744                       "shift LEFT", "selectNextColumnExtendSelection",
745                    "shift KP_LEFT", "selectNextColumnExtendSelection",
746                  "ctrl shift LEFT", "selectNextColumnExtendSelection",
747               "ctrl shift KP_LEFT", "selectNextColumnExtendSelection",
748                        "ctrl LEFT", "selectNextColumnChangeLead",
749                     "ctrl KP_LEFT", "selectNextColumnChangeLead",
750                            "RIGHT", "selectPreviousColumn",
751                         "KP_RIGHT", "selectPreviousColumn",
752                      "shift RIGHT", "selectPreviousColumnExtendSelection",
753                   "shift KP_RIGHT", "selectPreviousColumnExtendSelection",
754                 "ctrl shift RIGHT", "selectPreviousColumnExtendSelection",
755              "ctrl shift KP_RIGHT", "selectPreviousColumnExtendSelection",
756                       "ctrl RIGHT", "selectPreviousColumnChangeLead",
757                    "ctrl KP_RIGHT", "selectPreviousColumnChangeLead",
758                 }),
759            "List.font", new FontLazyValue(Region.LIST),
760            "List.rendererUseUIBorder", Boolean.FALSE,
761
762            "Menu.arrowIcon", new GTKStyle.GTKLazyValue(
763                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
764                              "getMenuArrowIcon"),
765            "Menu.checkIcon", null,
766            "Menu.font", new FontLazyValue(Region.MENU),
767            "Menu.margin", zeroInsets,
768            "Menu.cancelMode", "hideMenuTree",
769            "Menu.alignAcceleratorText", Boolean.FALSE,
770            "Menu.useMenuBarForTopLevelMenus", Boolean.TRUE,
771
772
773                "MenuBar.windowBindings", new Object[] {
774                "F10", "takeFocus" },
775            "MenuBar.font", new FontLazyValue(Region.MENU_BAR),
776
777
778            "MenuItem.arrowIcon", null,
779            "MenuItem.checkIcon", null,
780            "MenuItem.font", new FontLazyValue(Region.MENU_ITEM),
781            "MenuItem.margin", zeroInsets,
782            "MenuItem.alignAcceleratorText", Boolean.FALSE,
783
784
785            "OptionPane.setButtonMargin", Boolean.FALSE,
786            "OptionPane.sameSizeButtons", Boolean.TRUE,
787            "OptionPane.buttonOrientation", SwingConstants.RIGHT,
788            "OptionPane.minimumSize", new DimensionUIResource(262, 90),
789            "OptionPane.buttonPadding", 10,
790            "OptionPane.windowBindings", new Object[] {
791                "ESCAPE", "close" },
792            "OptionPane.buttonClickThreshhold", 500,
793            "OptionPane.isYesLast", Boolean.TRUE,
794            "OptionPane.font", new FontLazyValue(Region.OPTION_PANE),
795
796            "Panel.font", new FontLazyValue(Region.PANEL),
797
798            "PasswordField.caretForeground", caretColor,
799            "PasswordField.caretAspectRatio", defaultCaretAspectRatio,
800            "PasswordField.caretBlinkRate", caretBlinkRate,
801            "PasswordField.margin", zeroInsets,
802            "PasswordField.focusInputMap", passwordInputMap,
803            "PasswordField.font", new FontLazyValue(Region.PASSWORD_FIELD),
804
805
806            "PopupMenu.consumeEventOnClose", Boolean.TRUE,
807            "PopupMenu.selectedWindowInputMapBindings", new Object[] {
808                  "ESCAPE", "cancel",
809                    "DOWN", "selectNext",
810                 "KP_DOWN", "selectNext",
811                      "UP", "selectPrevious",
812                   "KP_UP", "selectPrevious",
813                    "LEFT", "selectParent",
814                 "KP_LEFT", "selectParent",
815                   "RIGHT", "selectChild",
816                "KP_RIGHT", "selectChild",
817                   "ENTER", "return",
818                   "SPACE", "return"
819            },
820            "PopupMenu.selectedWindowInputMapBindings.RightToLeft",
821                  new Object[] {
822                    "LEFT", "selectChild",
823                 "KP_LEFT", "selectChild",
824                   "RIGHT", "selectParent",
825                "KP_RIGHT", "selectParent",
826            },
827            "PopupMenu.font", new FontLazyValue(Region.POPUP_MENU),
828
829            "ProgressBar.horizontalSize",
830                new DimensionUIResource(hProgWidth, hProgHeight),
831            "ProgressBar.verticalSize",
832                new DimensionUIResource(vProgWidth, vProgHeight),
833            "ProgressBar.font", new FontLazyValue(Region.PROGRESS_BAR),
834
835            "RadioButton.focusInputMap",
836                   new UIDefaults.LazyInputMap(new Object[] {
837                            "SPACE", "pressed",
838                   "released SPACE", "released",
839                           "RETURN", "pressed"
840                   }),
841            "RadioButton.icon", new GTKStyle.GTKLazyValue(
842                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
843                              "getRadioButtonIcon"),
844            "RadioButton.font", new FontLazyValue(Region.RADIO_BUTTON),
845            "RadioButton.margin", zeroInsets,
846
847
848            "RadioButtonMenuItem.arrowIcon", null,
849            "RadioButtonMenuItem.checkIcon", new GTKStyle.GTKLazyValue(
850                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
851                              "getRadioButtonMenuItemCheckIcon"),
852            "RadioButtonMenuItem.font", new FontLazyValue(Region.RADIO_BUTTON_MENU_ITEM),
853            "RadioButtonMenuItem.margin", zeroInsets,
854            "RadioButtonMenuItem.alignAcceleratorText", Boolean.FALSE,
855
856
857            // These bindings are only enabled when there is a default
858            // button set on the rootpane.
859            "RootPane.defaultButtonWindowKeyBindings", new Object[] {
860                               "ENTER", "press",
861                      "released ENTER", "release",
862                          "ctrl ENTER", "press",
863                 "ctrl released ENTER", "release"
864            },
865
866
867            "ScrollBar.squareButtons", Boolean.FALSE,
868            "ScrollBar.thumbHeight", Integer.valueOf(14),
869            "ScrollBar.width", Integer.valueOf(16),
870            "ScrollBar.minimumThumbSize", new Dimension(8, 8),
871            "ScrollBar.maximumThumbSize", new Dimension(4096, 4096),
872            "ScrollBar.allowsAbsolutePositioning", Boolean.TRUE,
873            "ScrollBar.alwaysShowThumb", Boolean.TRUE,
874            "ScrollBar.ancestorInputMap",
875                   new UIDefaults.LazyInputMap(new Object[] {
876                       "RIGHT", "positiveUnitIncrement",
877                    "KP_RIGHT", "positiveUnitIncrement",
878                        "DOWN", "positiveUnitIncrement",
879                     "KP_DOWN", "positiveUnitIncrement",
880                   "PAGE_DOWN", "positiveBlockIncrement",
881                        "LEFT", "negativeUnitIncrement",
882                     "KP_LEFT", "negativeUnitIncrement",
883                          "UP", "negativeUnitIncrement",
884                       "KP_UP", "negativeUnitIncrement",
885                     "PAGE_UP", "negativeBlockIncrement",
886                        "HOME", "minScroll",
887                         "END", "maxScroll"
888                   }),
889            "ScrollBar.ancestorInputMap.RightToLeft",
890                    new UIDefaults.LazyInputMap(new Object[] {
891                       "RIGHT", "negativeUnitIncrement",
892                    "KP_RIGHT", "negativeUnitIncrement",
893                        "LEFT", "positiveUnitIncrement",
894                     "KP_LEFT", "positiveUnitIncrement",
895                    }),
896
897
898            "Spinner.disableOnBoundaryValues", Boolean.TRUE,
899
900
901            "ScrollPane.fillUpperCorner", Boolean.TRUE,
902            "ScrollPane.fillLowerCorner", Boolean.TRUE,
903            "ScrollPane.ancestorInputMap",
904                    new UIDefaults.LazyInputMap(new Object[] {
905                           "RIGHT", "unitScrollRight",
906                        "KP_RIGHT", "unitScrollRight",
907                            "DOWN", "unitScrollDown",
908                         "KP_DOWN", "unitScrollDown",
909                            "LEFT", "unitScrollLeft",
910                         "KP_LEFT", "unitScrollLeft",
911                              "UP", "unitScrollUp",
912                           "KP_UP", "unitScrollUp",
913                         "PAGE_UP", "scrollUp",
914                       "PAGE_DOWN", "scrollDown",
915                    "ctrl PAGE_UP", "scrollLeft",
916                  "ctrl PAGE_DOWN", "scrollRight",
917                       "ctrl HOME", "scrollHome",
918                        "ctrl END", "scrollEnd"
919                    }),
920            "ScrollPane.ancestorInputMap.RightToLeft",
921                    new UIDefaults.LazyInputMap(new Object[] {
922                    "ctrl PAGE_UP", "scrollRight",
923                  "ctrl PAGE_DOWN", "scrollLeft",
924                    }),
925            "ScrollPane.font", new FontLazyValue(Region.SCROLL_PANE),
926
927
928            "Separator.insets", zeroInsets,
929            "Separator.thickness", Integer.valueOf(2),
930
931
932            "Slider.paintValue", Boolean.TRUE,
933            "Slider.thumbWidth", Integer.valueOf(30),
934            "Slider.thumbHeight", Integer.valueOf(14),
935            "Slider.focusInputMap",
936                    new UIDefaults.LazyInputMap(new Object[] {
937                            "RIGHT", "positiveUnitIncrement",
938                         "KP_RIGHT", "positiveUnitIncrement",
939                             "DOWN", "negativeUnitIncrement",
940                          "KP_DOWN", "negativeUnitIncrement",
941                        "PAGE_DOWN", "negativeBlockIncrement",
942                             "LEFT", "negativeUnitIncrement",
943                          "KP_LEFT", "negativeUnitIncrement",
944                               "UP", "positiveUnitIncrement",
945                            "KP_UP", "positiveUnitIncrement",
946                          "PAGE_UP", "positiveBlockIncrement",
947                             "HOME", "minScroll",
948                              "END", "maxScroll"
949                        }),
950            "Slider.focusInputMap.RightToLeft",
951                    new UIDefaults.LazyInputMap(new Object[] {
952                            "RIGHT", "negativeUnitIncrement",
953                         "KP_RIGHT", "negativeUnitIncrement",
954                             "LEFT", "positiveUnitIncrement",
955                          "KP_LEFT", "positiveUnitIncrement",
956                         }),
957            "Slider.onlyLeftMouseButtonDrag", Boolean.FALSE,
958
959            "Spinner.ancestorInputMap",
960               new UIDefaults.LazyInputMap(new Object[] {
961                               "UP", "increment",
962                            "KP_UP", "increment",
963                             "DOWN", "decrement",
964                          "KP_DOWN", "decrement",
965               }),
966            "Spinner.font", new FontLazyValue(Region.SPINNER),
967            "Spinner.editorAlignment", JTextField.LEADING,
968
969            "SplitPane.ancestorInputMap",
970                    new UIDefaults.LazyInputMap(new Object[] {
971                        "UP", "negativeIncrement",
972                      "DOWN", "positiveIncrement",
973                      "LEFT", "negativeIncrement",
974                     "RIGHT", "positiveIncrement",
975                     "KP_UP", "negativeIncrement",
976                   "KP_DOWN", "positiveIncrement",
977                   "KP_LEFT", "negativeIncrement",
978                  "KP_RIGHT", "positiveIncrement",
979                      "HOME", "selectMin",
980                       "END", "selectMax",
981                        "F8", "startResize",
982                        "F6", "toggleFocus",
983                  "ctrl TAB", "focusOutForward",
984            "ctrl shift TAB", "focusOutBackward"
985                    }),
986
987
988            "SplitPane.size", Integer.valueOf(7),
989            "SplitPane.oneTouchOffset", Integer.valueOf(2),
990            "SplitPane.oneTouchButtonSize", Integer.valueOf(5),
991            "SplitPane.supportsOneTouchButtons", Boolean.FALSE,
992
993
994            "TabbedPane.focusInputMap",
995              new UIDefaults.LazyInputMap(new Object[] {
996                         "RIGHT", "navigateRight",
997                      "KP_RIGHT", "navigateRight",
998                          "LEFT", "navigateLeft",
999                       "KP_LEFT", "navigateLeft",
1000                            "UP", "navigateUp",
1001                         "KP_UP", "navigateUp",
1002                          "DOWN", "navigateDown",
1003                       "KP_DOWN", "navigateDown",
1004                     "ctrl DOWN", "requestFocusForVisibleComponent",
1005                  "ctrl KP_DOWN", "requestFocusForVisibleComponent",
1006                         "SPACE", "selectTabWithFocus"
1007                }),
1008            "TabbedPane.ancestorInputMap",
1009               new UIDefaults.LazyInputMap(new Object[] {
1010                         "ctrl TAB", "navigateNext",
1011                   "ctrl shift TAB", "navigatePrevious",
1012                   "ctrl PAGE_DOWN", "navigatePageDown",
1013                     "ctrl PAGE_UP", "navigatePageUp",
1014                          "ctrl UP", "requestFocus",
1015                       "ctrl KP_UP", "requestFocus",
1016                 }),
1017
1018            "TabbedPane.labelShift", 3,
1019            "TabbedPane.selectedLabelShift", 3,
1020            "TabbedPane.font", new FontLazyValue(Region.TABBED_PANE),
1021            "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 0, 1),
1022
1023            "Table.scrollPaneBorder", zeroBorder,
1024            "Table.background", tableBg,
1025            "Table.focusCellBackground", tableFocusCellBg,
1026            "Table.focusCellForeground", tableFocusCellFg,
1027            "Table.focusCellHighlightBorder", focusBorder,
1028            "Table.focusSelectedCellHighlightBorder", focusSelectedBorder,
1029            "Table.ancestorInputMap",
1030                    new UIDefaults.LazyInputMap(new Object[] {
1031                               "ctrl C", "copy",
1032                               "ctrl V", "paste",
1033                               "ctrl X", "cut",
1034                                 "COPY", "copy",
1035                                "PASTE", "paste",
1036                                  "CUT", "cut",
1037                       "control INSERT", "copy",
1038                         "shift INSERT", "paste",
1039                         "shift DELETE", "cut",
1040                                "RIGHT", "selectNextColumn",
1041                             "KP_RIGHT", "selectNextColumn",
1042                          "shift RIGHT", "selectNextColumnExtendSelection",
1043                       "shift KP_RIGHT", "selectNextColumnExtendSelection",
1044                     "ctrl shift RIGHT", "selectNextColumnExtendSelection",
1045                  "ctrl shift KP_RIGHT", "selectNextColumnExtendSelection",
1046                           "ctrl RIGHT", "selectNextColumnChangeLead",
1047                        "ctrl KP_RIGHT", "selectNextColumnChangeLead",
1048                                 "LEFT", "selectPreviousColumn",
1049                              "KP_LEFT", "selectPreviousColumn",
1050                           "shift LEFT", "selectPreviousColumnExtendSelection",
1051                        "shift KP_LEFT", "selectPreviousColumnExtendSelection",
1052                      "ctrl shift LEFT", "selectPreviousColumnExtendSelection",
1053                   "ctrl shift KP_LEFT", "selectPreviousColumnExtendSelection",
1054                            "ctrl LEFT", "selectPreviousColumnChangeLead",
1055                         "ctrl KP_LEFT", "selectPreviousColumnChangeLead",
1056                                 "DOWN", "selectNextRow",
1057                              "KP_DOWN", "selectNextRow",
1058                           "shift DOWN", "selectNextRowExtendSelection",
1059                        "shift KP_DOWN", "selectNextRowExtendSelection",
1060                      "ctrl shift DOWN", "selectNextRowExtendSelection",
1061                   "ctrl shift KP_DOWN", "selectNextRowExtendSelection",
1062                            "ctrl DOWN", "selectNextRowChangeLead",
1063                         "ctrl KP_DOWN", "selectNextRowChangeLead",
1064                                   "UP", "selectPreviousRow",
1065                                "KP_UP", "selectPreviousRow",
1066                             "shift UP", "selectPreviousRowExtendSelection",
1067                          "shift KP_UP", "selectPreviousRowExtendSelection",
1068                        "ctrl shift UP", "selectPreviousRowExtendSelection",
1069                     "ctrl shift KP_UP", "selectPreviousRowExtendSelection",
1070                              "ctrl UP", "selectPreviousRowChangeLead",
1071                           "ctrl KP_UP", "selectPreviousRowChangeLead",
1072                                 "HOME", "selectFirstColumn",
1073                           "shift HOME", "selectFirstColumnExtendSelection",
1074                      "ctrl shift HOME", "selectFirstRowExtendSelection",
1075                            "ctrl HOME", "selectFirstRow",
1076                                  "END", "selectLastColumn",
1077                            "shift END", "selectLastColumnExtendSelection",
1078                       "ctrl shift END", "selectLastRowExtendSelection",
1079                             "ctrl END", "selectLastRow",
1080                              "PAGE_UP", "scrollUpChangeSelection",
1081                        "shift PAGE_UP", "scrollUpExtendSelection",
1082                   "ctrl shift PAGE_UP", "scrollLeftExtendSelection",
1083                         "ctrl PAGE_UP", "scrollLeftChangeSelection",
1084                            "PAGE_DOWN", "scrollDownChangeSelection",
1085                      "shift PAGE_DOWN", "scrollDownExtendSelection",
1086                 "ctrl shift PAGE_DOWN", "scrollRightExtendSelection",
1087                       "ctrl PAGE_DOWN", "scrollRightChangeSelection",
1088                                  "TAB", "selectNextColumnCell",
1089                            "shift TAB", "selectPreviousColumnCell",
1090                                "ENTER", "selectNextRowCell",
1091                          "shift ENTER", "selectPreviousRowCell",
1092                               "ctrl A", "selectAll",
1093                           "ctrl SLASH", "selectAll",
1094                      "ctrl BACK_SLASH", "clearSelection",
1095                               "ESCAPE", "cancel",
1096                                   "F2", "startEditing",
1097                                "SPACE", "addToSelection",
1098                           "ctrl SPACE", "toggleAndAnchor",
1099                          "shift SPACE", "extendTo",
1100                     "ctrl shift SPACE", "moveSelectionTo",
1101                                   "F8", "focusHeader"
1102                    }),
1103            "Table.ancestorInputMap.RightToLeft",
1104                    new UIDefaults.LazyInputMap(new Object[] {
1105                                "RIGHT", "selectPreviousColumn",
1106                             "KP_RIGHT", "selectPreviousColumn",
1107                          "shift RIGHT", "selectPreviousColumnExtendSelection",
1108                       "shift KP_RIGHT", "selectPreviousColumnExtendSelection",
1109                     "ctrl shift RIGHT", "selectPreviousColumnExtendSelection",
1110                  "ctrl shift KP_RIGHT", "selectPreviousColumnExtendSelection",
1111                          "shift RIGHT", "selectPreviousColumnChangeLead",
1112                       "shift KP_RIGHT", "selectPreviousColumnChangeLead",
1113                                 "LEFT", "selectNextColumn",
1114                              "KP_LEFT", "selectNextColumn",
1115                           "shift LEFT", "selectNextColumnExtendSelection",
1116                        "shift KP_LEFT", "selectNextColumnExtendSelection",
1117                      "ctrl shift LEFT", "selectNextColumnExtendSelection",
1118                   "ctrl shift KP_LEFT", "selectNextColumnExtendSelection",
1119                            "ctrl LEFT", "selectNextColumnChangeLead",
1120                         "ctrl KP_LEFT", "selectNextColumnChangeLead",
1121                         "ctrl PAGE_UP", "scrollRightChangeSelection",
1122                       "ctrl PAGE_DOWN", "scrollLeftChangeSelection",
1123                   "ctrl shift PAGE_UP", "scrollRightExtendSelection",
1124                 "ctrl shift PAGE_DOWN", "scrollLeftExtendSelection",
1125                    }),
1126            "Table.font", new FontLazyValue(Region.TABLE),
1127            "Table.ascendingSortIcon",  new GTKStyle.GTKLazyValue(
1128                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
1129                              "getAscendingSortIcon"),
1130            "Table.descendingSortIcon",  new GTKStyle.GTKLazyValue(
1131                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
1132                              "getDescendingSortIcon"),
1133
1134            "TableHeader.font", new FontLazyValue(Region.TABLE_HEADER),
1135            "TableHeader.alignSorterArrow", Boolean.TRUE,
1136
1137            "TextArea.caretForeground", caretColor,
1138            "TextArea.caretAspectRatio", defaultCaretAspectRatio,
1139            "TextArea.caretBlinkRate", caretBlinkRate,
1140            "TextArea.margin", zeroInsets,
1141            "TextArea.focusInputMap", multilineInputMap,
1142            "TextArea.font", new FontLazyValue(Region.TEXT_AREA),
1143
1144
1145            "TextField.caretForeground", caretColor,
1146            "TextField.caretAspectRatio", defaultCaretAspectRatio,
1147            "TextField.caretBlinkRate", caretBlinkRate,
1148            "TextField.margin", zeroInsets,
1149            "TextField.focusInputMap", fieldInputMap,
1150            "TextField.font", new FontLazyValue(Region.TEXT_FIELD),
1151
1152
1153            "TextPane.caretForeground", caretColor,
1154            "TextPane.caretAspectRatio", defaultCaretAspectRatio,
1155            "TextPane.caretBlinkRate", caretBlinkRate,
1156            "TextPane.margin", editorMargin,
1157            "TextPane.focusInputMap", multilineInputMap,
1158            "TextPane.font", new FontLazyValue(Region.TEXT_PANE),
1159
1160
1161            "TitledBorder.titleColor", controlText,
1162            "TitledBorder.border", new UIDefaults.LazyValue() {
1163                public Object createValue(UIDefaults table) {
1164                    return new GTKPainter.TitledBorder();
1165                }
1166            },
1167
1168            "ToggleButton.focusInputMap",
1169                   new UIDefaults.LazyInputMap(new Object[] {
1170                            "SPACE", "pressed",
1171                   "released SPACE", "released"
1172                   }),
1173            "ToggleButton.font", new FontLazyValue(Region.TOGGLE_BUTTON),
1174            "ToggleButton.margin", zeroInsets,
1175
1176
1177            "ToolBar.separatorSize", new DimensionUIResource(10, 10),
1178            "ToolBar.handleIcon", new UIDefaults.ActiveValue() {
1179                public Object createValue(UIDefaults table) {
1180                    return GTKIconFactory.getToolBarHandleIcon();
1181                }
1182            },
1183            "ToolBar.ancestorInputMap",
1184               new UIDefaults.LazyInputMap(new Object[] {
1185                        "UP", "navigateUp",
1186                     "KP_UP", "navigateUp",
1187                      "DOWN", "navigateDown",
1188                   "KP_DOWN", "navigateDown",
1189                      "LEFT", "navigateLeft",
1190                   "KP_LEFT", "navigateLeft",
1191                     "RIGHT", "navigateRight",
1192                  "KP_RIGHT", "navigateRight"
1193                 }),
1194            "ToolBar.font", new FontLazyValue(Region.TOOL_BAR),
1195
1196            "ToolTip.font", new FontLazyValue(Region.TOOL_TIP),
1197
1198            "Tree.padding", Integer.valueOf(4),
1199            "Tree.background", tableBg,
1200            "Tree.drawHorizontalLines", Boolean.FALSE,
1201            "Tree.drawVerticalLines", Boolean.FALSE,
1202            "Tree.rowHeight", Integer.valueOf(-1),
1203            "Tree.scrollsOnExpand", Boolean.FALSE,
1204            "Tree.expanderSize", Integer.valueOf(10),
1205            "Tree.repaintWholeRow", Boolean.TRUE,
1206            "Tree.closedIcon", null,
1207            "Tree.leafIcon", null,
1208            "Tree.openIcon", null,
1209            "Tree.expandedIcon", new GTKStyle.GTKLazyValue(
1210                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
1211                              "getTreeExpandedIcon"),
1212            "Tree.collapsedIcon", new GTKStyle.GTKLazyValue(
1213                              "com.sun.java.swing.plaf.gtk.GTKIconFactory",
1214                              "getTreeCollapsedIcon"),
1215            "Tree.leftChildIndent", Integer.valueOf(2),
1216            "Tree.rightChildIndent", Integer.valueOf(12),
1217            "Tree.scrollsHorizontallyAndVertically", Boolean.FALSE,
1218            "Tree.drawsFocusBorder", Boolean.TRUE,
1219            "Tree.focusInputMap",
1220                    new UIDefaults.LazyInputMap(new Object[] {
1221                                 "ctrl C", "copy",
1222                                 "ctrl V", "paste",
1223                                 "ctrl X", "cut",
1224                                   "COPY", "copy",
1225                                  "PASTE", "paste",
1226                                    "CUT", "cut",
1227                         "control INSERT", "copy",
1228                           "shift INSERT", "paste",
1229                           "shift DELETE", "cut",
1230                                     "UP", "selectPrevious",
1231                                  "KP_UP", "selectPrevious",
1232                               "shift UP", "selectPreviousExtendSelection",
1233                            "shift KP_UP", "selectPreviousExtendSelection",
1234                          "ctrl shift UP", "selectPreviousExtendSelection",
1235                       "ctrl shift KP_UP", "selectPreviousExtendSelection",
1236                                "ctrl UP", "selectPreviousChangeLead",
1237                             "ctrl KP_UP", "selectPreviousChangeLead",
1238                                   "DOWN", "selectNext",
1239                                "KP_DOWN", "selectNext",
1240                             "shift DOWN", "selectNextExtendSelection",
1241                          "shift KP_DOWN", "selectNextExtendSelection",
1242                        "ctrl shift DOWN", "selectNextExtendSelection",
1243                     "ctrl shift KP_DOWN", "selectNextExtendSelection",
1244                              "ctrl DOWN", "selectNextChangeLead",
1245                           "ctrl KP_DOWN", "selectNextChangeLead",
1246                                  "RIGHT", "selectChild",
1247                               "KP_RIGHT", "selectChild",
1248                                   "LEFT", "selectParent",
1249                                "KP_LEFT", "selectParent",
1250                                "typed +", "expand",
1251                                "typed -", "collapse",
1252                             "BACK_SPACE", "moveSelectionToParent",
1253                                "PAGE_UP", "scrollUpChangeSelection",
1254                          "shift PAGE_UP", "scrollUpExtendSelection",
1255                     "ctrl shift PAGE_UP", "scrollUpExtendSelection",
1256                           "ctrl PAGE_UP", "scrollUpChangeLead",
1257                              "PAGE_DOWN", "scrollDownChangeSelection",
1258                        "shift PAGE_DOWN", "scrollDownExtendSelection",
1259                   "ctrl shift PAGE_DOWN", "scrollDownExtendSelection",
1260                         "ctrl PAGE_DOWN", "scrollDownChangeLead",
1261                                   "HOME", "selectFirst",
1262                             "shift HOME", "selectFirstExtendSelection",
1263                        "ctrl shift HOME", "selectFirstExtendSelection",
1264                              "ctrl HOME", "selectFirstChangeLead",
1265                                    "END", "selectLast",
1266                              "shift END", "selectLastExtendSelection",
1267                         "ctrl shift END", "selectLastExtendSelection",
1268                               "ctrl END", "selectLastChangeLead",
1269                                     "F2", "startEditing",
1270                                 "ctrl A", "selectAll",
1271                             "ctrl SLASH", "selectAll",
1272                        "ctrl BACK_SLASH", "clearSelection",
1273                              "ctrl LEFT", "scrollLeft",
1274                           "ctrl KP_LEFT", "scrollLeft",
1275                             "ctrl RIGHT", "scrollRight",
1276                          "ctrl KP_RIGHT", "scrollRight",
1277                                  "SPACE", "addToSelection",
1278                             "ctrl SPACE", "toggleAndAnchor",
1279                            "shift SPACE", "extendTo",
1280                       "ctrl shift SPACE", "moveSelectionTo"
1281                    }),
1282            "Tree.focusInputMap.RightToLeft",
1283                    new UIDefaults.LazyInputMap(new Object[] {
1284                                  "RIGHT", "selectParent",
1285                               "KP_RIGHT", "selectParent",
1286                                   "LEFT", "selectChild",
1287                                "KP_LEFT", "selectChild",
1288                 }),
1289            "Tree.ancestorInputMap",
1290                      new UIDefaults.LazyInputMap(new Object[] {
1291                         "ESCAPE", "cancel"
1292                      }),
1293            "Tree.font", new FontLazyValue(Region.TREE),
1294
1295            "Viewport.font", new FontLazyValue(Region.VIEWPORT)
1296        };
1297        table.putDefaults(defaults);
1298
1299        if (fallbackFont != null) {
1300            table.put("TitledBorder.font", fallbackFont);
1301        }
1302        if (aaTextInfo != null) {
1303            table.putAll(aaTextInfo);
1304        }
1305    }
1306
1307    protected void initSystemColorDefaults(UIDefaults table) {
1308        GTKStyleFactory factory = (GTKStyleFactory)getStyleFactory();
1309        GTKStyle windowStyle =
1310                (GTKStyle)factory.getStyle(null, Region.INTERNAL_FRAME);
1311        table.put("window", windowStyle.getGTKColor(SynthConstants.ENABLED,
1312                GTKColorType.BACKGROUND));
1313        table.put("windowText", windowStyle.getGTKColor(SynthConstants.ENABLED,
1314                GTKColorType.TEXT_FOREGROUND));
1315
1316        GTKStyle entryStyle = (GTKStyle)factory.getStyle(null, Region.TEXT_FIELD);
1317        table.put("text", entryStyle.getGTKColor(SynthConstants.ENABLED,
1318                                           GTKColorType.TEXT_BACKGROUND));
1319        table.put("textText", entryStyle.getGTKColor(SynthConstants.ENABLED,
1320                                           GTKColorType.TEXT_FOREGROUND));
1321        table.put("textHighlight",
1322                entryStyle.getGTKColor(SynthConstants.SELECTED,
1323                                         GTKColorType.TEXT_BACKGROUND));
1324        table.put("textHighlightText",
1325                  entryStyle.getGTKColor(SynthConstants.SELECTED,
1326                                         GTKColorType.TEXT_FOREGROUND));
1327        table.put("textInactiveText",
1328                  entryStyle.getGTKColor(SynthConstants.DISABLED,
1329                                         GTKColorType.TEXT_FOREGROUND));
1330        Object caretColor =
1331            entryStyle.getClassSpecificValue("cursor-color");
1332        if (caretColor == null) {
1333            caretColor = GTKStyle.BLACK_COLOR;
1334        }
1335        table.put("caretColor", caretColor);
1336
1337        GTKStyle menuStyle = (GTKStyle)factory.getStyle(null, Region.MENU_ITEM);
1338        table.put("menu", menuStyle.getGTKColor(SynthConstants.ENABLED,
1339                                           GTKColorType.BACKGROUND));
1340        table.put("menuText", menuStyle.getGTKColor(SynthConstants.ENABLED,
1341                                           GTKColorType.TEXT_FOREGROUND));
1342
1343        GTKStyle scrollbarStyle = (GTKStyle)factory.getStyle(null, Region.SCROLL_BAR);
1344        table.put("scrollbar", scrollbarStyle.getGTKColor(SynthConstants.ENABLED,
1345                                           GTKColorType.BACKGROUND));
1346
1347        GTKStyle infoStyle = (GTKStyle)factory.getStyle(null, Region.OPTION_PANE);
1348        table.put("info", infoStyle.getGTKColor(SynthConstants.ENABLED,
1349                                           GTKColorType.BACKGROUND));
1350        table.put("infoText", infoStyle.getGTKColor(SynthConstants.ENABLED,
1351                                           GTKColorType.TEXT_FOREGROUND));
1352
1353        GTKStyle desktopStyle = (GTKStyle)factory.getStyle(null, Region.DESKTOP_PANE);
1354        table.put("desktop", desktopStyle.getGTKColor(SynthConstants.ENABLED,
1355                                           GTKColorType.BACKGROUND));
1356
1357        // colors specific only for GTK
1358        // It is impossible to create a simple GtkWidget without specifying the
1359        // type. So for GtkWidget we can use any appropriate concrete type of
1360        // wigdet. LABEL in this case.
1361        GTKStyle widgetStyle = (GTKStyle)factory.getStyle(null, Region.LABEL);
1362        Color bg = widgetStyle.getGTKColor(SynthConstants.ENABLED,
1363                                           GTKColorType.BACKGROUND);
1364        table.put("control", bg);
1365        table.put("controlHighlight", bg);
1366        table.put("controlText", widgetStyle.getGTKColor(SynthConstants.ENABLED,
1367                                               GTKColorType.TEXT_FOREGROUND));
1368        table.put("controlLtHighlight", widgetStyle.getGTKColor(
1369                SynthConstants.ENABLED, GTKColorType.LIGHT));
1370        table.put("controlShadow", widgetStyle.getGTKColor(
1371                SynthConstants.ENABLED, GTKColorType.DARK));
1372        table.put("controlDkShadow", widgetStyle.getGTKColor(
1373                SynthConstants.ENABLED, GTKColorType.BLACK));
1374        table.put("light", widgetStyle.getGTKColor(
1375                SynthConstants.ENABLED, GTKColorType.LIGHT));
1376        table.put("mid", widgetStyle.getGTKColor(
1377                SynthConstants.ENABLED, GTKColorType.MID));
1378        table.put("dark", widgetStyle.getGTKColor(
1379                SynthConstants.ENABLED, GTKColorType.DARK));
1380        table.put("black", widgetStyle.getGTKColor(
1381                SynthConstants.ENABLED, GTKColorType.BLACK));
1382        table.put("white", widgetStyle.getGTKColor(
1383                SynthConstants.ENABLED, GTKColorType.WHITE));
1384    }
1385
1386    /**
1387     * Creates the GTK look and feel class for the passed in Component.
1388     */
1389    public static ComponentUI createUI(JComponent c) {
1390        String key = c.getUIClassID().intern();
1391
1392        if (key == "FileChooserUI") {
1393            return GTKFileChooserUI.createUI(c);
1394        }
1395        return SynthLookAndFeel.createUI(c);
1396    }
1397
1398    /**
1399     * Returns the cached gtkThemeName
1400     */
1401    static String getGtkThemeName() {
1402        return gtkThemeName;
1403    }
1404
1405    static boolean isLeftToRight(Component c) {
1406        return c.getComponentOrientation().isLeftToRight();
1407    }
1408
1409    public void initialize() {
1410        /*
1411         * We need to call loadGTK() to ensure that the native GTK
1412         * libraries are loaded.  It is very unlikely that this call will
1413         * fail (since we've already verified native GTK support in
1414         * isSupportedLookAndFeel()), but we can throw an error in the
1415         * failure situation just in case.
1416         */
1417        Toolkit toolkit = Toolkit.getDefaultToolkit();
1418        if (toolkit instanceof UNIXToolkit &&
1419            !((UNIXToolkit)toolkit).loadGTK())
1420        {
1421            throw new InternalError("Unable to load native GTK libraries");
1422        }
1423
1424        if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK2) {
1425            String version = AccessController.doPrivileged(
1426                    new GetPropertyAction("jdk.gtk.version"));
1427            if (version != null) {
1428                IS_22 = version.equals("2.2");
1429            } else {
1430                IS_22 = true;
1431            }
1432        } else if (UNIXToolkit.getGtkVersion() ==
1433                                UNIXToolkit.GtkVersions.GTK3) {
1434            IS_3 = true;
1435        }
1436
1437        super.initialize();
1438        inInitialize = true;
1439        loadStyles();
1440        inInitialize = false;
1441
1442        /*
1443         * Check if system AA font settings should be used.
1444         * REMIND: See comment on isLocalDisplay() definition regarding
1445         * XRender.
1446         */
1447        gtkAAFontSettingsCond = SwingUtilities2.isLocalDisplay();
1448        aaTextInfo = new HashMap<>(2);
1449        SwingUtilities2.putAATextInfo(gtkAAFontSettingsCond, aaTextInfo);
1450    }
1451
1452    static ReferenceQueue<GTKLookAndFeel> queue = new ReferenceQueue<GTKLookAndFeel>();
1453
1454    private static void flushUnreferenced() {
1455        WeakPCL pcl;
1456
1457        while ((pcl = (WeakPCL)queue.poll()) != null) {
1458            pcl.dispose();
1459        }
1460    }
1461
1462    static class WeakPCL extends WeakReference<GTKLookAndFeel> implements
1463            PropertyChangeListener {
1464        private Toolkit kit;
1465        private String key;
1466
1467        WeakPCL(GTKLookAndFeel target, Toolkit kit, String key) {
1468            super(target, queue);
1469            this.kit = kit;
1470            this.key = key;
1471        }
1472
1473        public String getKey() { return key; }
1474
1475        public void propertyChange(final PropertyChangeEvent pce) {
1476            final GTKLookAndFeel lnf = get();
1477
1478            if (lnf == null || UIManager.getLookAndFeel() != lnf) {
1479                // The property was GC'ed, we're no longer interested in
1480                // PropertyChanges, remove the listener.
1481                dispose();
1482            }
1483            else {
1484                // We are using invokeLater here because we are getting called
1485                // on the AWT-Motif thread which can cause a deadlock.
1486                SwingUtilities.invokeLater(new Runnable() {
1487                    public void run() {
1488                        String name = pce.getPropertyName();
1489                        /* We are listening for GTK desktop text AA settings:
1490                         * "gnome.Xft/Antialias" and "gnome.Xft/RGBA".
1491                         * However we don't need to read these here as
1492                         * the UIDefaults reads them and this event causes
1493                         * those to be reinitialised.
1494                         */
1495                        if ("gnome.Net/ThemeName".equals(name)) {
1496                            GTKEngine.INSTANCE.themeChanged();
1497                            GTKIconFactory.resetIcons();
1498                        }
1499                        lnf.loadStyles();
1500                        Window appWindows[] = Window.getWindows();
1501                        for (int i = 0; i < appWindows.length; i++) {
1502                            SynthLookAndFeel.updateStyles(appWindows[i]);
1503                        }
1504                    }
1505                });
1506            }
1507        }
1508
1509        void dispose() {
1510            kit.removePropertyChangeListener(key, this);
1511        }
1512    }
1513
1514    public boolean isSupportedLookAndFeel() {
1515        Toolkit toolkit = Toolkit.getDefaultToolkit();
1516        return (toolkit instanceof SunToolkit &&
1517                ((SunToolkit)toolkit).isNativeGTKAvailable());
1518    }
1519
1520    public boolean isNativeLookAndFeel() {
1521        return true;
1522    }
1523
1524    public String getDescription() {
1525        return "GTK look and feel";
1526    }
1527
1528    public String getName() {
1529        return "GTK look and feel";
1530    }
1531
1532    public String getID() {
1533        return "GTK";
1534    }
1535
1536    // Subclassed to pass in false to the superclass, we don't want to try
1537    // and load the system colors.
1538    protected void loadSystemColors(UIDefaults table, String[] systemColors, boolean useNative) {
1539        super.loadSystemColors(table, systemColors, false);
1540    }
1541
1542    private void loadStyles() {
1543        gtkThemeName = (String)Toolkit.getDefaultToolkit().
1544                getDesktopProperty("gnome.Net/ThemeName");
1545
1546        setStyleFactory(getGTKStyleFactory());
1547
1548        // If we are in initialize initializations will be
1549        // called later, don't do it now.
1550        if (!inInitialize) {
1551            UIDefaults table = UIManager.getLookAndFeelDefaults();
1552            initSystemColorDefaults(table);
1553            initComponentDefaults(table);
1554        }
1555    }
1556
1557    private GTKStyleFactory getGTKStyleFactory() {
1558
1559        GTKEngine engine = GTKEngine.INSTANCE;
1560        Object iconSizes = engine.getSetting(GTKEngine.Settings.GTK_ICON_SIZES);
1561        if (iconSizes instanceof String) {
1562            if (!configIconSizes((String)iconSizes)) {
1563                System.err.println("Error parsing gtk-icon-sizes string: '" + iconSizes + "'");
1564            }
1565        }
1566
1567        // Desktop property appears to have preference over rc font.
1568        Object fontName = Toolkit.getDefaultToolkit().getDesktopProperty(
1569                                  "gnome.Gtk/FontName");
1570
1571       if (!(fontName instanceof String)) {
1572            fontName = engine.getSetting(GTKEngine.Settings.GTK_FONT_NAME);
1573            if (!(fontName instanceof String)) {
1574               fontName = "sans 10";
1575            }
1576        }
1577
1578        if (styleFactory == null) {
1579            styleFactory = new GTKStyleFactory();
1580        }
1581
1582        Font defaultFont = PangoFonts.lookupFont((String)fontName);
1583        fallbackFont = defaultFont;
1584        styleFactory.initStyles(defaultFont);
1585
1586        return styleFactory;
1587    }
1588
1589    private boolean configIconSizes(String sizeString) {
1590        String[] sizes = sizeString.split(":");
1591        for (int i = 0; i < sizes.length; i++) {
1592            String[] splits = sizes[i].split("=");
1593
1594            if (splits.length != 2) {
1595                return false;
1596            }
1597
1598            String size = splits[0].trim().intern();
1599            if (size.length() < 1) {
1600                return false;
1601            }
1602
1603            splits = splits[1].split(",");
1604
1605            if (splits.length != 2) {
1606                return false;
1607            }
1608
1609            String width = splits[0].trim();
1610            String height = splits[1].trim();
1611
1612            if (width.length() < 1 || height.length() < 1) {
1613                return false;
1614            }
1615
1616            int w;
1617            int h;
1618
1619            try {
1620                w = Integer.parseInt(width);
1621                h = Integer.parseInt(height);
1622            } catch (NumberFormatException nfe) {
1623                return false;
1624            }
1625
1626            if (w > 0 && h > 0) {
1627                int type = GTKStyle.GTKStockIconInfo.getIconType(size);
1628                GTKStyle.GTKStockIconInfo.setIconSize(type, w, h);
1629            } else {
1630                System.err.println("Invalid size in gtk-icon-sizes: " + w + "," + h);
1631            }
1632        }
1633
1634        return true;
1635    }
1636
1637    /**
1638     * Returns whether or not the UIs should update their
1639     * <code>SynthStyles</code> from the <code>SynthStyleFactory</code>
1640     * when the ancestor of the Component changes.
1641     *
1642     * @return whether or not the UIs should update their
1643     * <code>SynthStyles</code> from the <code>SynthStyleFactory</code>
1644     * when the ancestor changed.
1645     */
1646    public boolean shouldUpdateStyleOnAncestorChanged() {
1647        return true;
1648    }
1649
1650    /**
1651     * {@inheritDoc}
1652     */
1653    public LayoutStyle getLayoutStyle() {
1654        return GnomeLayoutStyle.INSTANCE;
1655    }
1656
1657
1658    /**
1659     * Gnome layout style.  From:
1660     * http://developer.gnome.org/projects/gup/hig/2.0/design-window.html#window-layout-spacing
1661     * You'll notice this doesn't do the radiobutton/checkbox border
1662     * adjustments that windows/metal do.  This is because gtk doesn't
1663     * provide margins/insets for checkbox/radiobuttons.
1664     */
1665    @SuppressWarnings("fallthrough")
1666    private static class GnomeLayoutStyle extends DefaultLayoutStyle {
1667        private static GnomeLayoutStyle INSTANCE = new GnomeLayoutStyle();
1668
1669        @Override
1670        public int getPreferredGap(JComponent component1,
1671                JComponent component2, ComponentPlacement type, int position,
1672                Container parent) {
1673            // Checks args
1674            super.getPreferredGap(component1, component2, type, position,
1675                                  parent);
1676
1677            switch(type) {
1678            case INDENT:
1679                if (position == SwingConstants.EAST ||
1680                        position == SwingConstants.WEST) {
1681                    // Indent group members 12 pixels to denote hierarchy and
1682                    // association.
1683                    return 12;
1684                }
1685                // Fall through to related
1686            // As a basic rule of thumb, leave space between user
1687            // interface components in increments of 6 pixels, going up as
1688            // the relationship between related elements becomes more
1689            // distant. For example, between icon labels and associated
1690            // graphics within an icon, 6 pixels are adequate. Between
1691            // labels and associated components, leave 12 horizontal
1692            // pixels. For vertical spacing between groups of components,
1693            // 18 pixels is adequate.
1694            //
1695            // The first part of this is handled automatically by Icon (which
1696            // won't give you 6 pixels).
1697            case RELATED:
1698                if (isLabelAndNonlabel(component1, component2, position)) {
1699                    return 12;
1700                }
1701                return 6;
1702            case UNRELATED:
1703                return 12;
1704            }
1705            return 0;
1706        }
1707
1708        @Override
1709        public int getContainerGap(JComponent component, int position,
1710                                   Container parent) {
1711            // Checks args
1712            super.getContainerGap(component, position, parent);
1713            // A general padding of 12 pixels is
1714            // recommended between the contents of a dialog window and the
1715            // window borders.
1716            return 12;
1717        }
1718    }
1719}
1720