alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (GTKStyle.java)

This example Java source code file (GTKStyle.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awt, color, colortype, dimension, dimensionuiresource, font, gtkstockicon, image, insets, jcomponent, object, override, plaf, reflection, region, security, string, swing, synthstyle, util

The GTKStyle.java Java example source code

/*
 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.java.swing.plaf.gtk;

import java.awt.*;
import java.lang.reflect.*;
import java.security.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.synth.*;

import sun.awt.AppContext;
import sun.awt.UNIXToolkit;
import sun.swing.SwingUtilities2;
import sun.swing.plaf.synth.SynthIcon;

import com.sun.java.swing.plaf.gtk.GTKEngine.WidgetType;

/**
 *
 * @author Scott Violet
 */
class GTKStyle extends SynthStyle implements GTKConstants {

    private static native int nativeGetXThickness(int widgetType);
    private static native int nativeGetYThickness(int widgetType);
    private static native int nativeGetColorForState(int widgetType,
                                                     int state, int typeID);
    private static native Object nativeGetClassValue(int widgetType,
                                                     String key);
    private static native String nativeGetPangoFontName(int widgetType);

    private static final String ICON_PROPERTY_PREFIX = "gtk.icon.";

    static final Color BLACK_COLOR = new ColorUIResource(Color.BLACK);
    static final Color WHITE_COLOR = new ColorUIResource(Color.WHITE);

    static final Font DEFAULT_FONT = new FontUIResource("sansserif",
                                                        Font.PLAIN, 10  );
    static final Insets BUTTON_DEFAULT_BORDER_INSETS = new Insets(1, 1, 1, 1);

    private static final GTKGraphicsUtils GTK_GRAPHICS = new GTKGraphicsUtils();

    /**
     * Maps from a key that is passed to Style.get to the equivalent class
     * specific key.
     */
    private static final Map<String,String> CLASS_SPECIFIC_MAP;

    /**
     * Backing style properties that are used if the style does not
     * defined the property.
     */
    private static final Map<String,GTKStockIcon> ICONS_MAP;

    /**
     * The font used for this particular style, as determined at
     * construction time.
     */
    private final Font font;

    /** Widget type used when looking up class specific values. */
    private final int widgetType;

    /** The x/y thickness values for this particular style. */
    private final int xThickness, yThickness;

    GTKStyle(Font userFont, WidgetType widgetType) {
        this.widgetType = widgetType.ordinal();

        String pangoFontName;
        synchronized (sun.awt.UNIXToolkit.GTK_LOCK) {
            xThickness = nativeGetXThickness(this.widgetType);
            yThickness = nativeGetYThickness(this.widgetType);
            pangoFontName = nativeGetPangoFontName(this.widgetType);
        }

        Font pangoFont = null;
        if (pangoFontName != null) {
            pangoFont = PangoFonts.lookupFont(pangoFontName);
        }
        if (pangoFont != null) {
            this.font = pangoFont;
        } else if (userFont != null) {
            this.font = userFont;
        } else {
            this.font = DEFAULT_FONT;
        }
    }

    @Override
    public void installDefaults(SynthContext context) {
        super.installDefaults(context);
        if (!context.getRegion().isSubregion()) {
            context.getComponent().putClientProperty(
                SwingUtilities2.AA_TEXT_PROPERTY_KEY,
                GTKLookAndFeel.aaTextInfo);
        }
    }

    @Override
    public SynthGraphicsUtils getGraphicsUtils(SynthContext context) {
        return GTK_GRAPHICS;
    }

    /**
     * Returns a <code>SynthPainter that will route the appropriate
     * calls to a <code>GTKEngine.
     *
     * @param state SynthContext identifying requestor
     * @return SynthPainter
     */
    @Override
    public SynthPainter getPainter(SynthContext state) {
        return GTKPainter.INSTANCE;
    }

    protected Color getColorForState(SynthContext context, ColorType type) {
        if (type == ColorType.FOCUS || type == GTKColorType.BLACK) {
            return BLACK_COLOR;
        }
        else if (type == GTKColorType.WHITE) {
            return WHITE_COLOR;
        }

        Region id = context.getRegion();
        int state = context.getComponentState();
        state = GTKLookAndFeel.synthStateToGTKState(id, state);

        if (type == ColorType.TEXT_FOREGROUND &&
               (id == Region.BUTTON ||
                id == Region.CHECK_BOX ||
                id == Region.CHECK_BOX_MENU_ITEM ||
                id == Region.MENU ||
                id == Region.MENU_ITEM ||
                id == Region.RADIO_BUTTON ||
                id == Region.RADIO_BUTTON_MENU_ITEM ||
                id == Region.TABBED_PANE_TAB ||
                id == Region.TOGGLE_BUTTON ||
                id == Region.TOOL_TIP ||
                id == Region.MENU_ITEM_ACCELERATOR ||
                id == Region.TABBED_PANE_TAB)) {
            type = ColorType.FOREGROUND;
        } else if (id == Region.TABLE ||
                   id == Region.LIST ||
                   id == Region.TREE ||
                   id == Region.TREE_CELL) {
            if (type == ColorType.FOREGROUND) {
                type = ColorType.TEXT_FOREGROUND;
                if (state == SynthConstants.PRESSED) {
                    state = SynthConstants.SELECTED;
                }
            } else if (type == ColorType.BACKGROUND) {
                type = ColorType.TEXT_BACKGROUND;
            }
        }

        return getStyleSpecificColor(context, state, type);
    }

    /**
     * Returns color specific to the current style. This method is
     * invoked when other variants don't fit.
     */
    private Color getStyleSpecificColor(SynthContext context, int state,
                                        ColorType type)
    {
        state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal();
        synchronized (sun.awt.UNIXToolkit.GTK_LOCK) {
            int rgb = nativeGetColorForState(widgetType, state,
                                             type.getID());
            return new ColorUIResource(rgb);
        }
    }

    Color getGTKColor(int state, ColorType type) {
        return getGTKColor(null, state, type);
    }

    /**
     * Returns the color for the specified state.
     *
     * @param context SynthContext identifying requestor
     * @param state to get the color for
     * @param type of the color
     * @return Color to render with
     */
    Color getGTKColor(SynthContext context, int state, ColorType type) {
        if (context != null) {
            JComponent c = context.getComponent();
            Region id = context.getRegion();

            state = GTKLookAndFeel.synthStateToGTKState(id, state);
            if (!id.isSubregion() &&
                (state & SynthConstants.ENABLED) != 0) {
                if (type == ColorType.BACKGROUND ||
                    type == ColorType.TEXT_BACKGROUND) {
                    Color bg = c.getBackground();
                    if (!(bg instanceof UIResource)) {
                        return bg;
                    }
                }
                else if (type == ColorType.FOREGROUND ||
                         type == ColorType.TEXT_FOREGROUND) {
                    Color fg = c.getForeground();
                    if (!(fg instanceof UIResource)) {
                        return fg;
                    }
                }
            }
        }

        return getStyleSpecificColor(context, state, type);
    }

    @Override
    public Color getColor(SynthContext context, ColorType type) {
        JComponent c = context.getComponent();
        Region id = context.getRegion();
        int state = context.getComponentState();

        if (c.getName() == "Table.cellRenderer") {
             if (type == ColorType.BACKGROUND) {
                 return c.getBackground();
             }
             if (type == ColorType.FOREGROUND) {
                 return c.getForeground();
             }
        }

        if (id == Region.LABEL && type == ColorType.TEXT_FOREGROUND) {
            type = ColorType.FOREGROUND;
        }

        // For the enabled state, prefer the widget's colors
        if (!id.isSubregion() && (state & SynthConstants.ENABLED) != 0) {
            if (type == ColorType.BACKGROUND) {
                return c.getBackground();
            }
            else if (type == ColorType.FOREGROUND) {
                return c.getForeground();
            }
            else if (type == ColorType.TEXT_FOREGROUND) {
                // If getForeground returns a non-UIResource it means the
                // developer has explicitly set the foreground, use it over
                // that of TEXT_FOREGROUND as that is typically the expected
                // behavior.
                Color color = c.getForeground();
                if (color != null && !(color instanceof UIResource)) {
                    return color;
                }
            }
        }
        return getColorForState(context, type);
    }

    protected Font getFontForState(SynthContext context) {
        return font;
    }

    /**
     * Returns the X thickness to use for this GTKStyle.
     *
     * @return x thickness.
     */
    int getXThickness() {
        return xThickness;
    }

    /**
     * Returns the Y thickness to use for this GTKStyle.
     *
     * @return y thickness.
     */
    int getYThickness() {
        return yThickness;
    }

    /**
     * Returns the Insets. If <code>insets is non-null the resulting
     * insets will be placed in it, otherwise a new Insets object will be
     * created and returned.
     *
     * @param context SynthContext identifying requestor
     * @param insets Where to place Insets
     * @return Insets.
     */
    @Override
    public Insets getInsets(SynthContext state, Insets insets) {
        Region id = state.getRegion();
        JComponent component = state.getComponent();
        String name = (id.isSubregion()) ? null : component.getName();

        if (insets == null) {
            insets = new Insets(0, 0, 0, 0);
        } else {
            insets.top = insets.bottom = insets.left = insets.right = 0;
        }

        if (id == Region.ARROW_BUTTON || id == Region.BUTTON ||
                id == Region.TOGGLE_BUTTON) {
            if ("Spinner.previousButton" == name ||
                    "Spinner.nextButton" == name) {
                return getSimpleInsets(state, insets, 1);
            } else {
                return getButtonInsets(state, insets);
            }
        }
        else if (id == Region.CHECK_BOX || id == Region.RADIO_BUTTON) {
            return getRadioInsets(state, insets);
        }
        else if (id == Region.MENU_BAR) {
            return getMenuBarInsets(state, insets);
        }
        else if (id == Region.MENU ||
                 id == Region.MENU_ITEM ||
                 id == Region.CHECK_BOX_MENU_ITEM ||
                 id == Region.RADIO_BUTTON_MENU_ITEM) {
            return getMenuItemInsets(state, insets);
        }
        else if (id == Region.FORMATTED_TEXT_FIELD) {
            return getTextFieldInsets(state, insets);
        }
        else if (id == Region.INTERNAL_FRAME) {
            insets = Metacity.INSTANCE.getBorderInsets(state, insets);
        }
        else if (id == Region.LABEL) {
            if ("TableHeader.renderer" == name) {
                return getButtonInsets(state, insets);
            }
            else if (component instanceof ListCellRenderer) {
                return getTextFieldInsets(state, insets);
            }
            else if ("Tree.cellRenderer" == name) {
                return getSimpleInsets(state, insets, 1);
            }
        }
        else if (id == Region.OPTION_PANE) {
            return getSimpleInsets(state, insets, 6);
        }
        else if (id == Region.POPUP_MENU) {
            return getSimpleInsets(state, insets, 2);
        }
        else if (id == Region.PROGRESS_BAR || id == Region.SLIDER ||
                 id == Region.TABBED_PANE  || id == Region.TABBED_PANE_CONTENT ||
                 id == Region.TOOL_BAR     ||
                 id == Region.TOOL_BAR_DRAG_WINDOW ||
                 id == Region.TOOL_TIP) {
            return getThicknessInsets(state, insets);
        }
        else if (id == Region.SCROLL_BAR) {
            return getScrollBarInsets(state, insets);
        }
        else if (id == Region.SLIDER_TRACK) {
            return getSliderTrackInsets(state, insets);
        }
        else if (id == Region.TABBED_PANE_TAB) {
            return getTabbedPaneTabInsets(state, insets);
        }
        else if (id == Region.TEXT_FIELD || id == Region.PASSWORD_FIELD) {
            if (name == "Tree.cellEditor") {
                return getSimpleInsets(state, insets, 1);
            }
            return getTextFieldInsets(state, insets);
        } else if (id == Region.SEPARATOR ||
                   id == Region.POPUP_MENU_SEPARATOR ||
                   id == Region.TOOL_BAR_SEPARATOR) {
            return getSeparatorInsets(state, insets);
        } else if (id == GTKEngine.CustomRegion.TITLED_BORDER) {
            return getThicknessInsets(state, insets);
        }
        return insets;
    }

    private Insets getButtonInsets(SynthContext context, Insets insets) {
        // The following calculations are derived from gtkbutton.c
        // (GTK+ version 2.8.20), gtk_button_size_allocate() method.
        int CHILD_SPACING = 1;
        int focusSize = getClassSpecificIntValue(context, "focus-line-width",1);
        int focusPad = getClassSpecificIntValue(context, "focus-padding", 1);
        int xThickness = getXThickness();
        int yThickness = getYThickness();
        int w = focusSize + focusPad + xThickness + CHILD_SPACING;
        int h = focusSize + focusPad + yThickness + CHILD_SPACING;
        insets.left = insets.right = w;
        insets.top = insets.bottom = h;

        Component component = context.getComponent();
        if ((component instanceof JButton) &&
            !(component.getParent() instanceof JToolBar) &&
            ((JButton)component).isDefaultCapable())
        {
            // Include the default border insets, but only for JButtons
            // that are default capable.  Note that
            // JButton.getDefaultCapable() returns true by default, but
            // GtkToolButtons are never default capable, so we skip this
            // step if the button is contained in a toolbar.
            Insets defaultInsets = getClassSpecificInsetsValue(context,
                          "default-border", BUTTON_DEFAULT_BORDER_INSETS);
            insets.left += defaultInsets.left;
            insets.right += defaultInsets.right;
            insets.top += defaultInsets.top;
            insets.bottom += defaultInsets.bottom;
        }

        return insets;
    }

    /*
     * This is used for both RADIO_BUTTON and CHECK_BOX.
     */
    private Insets getRadioInsets(SynthContext context, Insets insets) {
        // The following calculations are derived from gtkcheckbutton.c
        // (GTK+ version 2.8.20), gtk_check_button_size_allocate() method.
        int focusSize =
            getClassSpecificIntValue(context, "focus-line-width", 1);
        int focusPad =
            getClassSpecificIntValue(context, "focus-padding", 1);
        int totalFocus = focusSize + focusPad;

        // Note: GTKIconFactory.DelegateIcon will have already included the
        // "indicator-spacing" value in the size of the indicator icon,
        // which explains why we use zero as the left inset (or right inset
        // in the RTL case); see 6489585 for more details.
        insets.top    = totalFocus;
        insets.bottom = totalFocus;
        if (context.getComponent().getComponentOrientation().isLeftToRight()) {
            insets.left  = 0;
            insets.right = totalFocus;
        } else {
            insets.left  = totalFocus;
            insets.right = 0;
        }

        return insets;
    }

    private Insets getMenuBarInsets(SynthContext context, Insets insets) {
        // The following calculations are derived from gtkmenubar.c
        // (GTK+ version 2.8.20), gtk_menu_bar_size_allocate() method.
        int internalPadding = getClassSpecificIntValue(context,
                                                       "internal-padding", 1);
        int xThickness = getXThickness();
        int yThickness = getYThickness();
        insets.left = insets.right = xThickness + internalPadding;
        insets.top = insets.bottom = yThickness + internalPadding;
        return insets;
    }

    private Insets getMenuItemInsets(SynthContext context, Insets insets) {
        // The following calculations are derived from gtkmenuitem.c
        // (GTK+ version 2.8.20), gtk_menu_item_size_allocate() method.
        int horizPadding = getClassSpecificIntValue(context,
                                                    "horizontal-padding", 3);
        int xThickness = getXThickness();
        int yThickness = getYThickness();
        insets.left = insets.right = xThickness + horizPadding;
        insets.top = insets.bottom = yThickness;
        return insets;
    }

    private Insets getThicknessInsets(SynthContext context, Insets insets) {
        insets.left = insets.right = getXThickness();
        insets.top = insets.bottom = getYThickness();
        return insets;
    }

    private Insets getSeparatorInsets(SynthContext context, Insets insets) {
        int horizPadding = 0;
        if (context.getRegion() == Region.POPUP_MENU_SEPARATOR) {
            horizPadding =
                getClassSpecificIntValue(context, "horizontal-padding", 3);
        }
        insets.right = insets.left = getXThickness() + horizPadding;
        insets.top = insets.bottom = getYThickness();
        return insets;
    }

    private Insets getSliderTrackInsets(SynthContext context, Insets insets) {
        int focusSize = getClassSpecificIntValue(context, "focus-line-width", 1);
        int focusPad = getClassSpecificIntValue(context, "focus-padding", 1);
        insets.top = insets.bottom =
                insets.left = insets.right = focusSize + focusPad;
        return insets;
    }

    private Insets getSimpleInsets(SynthContext context, Insets insets, int n) {
        insets.top = insets.bottom = insets.right = insets.left = n;
        return insets;
    }

    private Insets getTabbedPaneTabInsets(SynthContext context, Insets insets) {
        int xThickness = getXThickness();
        int yThickness = getYThickness();
        int focusSize = getClassSpecificIntValue(context, "focus-line-width",1);
        int pad = 2;

        insets.left = insets.right = focusSize + pad + xThickness;
        insets.top = insets.bottom = focusSize + pad + yThickness;
        return insets;
    }

    // NOTE: this is called for ComboBox, and FormattedTextField also
    private Insets getTextFieldInsets(SynthContext context, Insets insets) {
        insets = getClassSpecificInsetsValue(context, "inner-border",
                                    getSimpleInsets(context, insets, 2));

        int xThickness = getXThickness();
        int yThickness = getYThickness();
        boolean interiorFocus =
                getClassSpecificBoolValue(context, "interior-focus", true);
        int focusSize = 0;

        if (!interiorFocus) {
            focusSize = getClassSpecificIntValue(context, "focus-line-width",1);
        }

        insets.left   += focusSize + xThickness;
        insets.right  += focusSize + xThickness;
        insets.top    += focusSize + yThickness;
        insets.bottom += focusSize + yThickness;
        return insets;
    }

    private Insets getScrollBarInsets(SynthContext context, Insets insets) {
        int troughBorder =
            getClassSpecificIntValue(context, "trough-border", 1);
        insets.left = insets.right = insets.top = insets.bottom = troughBorder;

        JComponent c = context.getComponent();
        if (c.getParent() instanceof JScrollPane) {
            // This scrollbar is part of a scrollpane; use only the
            // "scrollbar-spacing" style property to determine the padding
            // between the scrollbar and its parent scrollpane.
            int spacing =
                getClassSpecificIntValue(WidgetType.SCROLL_PANE,
                                         "scrollbar-spacing", 3);
            if (((JScrollBar)c).getOrientation() == JScrollBar.HORIZONTAL) {
                insets.top += spacing;
            } else {
                if (c.getComponentOrientation().isLeftToRight()) {
                    insets.left += spacing;
                } else {
                    insets.right += spacing;
                }
            }
        } else {
            // This is a standalone scrollbar; leave enough room for the
            // focus line in addition to the trough border.
            if (c.isFocusable()) {
                int focusSize =
                    getClassSpecificIntValue(context, "focus-line-width", 1);
                int focusPad =
                    getClassSpecificIntValue(context, "focus-padding", 1);
                int totalFocus = focusSize + focusPad;
                insets.left   += totalFocus;
                insets.right  += totalFocus;
                insets.top    += totalFocus;
                insets.bottom += totalFocus;
            }
        }
        return insets;
    }

    /**
     * Returns the value for a class specific property for a particular
     * WidgetType.  This method is useful in those cases where we need to
     * fetch a value for a Region that is not associated with the component
     * currently in use (e.g. we need to figure out the insets for a
     * SCROLL_BAR, but certain values can only be extracted from a
     * SCROLL_PANE region).
     *
     * @param wt WidgetType for which to fetch the value
     * @param key Key identifying class specific value
     * @return Value, or null if one has not been defined
     */
    private static Object getClassSpecificValue(WidgetType wt, String key) {
        synchronized (UNIXToolkit.GTK_LOCK) {
            return nativeGetClassValue(wt.ordinal(), key);
        }
    }

    /**
     * Convenience method to get a class specific integer value for
     * a particular WidgetType.
     *
     * @param wt WidgetType for which to fetch the value
     * @param key Key identifying class specific value
     * @param defaultValue Returned if there is no value for the specified
     *        type
     * @return Value, or defaultValue if <code>key is not defined
     */
    private static int getClassSpecificIntValue(WidgetType wt, String key,
                                                int defaultValue)
    {
        Object value = getClassSpecificValue(wt, key);
        if (value instanceof Number) {
            return ((Number)value).intValue();
        }
        return defaultValue;
    }

    /**
     * Returns the value for a class specific property. A class specific value
     * is a value that will be picked up based on class hierarchy.
     *
     * @param key Key identifying class specific value
     * @return Value, or null if one has not been defined.
     */
    Object getClassSpecificValue(String key) {
        synchronized (sun.awt.UNIXToolkit.GTK_LOCK) {
            return nativeGetClassValue(widgetType, key);
        }
    }

    /**
     * Convenience method to get a class specific integer value.
     *
     * @param context SynthContext identifying requestor
     * @param key Key identifying class specific value
     * @param defaultValue Returned if there is no value for the specified
     *        type
     * @return Value, or defaultValue if <code>key is not defined
     */
    int getClassSpecificIntValue(SynthContext context, String key,
                                 int defaultValue)
    {
        Object value = getClassSpecificValue(key);

        if (value instanceof Number) {
            return ((Number)value).intValue();
        }
        return defaultValue;
    }

    /**
     * Convenience method to get a class specific Insets value.
     *
     * @param context SynthContext identifying requestor
     * @param key Key identifying class specific value
     * @param defaultValue Returned if there is no value for the specified
     *        type
     * @return Value, or defaultValue if <code>key is not defined
     */
    Insets getClassSpecificInsetsValue(SynthContext context, String key,
                                       Insets defaultValue)
    {
        Object value = getClassSpecificValue(key);

        if (value instanceof Insets) {
            return (Insets)value;
        }
        return defaultValue;
    }

    /**
     * Convenience method to get a class specific Boolean value.
     *
     * @param context SynthContext identifying requestor
     * @param key Key identifying class specific value
     * @param defaultValue Returned if there is no value for the specified
     *        type
     * @return Value, or defaultValue if <code>key is not defined
     */
    boolean getClassSpecificBoolValue(SynthContext context, String key,
                                      boolean defaultValue)
    {
        Object value = getClassSpecificValue(key);

        if (value instanceof Boolean) {
            return ((Boolean)value).booleanValue();
        }
        return defaultValue;
    }

    /**
     * Returns the value to initialize the opacity property of the Component
     * to. A Style should NOT assume the opacity will remain this value, the
     * developer may reset it or override it.
     *
     * @param context SynthContext identifying requestor
     * @return opaque Whether or not the JComponent is opaque.
     */
    @Override
    public boolean isOpaque(SynthContext context) {
        Region region = context.getRegion();
        if (region == Region.COMBO_BOX ||
              region == Region.DESKTOP_PANE ||
              region == Region.DESKTOP_ICON ||
              region == Region.EDITOR_PANE ||
              region == Region.FORMATTED_TEXT_FIELD ||
              region == Region.INTERNAL_FRAME ||
              region == Region.LIST ||
              region == Region.MENU_BAR ||
              region == Region.PANEL ||
              region == Region.PASSWORD_FIELD ||
              region == Region.POPUP_MENU ||
              region == Region.PROGRESS_BAR ||
              region == Region.ROOT_PANE ||
              region == Region.SCROLL_PANE ||
              region == Region.SPINNER ||
              region == Region.SPLIT_PANE_DIVIDER ||
              region == Region.TABLE ||
              region == Region.TEXT_AREA ||
              region == Region.TEXT_FIELD ||
              region == Region.TEXT_PANE ||
              region == Region.TOOL_BAR_DRAG_WINDOW ||
              region == Region.TOOL_TIP ||
              region == Region.TREE ||
              region == Region.VIEWPORT) {
            return true;
        }
        Component c = context.getComponent();
        String name = c.getName();
        if (name == "ComboBox.renderer" || name == "ComboBox.listRenderer") {
            return true;
        }
        return false;
    }

    @Override
    public Object get(SynthContext context, Object key) {
        // See if this is a class specific value.
        String classKey = CLASS_SPECIFIC_MAP.get(key);
        if (classKey != null) {
            Object value = getClassSpecificValue(classKey);
            if (value != null) {
                return value;
            }
        }

        // Is it a specific value ?
        if (key == "ScrollPane.viewportBorderInsets") {
            return getThicknessInsets(context, new Insets(0, 0, 0, 0));
        }
        else if (key == "Slider.tickColor") {
            return getColorForState(context, ColorType.FOREGROUND);
        }
        else if (key == "ScrollBar.minimumThumbSize") {
            int len =
                getClassSpecificIntValue(context, "min-slider-length", 21);
            JScrollBar sb = (JScrollBar)context.getComponent();
            if (sb.getOrientation() == JScrollBar.HORIZONTAL) {
                return new DimensionUIResource(len, 0);
            } else {
                return new DimensionUIResource(0, len);
            }
        }
        else if (key == "Separator.thickness") {
            JSeparator sep = (JSeparator)context.getComponent();
            if (sep.getOrientation() == JSeparator.HORIZONTAL) {
                return getYThickness();
            } else {
                return getXThickness();
            }
        }
        else if (key == "ToolBar.separatorSize") {
            int size = getClassSpecificIntValue(WidgetType.TOOL_BAR,
                                                "space-size", 12);
            return new DimensionUIResource(size, size);
        }
        else if (key == "ScrollBar.buttonSize") {
            JScrollBar sb = (JScrollBar)context.getComponent().getParent();
            boolean horiz = (sb.getOrientation() == JScrollBar.HORIZONTAL);
            WidgetType wt = horiz ?
                WidgetType.HSCROLL_BAR : WidgetType.VSCROLL_BAR;
            int sliderWidth = getClassSpecificIntValue(wt, "slider-width", 14);
            int stepperSize = getClassSpecificIntValue(wt, "stepper-size", 14);
            return horiz ?
                new DimensionUIResource(stepperSize, sliderWidth) :
                new DimensionUIResource(sliderWidth, stepperSize);
        }
        else if (key == "ArrowButton.size") {
            String name = context.getComponent().getName();
            if (name != null && name.startsWith("Spinner")) {
                // Believe it or not, the size of a spinner arrow button is
                // dependent upon the size of the spinner's font.  These
                // calculations come from gtkspinbutton.c (version 2.8.20),
                // spin_button_get_arrow_size() method.
                String pangoFontName;
                synchronized (sun.awt.UNIXToolkit.GTK_LOCK) {
                    pangoFontName =
                        nativeGetPangoFontName(WidgetType.SPINNER.ordinal());
                }
                int arrowSize = (pangoFontName != null) ?
                    PangoFonts.getFontSize(pangoFontName) : 10;
                return (arrowSize + (getXThickness() * 2));
            }
            // For all other kinds of arrow buttons (e.g. combobox arrow
            // buttons), we will simply fall back on the value of
            // ArrowButton.size as defined in the UIDefaults for
            // GTKLookAndFeel when we call UIManager.get() below...
        }
        else if ("CheckBox.iconTextGap".equals(key) ||
                 "RadioButton.iconTextGap".equals(key))
        {
            // The iconTextGap value needs to include "indicator-spacing"
            // and it also needs to leave enough space for the focus line,
            // which falls between the indicator icon and the text.
            // See getRadioInsets() and 6489585 for more details.
            int indicatorSpacing =
                getClassSpecificIntValue(context, "indicator-spacing", 2);
            int focusSize =
                getClassSpecificIntValue(context, "focus-line-width", 1);
            int focusPad =
                getClassSpecificIntValue(context, "focus-padding", 1);
            return indicatorSpacing + focusSize + focusPad;
        }

        // Is it a stock icon ?
        GTKStockIcon stockIcon = null;
        synchronized (ICONS_MAP) {
            stockIcon = ICONS_MAP.get(key);
        }

        if (stockIcon != null) {
            return stockIcon;
        }

        // Is it another kind of value ?
        if (key != "engine") {
            // For backward compatibility we'll fallback to the UIManager.
            // We don't go to the UIManager for engine as the engine is GTK
            // specific.
            Object value = UIManager.get(key);
            if (key == "Table.rowHeight") {
                int focusLineWidth = getClassSpecificIntValue(context,
                        "focus-line-width", 0);
                if (value == null && focusLineWidth > 0) {
                    value = Integer.valueOf(16 + 2 * focusLineWidth);
                }
            }
            return value;
        }

        // Don't call super, we don't want to pick up defaults from
        // SynthStyle.
        return null;
    }

    private Icon getStockIcon(SynthContext context, String key, int type) {
        TextDirection direction = TextDirection.LTR;

        if (context != null) {
            ComponentOrientation co = context.getComponent().
                                              getComponentOrientation();

            if (co != null && !co.isLeftToRight()) {
                direction = TextDirection.RTL;
            }
        }

        // First try loading a theme-specific icon using the native
        // GTK libraries (native GTK handles the resizing for us).
        Icon icon = getStyleSpecificIcon(key, direction, type);
        if (icon != null) {
            return icon;
        }

        // In a failure case where native GTK (unexpectedly) returns a
        // null icon, we can try loading a default icon as a fallback.
        String propName = ICON_PROPERTY_PREFIX + key + '.' + type + '.' +
                          (direction == TextDirection.RTL ? "rtl" : "ltr");
        Image img = (Image)
            Toolkit.getDefaultToolkit().getDesktopProperty(propName);
        if (img != null) {
            return new ImageIcon(img);
        }

        // In an extreme failure situation, just return null (callers are
        // already prepared to handle a null icon, so the worst that can
        // happen is that an icon won't be included in the button/dialog).
        return null;
    }

    private Icon getStyleSpecificIcon(String key,
                                      TextDirection direction, int type)
    {
        UNIXToolkit tk = (UNIXToolkit)Toolkit.getDefaultToolkit();
        Image img =
            tk.getStockIcon(widgetType, key, type, direction.ordinal(), null);
        return (img != null) ? new ImageIcon(img) : null;
    }

    static class GTKStockIconInfo {
        private static Map<String,Integer> ICON_TYPE_MAP;
        private static final Object ICON_SIZE_KEY = new StringBuffer("IconSize");

        private static Dimension[] getIconSizesMap() {
            AppContext appContext = AppContext.getAppContext();
            Dimension[] iconSizes = (Dimension[])appContext.get(ICON_SIZE_KEY);

            if (iconSizes == null) {
                iconSizes = new Dimension[7];
                iconSizes[0] = null;                  // GTK_ICON_SIZE_INVALID
                iconSizes[1] = new Dimension(16, 16); // GTK_ICON_SIZE_MENU
                iconSizes[2] = new Dimension(18, 18); // GTK_ICON_SIZE_SMALL_TOOLBAR
                iconSizes[3] = new Dimension(24, 24); // GTK_ICON_SIZE_LARGE_TOOLBAR
                iconSizes[4] = new Dimension(20, 20); // GTK_ICON_SIZE_BUTTON
                iconSizes[5] = new Dimension(32, 32); // GTK_ICON_SIZE_DND
                iconSizes[6] = new Dimension(48, 48); // GTK_ICON_SIZE_DIALOG
                appContext.put(ICON_SIZE_KEY, iconSizes);
            }
            return iconSizes;
        }

        /**
         * Return the size of a particular icon type (logical size)
         *
         * @param type icon type (GtkIconSize value)
         * @return a Dimension object, or null if lsize is invalid
         */
        public static Dimension getIconSize(int type) {
            Dimension[] iconSizes = getIconSizesMap();
            return type >= 0 && type < iconSizes.length ?
                iconSizes[type] : null;
        }

        /**
         * Change icon size in a type to size mapping. This is called by code
         * that parses the gtk-icon-sizes setting
         *
         * @param type icon type (GtkIconSize value)
         * @param w the new icon width
         * @param h the new icon height
         */
        public static void setIconSize(int type, int w, int h) {
            Dimension[] iconSizes = getIconSizesMap();
            if (type >= 0 && type < iconSizes.length) {
                iconSizes[type] = new Dimension(w, h);
            }
        }

        /**
         * Return icon type (GtkIconSize value) given a symbolic name which can
         * occur in a theme file.
         *
         * @param size symbolic name, e.g. gtk-button
         * @return icon type. Valid types are 1 to 6
         */
        public static int getIconType(String size) {
            if (size == null) {
                return UNDEFINED;
            }
            if (ICON_TYPE_MAP == null) {
                initIconTypeMap();
            }
            Integer n = ICON_TYPE_MAP.get(size);
            return n != null ? n.intValue() : UNDEFINED;
        }

        private static void initIconTypeMap() {
            ICON_TYPE_MAP = new HashMap<String,Integer>();
            ICON_TYPE_MAP.put("gtk-menu", Integer.valueOf(1));
            ICON_TYPE_MAP.put("gtk-small-toolbar", Integer.valueOf(2));
            ICON_TYPE_MAP.put("gtk-large-toolbar", Integer.valueOf(3));
            ICON_TYPE_MAP.put("gtk-button", Integer.valueOf(4));
            ICON_TYPE_MAP.put("gtk-dnd", Integer.valueOf(5));
            ICON_TYPE_MAP.put("gtk-dialog", Integer.valueOf(6));
        }

    }

    /**
     * An Icon that is fetched using getStockIcon.
     */
    private static class GTKStockIcon extends SynthIcon {
        private String key;
        private int size;
        private boolean loadedLTR;
        private boolean loadedRTL;
        private Icon ltrIcon;
        private Icon rtlIcon;
        private SynthStyle style;

        GTKStockIcon(String key, int size) {
            this.key = key;
            this.size = size;
        }

        public void paintIcon(SynthContext context, Graphics g, int x,
                              int y, int w, int h) {
            Icon icon = getIcon(context);

            if (icon != null) {
                if (context == null) {
                    icon.paintIcon(null, g, x, y);
                }
                else {
                    icon.paintIcon(context.getComponent(), g, x, y);
                }
            }
        }

        public int getIconWidth(SynthContext context) {
            Icon icon = getIcon(context);

            if (icon != null) {
                return icon.getIconWidth();
            }
            return 0;
        }

        public int getIconHeight(SynthContext context) {
            Icon icon = getIcon(context);

            if (icon != null) {
                return icon.getIconHeight();
            }
            return 0;
        }

        private Icon getIcon(SynthContext context) {
            if (context != null) {
                ComponentOrientation co = context.getComponent().
                                                  getComponentOrientation();
                SynthStyle style = context.getStyle();

                if (style != this.style) {
                    this.style = style;
                    loadedLTR = loadedRTL = false;
                }
                if (co == null || co.isLeftToRight()) {
                    if (!loadedLTR) {
                        loadedLTR = true;
                        ltrIcon = ((GTKStyle)context.getStyle()).
                                  getStockIcon(context, key, size);
                    }
                    return ltrIcon;
                }
                else if (!loadedRTL) {
                    loadedRTL = true;
                    rtlIcon = ((GTKStyle)context.getStyle()).
                              getStockIcon(context, key,size);
                }
                return rtlIcon;
            }
            return ltrIcon;
        }
    }

    /**
     * GTKLazyValue is a slimmed down version of <code>ProxyLaxyValue.
     * The code is duplicate so that it can get at the package private
     * classes in gtk.
     */
    static class GTKLazyValue implements UIDefaults.LazyValue {
        /**
         * Name of the class to create.
         */
        private String className;
        private String methodName;

        GTKLazyValue(String name) {
            this(name, null);
        }

        GTKLazyValue(String name, String methodName) {
            this.className = name;
            this.methodName = methodName;
        }

        public Object createValue(UIDefaults table) {
            try {
                Class c = Class.forName(className, true,Thread.currentThread().
                                        getContextClassLoader());

                if (methodName == null) {
                    return c.newInstance();
                }
                Method m = c.getMethod(methodName, (Class[])null);

                return m.invoke(c, (Object[])null);
            } catch (ClassNotFoundException cnfe) {
            } catch (IllegalAccessException iae) {
            } catch (InvocationTargetException ite) {
            } catch (NoSuchMethodException nsme) {
            } catch (InstantiationException ie) {
            }
            return null;
        }
    }

    static {
        CLASS_SPECIFIC_MAP = new HashMap<String,String>();
        CLASS_SPECIFIC_MAP.put("Slider.thumbHeight", "slider-width");
        CLASS_SPECIFIC_MAP.put("Slider.trackBorder", "trough-border");
        CLASS_SPECIFIC_MAP.put("SplitPane.size", "handle-size");
        CLASS_SPECIFIC_MAP.put("Tree.expanderSize", "expander-size");
        CLASS_SPECIFIC_MAP.put("ScrollBar.thumbHeight", "slider-width");
        CLASS_SPECIFIC_MAP.put("ScrollBar.width", "slider-width");
        CLASS_SPECIFIC_MAP.put("TextArea.caretForeground", "cursor-color");
        CLASS_SPECIFIC_MAP.put("TextArea.caretAspectRatio", "cursor-aspect-ratio");
        CLASS_SPECIFIC_MAP.put("TextField.caretForeground", "cursor-color");
        CLASS_SPECIFIC_MAP.put("TextField.caretAspectRatio", "cursor-aspect-ratio");
        CLASS_SPECIFIC_MAP.put("PasswordField.caretForeground", "cursor-color");
        CLASS_SPECIFIC_MAP.put("PasswordField.caretAspectRatio", "cursor-aspect-ratio");
        CLASS_SPECIFIC_MAP.put("FormattedTextField.caretForeground", "cursor-color");
        CLASS_SPECIFIC_MAP.put("FormattedTextField.caretAspectRatio", "cursor-aspect-");
        CLASS_SPECIFIC_MAP.put("TextPane.caretForeground", "cursor-color");
        CLASS_SPECIFIC_MAP.put("TextPane.caretAspectRatio", "cursor-aspect-ratio");
        CLASS_SPECIFIC_MAP.put("EditorPane.caretForeground", "cursor-color");
        CLASS_SPECIFIC_MAP.put("EditorPane.caretAspectRatio", "cursor-aspect-ratio");

        ICONS_MAP = new HashMap<String, GTKStockIcon>();
        ICONS_MAP.put("FileChooser.cancelIcon", new GTKStockIcon("gtk-cancel", 4));
        ICONS_MAP.put("FileChooser.okIcon",     new GTKStockIcon("gtk-ok",     4));
        ICONS_MAP.put("OptionPane.errorIcon", new GTKStockIcon("gtk-dialog-error", 6));
        ICONS_MAP.put("OptionPane.informationIcon", new GTKStockIcon("gtk-dialog-info", 6));
        ICONS_MAP.put("OptionPane.warningIcon", new GTKStockIcon("gtk-dialog-warning", 6));
        ICONS_MAP.put("OptionPane.questionIcon", new GTKStockIcon("gtk-dialog-question", 6));
        ICONS_MAP.put("OptionPane.yesIcon", new GTKStockIcon("gtk-yes", 4));
        ICONS_MAP.put("OptionPane.noIcon", new GTKStockIcon("gtk-no", 4));
        ICONS_MAP.put("OptionPane.cancelIcon", new GTKStockIcon("gtk-cancel", 4));
        ICONS_MAP.put("OptionPane.okIcon", new GTKStockIcon("gtk-ok", 4));
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java GTKStyle.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.