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

Java example source code file (GTKPainter.java)

This example Java source code file (GTKPainter.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

arrowtype, awt, border, container, graphics, gtkpainter, gtkstyle, gui, insets, jcombobox, jcomponent, listtablefocusborder, orientation, plaf, reflection, region, shadowtype, string, swing, synthcontext

The GTKPainter.java Java example source code

/*
 * Copyright (c) 2002, 2012, 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 sun.awt.UNIXToolkit;

import javax.swing.plaf.synth.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import com.sun.java.swing.plaf.gtk.GTKConstants.ArrowType;
import com.sun.java.swing.plaf.gtk.GTKConstants.ExpanderStyle;
import com.sun.java.swing.plaf.gtk.GTKConstants.Orientation;
import com.sun.java.swing.plaf.gtk.GTKConstants.PositionType;
import com.sun.java.swing.plaf.gtk.GTKConstants.ShadowType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Joshua Outwater
 * @author Scott Violet
 */
// Need to support:
// default_outside_border: Insets when default.
// interior_focus: Indicates if focus should appear inside border, or
//                       outside border.
// focus-line-width: Integer giving size of focus border
// focus-padding: Integer giving padding between border and focus
//        indicator.
// focus-line-pattern:
//
class GTKPainter extends SynthPainter {
    private static final PositionType[] POSITIONS = {
        PositionType.BOTTOM, PositionType.RIGHT,
        PositionType.TOP, PositionType.LEFT
    };

    private static final ShadowType SHADOWS[] = {
        ShadowType.NONE, ShadowType.IN, ShadowType.OUT,
        ShadowType.ETCHED_IN, ShadowType.OUT
    };

    private final static GTKEngine ENGINE = GTKEngine.INSTANCE;
    final static GTKPainter INSTANCE = new GTKPainter();

    private GTKPainter() {
    }

    private String getName(SynthContext context) {
        return (context.getRegion().isSubregion()) ? null :
               context.getComponent().getName();
    }

    public void paintCheckBoxBackground(SynthContext context,
            Graphics g, int x, int y, int w, int h) {
        paintRadioButtonBackground(context, g, x, y, w, h);
    }

    public void paintCheckBoxMenuItemBackground(SynthContext context,
            Graphics g, int x, int y, int w, int h) {
        paintRadioButtonMenuItemBackground(context, g, x, y, w, h);
    }

    // FORMATTED_TEXT_FIELD
    public void paintFormattedTextFieldBackground(SynthContext context,
                                          Graphics g, int x, int y,
                                          int w, int h) {
        paintTextBackground(context, g, x, y, w, h);
    }

    //
    // TOOL_BAR_DRAG_WINDOW
    //
    public void paintToolBarDragWindowBackground(SynthContext context,
                                     Graphics g, int x, int y,
                                     int w, int h) {
        paintToolBarBackground(context, g, x, y, w, h);
    }


    //
    // TOOL_BAR
    //
    public void paintToolBarBackground(SynthContext context,
                                     Graphics g, int x, int y,
                                     int w, int h) {
        Region id = context.getRegion();
        int state = context.getComponentState();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
        int orientation = ((JToolBar)context.getComponent()).getOrientation();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id,
                                          state, orientation))
            {
                ENGINE.startPainting(g, x, y, w, h, id, state, orientation);
                ENGINE.paintBox(g, context, id, gtkState, ShadowType.OUT,
                                "handlebox_bin", x, y, w, h);
                ENGINE.finishPainting();
            }
        }
    }

    public void paintToolBarContentBackground(SynthContext context,
                                              Graphics g,
                                              int x, int y, int w, int h) {
        Region id = context.getRegion();
        int orientation = ((JToolBar)context.getComponent()).getOrientation();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, orientation)) {
                ENGINE.startPainting(g, x, y, w, h, id, orientation);
                ENGINE.paintBox(g, context, id, SynthConstants.ENABLED,
                                ShadowType.OUT, "toolbar", x, y, w, h);
                ENGINE.finishPainting();
            }
        }
    }

    //
    // PASSWORD_FIELD
    //
    public void paintPasswordFieldBackground(SynthContext context,
                                     Graphics g, int x, int y,
                                     int w, int h) {
        paintTextBackground(context, g, x, y, w, h);
    }

    //
    // TEXT_FIELD
    //
    public void paintTextFieldBackground(SynthContext context, Graphics g,
                                         int x, int y, int w, int h) {
        if (getName(context) == "Tree.cellEditor") {
            paintTreeCellEditorBackground(context, g, x, y, w, h);
        } else {
            paintTextBackground(context, g, x, y, w, h);
        }
    }

    //
    // RADIO_BUTTON
    //
    // NOTE: this is called for JCheckBox too
    public void paintRadioButtonBackground(SynthContext context,
                                     Graphics g, int x, int y,
                                     int w, int h) {
        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        if (gtkState == SynthConstants.MOUSE_OVER) {
            synchronized (UNIXToolkit.GTK_LOCK) {
                if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                    ENGINE.startPainting(g, x, y, w, h, id);
                    ENGINE.paintFlatBox(g, context, id,
                            SynthConstants.MOUSE_OVER, ShadowType.ETCHED_OUT,
                            "checkbutton", x, y, w, h, ColorType.BACKGROUND);
                    ENGINE.finishPainting();
                }
            }
        }
    }

    //
    // RADIO_BUTTON_MENU_ITEM
    //
    // NOTE: this is called for JCheckBoxMenuItem too
    public void paintRadioButtonMenuItemBackground(SynthContext context,
                                     Graphics g, int x, int y,
                                     int w, int h) {
        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        if (gtkState == SynthConstants.MOUSE_OVER) {
            synchronized (UNIXToolkit.GTK_LOCK) {
                if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                    ShadowType shadow = (GTKLookAndFeel.is2_2() ?
                        ShadowType.NONE : ShadowType.OUT);
                    ENGINE.startPainting(g, x, y, w, h, id);
                    ENGINE.paintBox(g, context, id, gtkState,
                            shadow, "menuitem", x, y, w, h);
                    ENGINE.finishPainting();
                }
            }
        }
    }

    //
    // LABEL
    //
    public void paintLabelBackground(SynthContext context,
                                     Graphics g, int x, int y,
                                     int w, int h) {
        String name = getName(context);
        JComponent c = context.getComponent();
        Container  container = c.getParent();

        if (name == "TableHeader.renderer" ||
            name == "GTKFileChooser.directoryListLabel" ||
            name == "GTKFileChooser.fileListLabel") {

            paintButtonBackgroundImpl(context, g, Region.BUTTON, "button",
                    x, y, w, h, true, false, false, false);
        }
        /*
         * If the label is a ListCellRenderer and it's in a container
         * (CellRendererPane) which is in a JComboBox then we paint the label
         * as a TextField like a gtk_entry for a combobox.
         */
        else if (c instanceof ListCellRenderer &&
                 container != null &&
                 container.getParent() instanceof JComboBox ) {
            paintTextBackground(context, g, x, y, w, h);
        }
    }

    //
    // INTERNAL_FRAME
    //
    public void paintInternalFrameBorder(SynthContext context,
                                      Graphics g, int x, int y,
                                      int w, int h) {
        Metacity.INSTANCE.paintFrameBorder(context, g, x, y, w, h);
    }

    //
    // DESKTOP_PANE
    //
    public void paintDesktopPaneBackground(SynthContext context,
                                           Graphics g, int x, int y,
                                           int w, int h) {
        // Does not call into ENGINE for better performance
        fillArea(context, g, x, y, w, h, ColorType.BACKGROUND);
    }

    //
    // DESKTOP_ICON
    //
    public void paintDesktopIconBorder(SynthContext context,
                                           Graphics g, int x, int y,
                                           int w, int h) {
        Metacity.INSTANCE.paintFrameBorder(context, g, x, y, w, h);
    }

    public void paintButtonBackground(SynthContext context, Graphics g,
                                      int x, int y, int w, int h) {
        String name = getName(context);
        if (name != null && name.startsWith("InternalFrameTitlePane.")) {
            Metacity.INSTANCE.paintButtonBackground(context, g, x, y, w, h);

        } else {
            AbstractButton button = (AbstractButton)context.getComponent();
            boolean paintBG = button.isContentAreaFilled() &&
                              button.isBorderPainted();
            boolean paintFocus = button.isFocusPainted();
            boolean defaultCapable = (button instanceof JButton) &&
                    ((JButton)button).isDefaultCapable();
            boolean toolButton = (button.getParent() instanceof JToolBar);
            paintButtonBackgroundImpl(context, g, Region.BUTTON, "button",
                    x, y, w, h, paintBG, paintFocus, defaultCapable, toolButton);
        }
    }

    private void paintButtonBackgroundImpl(SynthContext context, Graphics g,
            Region id, String detail, int x, int y, int w, int h,
            boolean paintBackground, boolean paintFocus,
            boolean defaultCapable, boolean toolButton) {
        int state = context.getComponentState();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (ENGINE.paintCachedImage(g, x, y, w, h, id, state, detail,
                    paintBackground, paintFocus, defaultCapable, toolButton)) {
                return;
            }
            ENGINE.startPainting(g, x, y, w, h, id, state, detail,
                paintBackground, paintFocus, defaultCapable, toolButton);

            // Paint the default indicator
            GTKStyle style = (GTKStyle)context.getStyle();
            if (defaultCapable && !toolButton) {
                Insets defaultInsets = style.getClassSpecificInsetsValue(
                        context, "default-border",
                        GTKStyle.BUTTON_DEFAULT_BORDER_INSETS);

                if (paintBackground && (state & SynthConstants.DEFAULT) != 0) {
                    ENGINE.paintBox(g, context, id, SynthConstants.ENABLED,
                            ShadowType.IN, "buttondefault", x, y, w, h);
                }
                x += defaultInsets.left;
                y += defaultInsets.top;
                w -= (defaultInsets.left + defaultInsets.right);
                h -= (defaultInsets.top + defaultInsets.bottom);
            }

            boolean interiorFocus = style.getClassSpecificBoolValue(
                    context, "interior-focus", true);
            int focusSize = style.getClassSpecificIntValue(
                    context, "focus-line-width",1);
            int focusPad = style.getClassSpecificIntValue(
                    context, "focus-padding", 1);

            int totalFocusSize = focusSize + focusPad;
            int xThickness = style.getXThickness();
            int yThickness = style.getYThickness();

            // Render the box.
            if (!interiorFocus &&
                    (state & SynthConstants.FOCUSED) == SynthConstants.FOCUSED) {
                x += totalFocusSize;
                y += totalFocusSize;
                w -= 2 * totalFocusSize;
                h -= 2 * totalFocusSize;
            }

            int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
            boolean paintBg;
            if (toolButton) {
                // Toolbar buttons should only have their background painted
                // in the PRESSED, SELECTED, or MOUSE_OVER states.
                paintBg =
                    (gtkState != SynthConstants.ENABLED) &&
                    (gtkState != SynthConstants.DISABLED);
            } else {
                // Otherwise, always paint the button's background, unless
                // the user has overridden it and we're in the ENABLED state.
                paintBg =
                    paintBackground ||
                    (gtkState != SynthConstants.ENABLED);
            }
            if (paintBg) {
                ShadowType shadowType = ShadowType.OUT;
                if ((state & (SynthConstants.PRESSED |
                              SynthConstants.SELECTED)) != 0) {
                    shadowType = ShadowType.IN;
                }
                ENGINE.paintBox(g, context, id, gtkState,
                        shadowType, detail, x, y, w, h);
            }

            // focus
            if (paintFocus && (state & SynthConstants.FOCUSED) != 0) {
                if (interiorFocus) {
                    x += xThickness + focusPad;
                    y += yThickness + focusPad;
                    w -= 2 * (xThickness + focusPad);
                    h -= 2 * (yThickness + focusPad);
                } else {
                    x -= totalFocusSize;
                    y -= totalFocusSize;
                    w += 2 * totalFocusSize;
                    h += 2 * totalFocusSize;
                }
                ENGINE.paintFocus(g, context, id, gtkState, detail, x, y, w, h);
            }
            ENGINE.finishPainting();
        }
    }

    //
    // ARROW_BUTTON
    //
    public void paintArrowButtonForeground(SynthContext context, Graphics g,
                                           int x, int y, int w, int h,
                                           int direction) {
        Region id = context.getRegion();
        Component c = context.getComponent();
        String name = c.getName();

        ArrowType arrowType = null;
        switch (direction) {
            case SwingConstants.NORTH:
                arrowType = ArrowType.UP; break;
            case SwingConstants.SOUTH:
                arrowType = ArrowType.DOWN; break;
            case SwingConstants.EAST:
                arrowType = ArrowType.RIGHT; break;
            case SwingConstants.WEST:
                arrowType = ArrowType.LEFT; break;
        }

        String detail = "arrow";
        if ((name == "ScrollBar.button") || (name == "TabbedPane.button")) {
            if (arrowType == ArrowType.UP || arrowType == ArrowType.DOWN) {
                detail = "vscrollbar";
            } else {
                detail = "hscrollbar";
            }
        } else if (name == "Spinner.nextButton" ||
                   name == "Spinner.previousButton") {
            detail = "spinbutton";
        } else if (name != "ComboBox.arrowButton") {
            assert false : "unexpected name: " + name;
        }

        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        ShadowType shadowType = (gtkState == SynthConstants.PRESSED ?
            ShadowType.IN : ShadowType.OUT);
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (ENGINE.paintCachedImage(g, x, y, w, h,
                    gtkState, name, direction)) {
                return;
            }
            ENGINE.startPainting(g, x, y, w, h, gtkState, name, direction);
            ENGINE.paintArrow(g, context, id, gtkState,
                    shadowType, arrowType, detail, x, y, w, h);
            ENGINE.finishPainting();
        }
    }

    public void paintArrowButtonBackground(SynthContext context,
            Graphics g, int x, int y, int w, int h) {
        Region id = context.getRegion();
        AbstractButton button = (AbstractButton)context.getComponent();

        String name = button.getName();
        String detail = "button";
        int direction = SwingConstants.CENTER;
        if ((name == "ScrollBar.button") || (name == "TabbedPane.button")) {
            Integer prop = (Integer)
                button.getClientProperty("__arrow_direction__");
            direction = (prop != null) ?
                prop.intValue() : SwingConstants.WEST;
            switch (direction) {
            default:
            case SwingConstants.EAST:
            case SwingConstants.WEST:
                detail = "hscrollbar";
                break;
            case SwingConstants.NORTH:
            case SwingConstants.SOUTH:
                detail = "vscrollbar";
                break;
            }
        } else if (name == "Spinner.previousButton") {
            detail = "spinbutton_down";
        } else if (name == "Spinner.nextButton") {
            detail = "spinbutton_up";
        } else if (name != "ComboBox.arrowButton") {
            assert false : "unexpected name: " + name;
        }

        int state = context.getComponentState();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (ENGINE.paintCachedImage(g, x, y, w, h, id,
                                        state, detail, direction))
            {
                return;
            }
            ENGINE.startPainting(g, x, y, w, h, id,
                                 state, detail, direction);

            if (detail.startsWith("spin")) {
                /*
                 * The ubuntulooks engine (and presumably others) expect us to
                 * first draw the full "spinbutton" background, and then draw
                 * the individual "spinbutton_up/down" buttons on top of that.
                 * Note that it is the state of the JSpinner (not its arrow
                 * button) that determines how we draw this background.
                 */
                int spinState = button.getParent().isEnabled() ?
                    SynthConstants.ENABLED : SynthConstants.DISABLED;
                int mody = (detail == "spinbutton_up") ? y : y-h;
                int modh = h*2;
                ENGINE.paintBox(g, context, id, spinState,
                                ShadowType.IN, "spinbutton",
                                x, mody, w, modh);
            }

            int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
            ShadowType shadowType = ShadowType.OUT;
            if ((gtkState & (SynthConstants.PRESSED |
                             SynthConstants.SELECTED)) != 0)
            {
                shadowType = ShadowType.IN;
            }
            ENGINE.paintBox(g, context, id, gtkState,
                            shadowType, detail,
                            x, y, w, h);

            ENGINE.finishPainting();
        }
    }


    //
    // LIST
    //
    public void paintListBackground(SynthContext context, Graphics g,
                                    int x, int y, int w, int h) {
        // Does not call into ENGINE for better performance
        fillArea(context, g, x, y, w, h, GTKColorType.TEXT_BACKGROUND);
    }

    public void paintMenuBarBackground(SynthContext context, Graphics g,
                                       int x, int y, int w, int h) {
        Region id = context.getRegion();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                return;
            }
            GTKStyle style = (GTKStyle)context.getStyle();
            int shadow = style.getClassSpecificIntValue(
                    context, "shadow-type", 2);
            ShadowType shadowType = SHADOWS[shadow];
            int gtkState = GTKLookAndFeel.synthStateToGTKState(
                    id, context.getComponentState());
            ENGINE.startPainting(g, x, y, w, h, id);
            ENGINE.paintBox(g, context, id, gtkState,
                shadowType, "menubar", x, y, w, h);
            ENGINE.finishPainting();
        }
    }

    //
    // MENU
    //
    public void paintMenuBackground(SynthContext context,
                                     Graphics g,
                                     int x, int y, int w, int h) {
        paintMenuItemBackground(context, g, x, y, w, h);
    }

    // This is called for both MENU and MENU_ITEM
    public void paintMenuItemBackground(SynthContext context,
                                     Graphics g,
                                     int x, int y, int w, int h) {
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                context.getRegion(), context.getComponentState());
        if (gtkState == SynthConstants.MOUSE_OVER) {
            Region id = Region.MENU_ITEM;
            synchronized (UNIXToolkit.GTK_LOCK) {
                if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                    ShadowType shadow = (GTKLookAndFeel.is2_2() ?
                        ShadowType.NONE : ShadowType.OUT);
                    ENGINE.startPainting(g, x, y, w, h, id);
                    ENGINE.paintBox(g, context, id, gtkState, shadow,
                            "menuitem", x, y, w, h);
                    ENGINE.finishPainting();
                }
            }
        }
    }

    public void paintPopupMenuBackground(SynthContext context, Graphics g,
                                        int x, int y, int w, int h) {
        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState)) {
                return;
            }
            ENGINE.startPainting(g, x, y, w, h, id, gtkState);
            ENGINE.paintBox(g, context, id, gtkState,
                    ShadowType.OUT, "menu", x, y, w, h);

            GTKStyle style = (GTKStyle)context.getStyle();
            int xThickness = style.getXThickness();
            int yThickness = style.getYThickness();
            ENGINE.paintBackground(g, context, id, gtkState,
                    style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND),
                    x + xThickness, y + yThickness,
                    w - xThickness - xThickness, h - yThickness - yThickness);
            ENGINE.finishPainting();
        }
    }

    public void paintProgressBarBackground(SynthContext context,
                                            Graphics g,
                                            int x, int y, int w, int h) {
        Region id = context.getRegion();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                ENGINE.startPainting(g, x, y, w, h, id);
                ENGINE.paintBox(g, context, id, SynthConstants.ENABLED,
                        ShadowType.IN, "trough", x, y, w, h);
                ENGINE.finishPainting();
            }
        }
    }

    public void paintProgressBarForeground(SynthContext context, Graphics g,
                                            int x, int y, int w, int h,
                                            int orientation) {
        Region id = context.getRegion();
        synchronized (UNIXToolkit.GTK_LOCK) {
            // Note that we don't call paintCachedImage() here.  Since the
            // progress bar foreground is painted differently for each value
            // it would be wasteful to try to cache an image for each state,
            // so instead we simply avoid caching in this case.
            if (w <= 0 || h <= 0) {
                return;
            }
            ENGINE.startPainting(g, x, y, w, h, id, "fg");
            ENGINE.paintBox(g, context, id, SynthConstants.MOUSE_OVER,
                            ShadowType.OUT, "bar", x, y, w, h);
            ENGINE.finishPainting(false); // don't bother caching the image
        }
    }

    public void paintViewportBorder(SynthContext context, Graphics g,
                                           int x, int y, int w, int h) {
        Region id = context.getRegion();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                ENGINE.startPainting(g, x, y, w, h, id);
                ENGINE.paintShadow(g, context, id, SynthConstants.ENABLED,
                        ShadowType.IN, "scrolled_window", x, y, w, h);
                ENGINE.finishPainting();
            }
        }
    }

    public void paintSeparatorBackground(SynthContext context,
                                          Graphics g,
                                          int x, int y, int w, int h,
                                         int orientation) {
        Region id = context.getRegion();
        int state = context.getComponentState();
        JComponent c = context.getComponent();

        /*
         * Note: In theory, the style's x/y thickness values would determine
         * the width of the separator content.  In practice, however, some
         * engines will render a line that is wider than the corresponding
         * thickness value.  For example, ubuntulooks reports x/y thickness
         * values of 1 for separators, but always renders a 2-pixel wide line.
         * As a result of all this, we need to be careful not to restrict
         * the w/h values below too much, so that the full thickness of the
         * rendered line will be captured by our image caching code.
         */
        String detail;
        if (c instanceof JToolBar.Separator) {
            /*
             * GTK renders toolbar separators differently in that an
             * artificial padding is added to each end of the separator.
             * The value of 0.2f below is derived from the source code of
             * gtktoolbar.c in the current version of GTK+ (2.8.20 at the
             * time of this writing).  Specifically, the relevant values are:
             *     SPACE_LINE_DIVISION 10.0
             *     SPACE_LINE_START     2.0
             *     SPACE_LINE_END       8.0
             * These are used to determine the distance from the top (or left)
             * edge of the toolbar to the other edge.  So for example, the
             * starting/top point of a vertical separator is 2/10 of the
             * height of a horizontal toolbar away from the top edge, which
             * is how we arrive at 0.2f below.  Likewise, the ending/bottom
             * point is 8/10 of the height away from the top edge, or in other
             * words, it is 2/10 away from the bottom edge, which is again
             * how we arrive at the 0.2f value below.
             *
             * The separator is also centered horizontally or vertically,
             * depending on its orientation.  This was determined empirically
             * and by examining the code referenced above.
             */
            detail = "toolbar";
            float pct = 0.2f;
            JToolBar.Separator sep = (JToolBar.Separator)c;
            Dimension size = sep.getSeparatorSize();
            GTKStyle style = (GTKStyle)context.getStyle();
            if (orientation == JSeparator.HORIZONTAL) {
                x += (int)(w * pct);
                w -= (int)(w * pct * 2);
                y += (size.height - style.getYThickness()) / 2;
            } else {
                y += (int)(h * pct);
                h -= (int)(h * pct * 2);
                x += (size.width - style.getXThickness()) / 2;
            }
        } else {
            // For regular/menu separators, we simply subtract out the insets.
            detail = "separator";
            Insets insets = c.getInsets();
            x += insets.left;
            y += insets.top;
            if (orientation == JSeparator.HORIZONTAL) {
                w -= (insets.left + insets.right);
            } else {
                h -= (insets.top + insets.bottom);
            }
        }

        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id,
                                          state, detail, orientation)) {
                ENGINE.startPainting(g, x, y, w, h, id,
                                     state, detail, orientation);
                if (orientation == JSeparator.HORIZONTAL) {
                    ENGINE.paintHline(g, context, id, state,
                                      detail, x, y, w, h);
                } else {
                    ENGINE.paintVline(g, context, id, state,
                                      detail, x, y, w, h);
                }
                ENGINE.finishPainting();
            }
        }
    }

    public void paintSliderTrackBackground(SynthContext context,
                                       Graphics g,
                                       int x, int y, int w,int h) {
        Region id = context.getRegion();
        int state = context.getComponentState();

        // For focused sliders, we paint focus rect outside the bounds passed.
        // Need to adjust for that.
        boolean focused = ((state & SynthConstants.FOCUSED) != 0);
        int focusSize = 0;
        if (focused) {
            GTKStyle style = (GTKStyle)context.getStyle();
            focusSize = style.getClassSpecificIntValue(
                                context, "focus-line-width", 1) +
                        style.getClassSpecificIntValue(
                                context, "focus-padding", 1);
            x -= focusSize;
            y -= focusSize;
            w += focusSize * 2;
            h += focusSize * 2;
        }

        // The ubuntulooks engine paints slider troughs differently depending
        // on the current slider value and its component orientation.
        JSlider slider = (JSlider)context.getComponent();
        double value = slider.getValue();
        double min = slider.getMinimum();
        double max = slider.getMaximum();
        double visible = 20; // not used for sliders; any value will work

        synchronized (UNIXToolkit.GTK_LOCK) {
            // Note that we don't call paintCachedImage() here.  Since some
            // engines (e.g. ubuntulooks) paint the slider background
            // differently for any given slider value, it would be wasteful
            // to try to cache an image for each state, so instead we simply
            // avoid caching in this case.
            if (w <= 0 || h <= 0) {
                return;
            }
            ENGINE.startPainting(g, x, y, w, h, id, state, value);
            int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
            ENGINE.setRangeValue(context, id, value, min, max, visible);
            ENGINE.paintBox(g, context, id, gtkState, ShadowType.IN,
                            "trough", x + focusSize, y + focusSize,
                            w - 2 * focusSize, h - 2 * focusSize);
            if (focused) {
                ENGINE.paintFocus(g, context, id, SynthConstants.ENABLED,
                                  "trough", x, y, w, h);
            }
            ENGINE.finishPainting(false); // don't bother caching the image
        }
    }

    public void paintSliderThumbBackground(SynthContext context,
            Graphics g, int x, int y, int w, int h, int dir) {
        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir)) {
                Orientation orientation = (dir == JSlider.HORIZONTAL ?
                    Orientation.HORIZONTAL : Orientation.VERTICAL);
                String detail = (dir == JSlider.HORIZONTAL ?
                    "hscale" : "vscale");
                ENGINE.startPainting(g, x, y, w, h, id, gtkState, dir);
                ENGINE.paintSlider(g, context, id, gtkState,
                        ShadowType.OUT, detail, x, y, w, h, orientation);
                ENGINE.finishPainting();
            }
        }
    }

    //
    // SPINNER
    //
    public void paintSpinnerBackground(SynthContext context,
                                        Graphics g,
                                        int x, int y, int w, int h) {
        // This is handled in paintTextFieldBackground
    }

    //
    // SPLIT_PANE_DIVIDER
    //
    public void paintSplitPaneDividerBackground(SynthContext context,
                                       Graphics g,
                                       int x, int y, int w, int h) {
        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        JSplitPane splitPane = (JSplitPane)context.getComponent();
        Orientation orientation =
                (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT ?
                    Orientation.VERTICAL : Orientation.HORIZONTAL);
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h,
                    id, gtkState, orientation)) {
                ENGINE.startPainting(g, x, y, w, h, id, gtkState, orientation);
                ENGINE.paintHandle(g, context, id, gtkState,
                        ShadowType.OUT, "paned", x, y, w, h, orientation);
                ENGINE.finishPainting();
            }
        }
    }

    public void paintSplitPaneDragDivider(SynthContext context,
                                       Graphics g,int x, int y, int w, int h,
                                       int orientation) {
        paintSplitPaneDividerForeground(context, g, x, y, w, h, orientation);
    }

    public void paintTabbedPaneContentBackground(SynthContext context,
                                      Graphics g, int x, int y, int w, int h) {
        JTabbedPane pane = (JTabbedPane)context.getComponent();
        int selectedIndex = pane.getSelectedIndex();
        PositionType placement = GTKLookAndFeel.SwingOrientationConstantToGTK(
                                                        pane.getTabPlacement());

        int gapStart = 0;
        int gapSize = 0;
        if (selectedIndex != -1) {
            Rectangle tabBounds = pane.getBoundsAt(selectedIndex);

            if (placement == PositionType.TOP ||
                placement == PositionType.BOTTOM) {

                gapStart = tabBounds.x - x;
                gapSize = tabBounds.width;
            }
            else {
                gapStart = tabBounds.y - y;
                gapSize = tabBounds.height;
            }
        }

        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h,
                    id, gtkState, placement, gapStart, gapSize)) {
                ENGINE.startPainting(g, x, y, w, h,
                        id, gtkState, placement, gapStart, gapSize);
                ENGINE.paintBoxGap(g, context, id, gtkState, ShadowType.OUT,
                        "notebook", x, y, w, h, placement, gapStart, gapSize);
                ENGINE.finishPainting();
            }
        }
    }

    public void paintTabbedPaneTabBackground(SynthContext context,
                                           Graphics g,
                                           int x, int y, int w, int h,
                                           int tabIndex) {
        Region id = context.getRegion();
        int state = context.getComponentState();
        int gtkState = ((state & SynthConstants.SELECTED) != 0 ?
            SynthConstants.ENABLED : SynthConstants.PRESSED);
        JTabbedPane pane = (JTabbedPane)context.getComponent();
        int placement = pane.getTabPlacement();

        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h,
                    id, gtkState, placement, tabIndex)) {
                PositionType side = POSITIONS[placement - 1];
                ENGINE.startPainting(g, x, y, w, h,
                        id, gtkState, placement, tabIndex);
                ENGINE.paintExtension(g, context, id, gtkState,
                        ShadowType.OUT, "tab", x, y, w, h, side, tabIndex);
                ENGINE.finishPainting();
            }
        }
    }

    //
    // TEXT_PANE
    //
    public void paintTextPaneBackground(SynthContext context, Graphics g,
                                        int x, int y, int w, int h) {
        paintTextAreaBackground(context, g, x, y, w, h);
    }

    //
    // EDITOR_PANE
    //
    public void paintEditorPaneBackground(SynthContext context, Graphics g,
                                          int x, int y, int w, int h) {
        paintTextAreaBackground(context, g, x, y, w, h);
    }

    //
    // TEXT_AREA
    //
    public void paintTextAreaBackground(SynthContext context, Graphics g,
                                        int x, int y, int w, int h) {
        // Does not call into ENGINE for better performance
        fillArea(context, g, x, y, w, h, GTKColorType.TEXT_BACKGROUND);
    }

    //
    // TEXT_FIELD
    //
    // NOTE: Combobox and Label, Password and FormattedTextField calls this
    // too.
    private void paintTextBackground(SynthContext context, Graphics g,
                                     int x, int y, int w, int h) {
        // Text is odd in that it uses the TEXT_BACKGROUND vs BACKGROUND.
        JComponent c = context.getComponent();
        Container container = c.getParent();
        Container containerParent = null;
        GTKStyle style = (GTKStyle)context.getStyle();
        Region id = context.getRegion();
        int state = context.getComponentState();

        if (c instanceof ListCellRenderer && container != null) {
            containerParent = container.getParent();
            if (containerParent instanceof JComboBox
                    && containerParent.hasFocus()) {
                state |= SynthConstants.FOCUSED;
            }
        }

        synchronized (UNIXToolkit.GTK_LOCK) {
            if (ENGINE.paintCachedImage(g, x, y, w, h, id, state)) {
                return;
            }

            int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
            int focusSize = 0;
            boolean interiorFocus = style.getClassSpecificBoolValue(
                    context, "interior-focus", true);

            focusSize = style.getClassSpecificIntValue(context,
                    "focus-line-width",1);
            if (!interiorFocus && (state & SynthConstants.FOCUSED) != 0) {
                x += focusSize;
                y += focusSize;
                w -= 2 * focusSize;
                h -= 2 * focusSize;
            }

            int xThickness = style.getXThickness();
            int yThickness = style.getYThickness();

            ENGINE.startPainting(g, x, y, w, h, id, state);
            ENGINE.paintShadow(g, context, id, gtkState,
                               ShadowType.IN, "entry", x, y, w, h);
            ENGINE.paintFlatBox(g, context, id,
                                gtkState, ShadowType.NONE, "entry_bg",
                                x + xThickness,
                                y + yThickness,
                                w - (2 * xThickness),
                                h - (2 * yThickness),
                                ColorType.TEXT_BACKGROUND);

            if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) {
                if (!interiorFocus) {
                    x -=  focusSize;
                    y -=  focusSize;
                    w +=  2 * focusSize;
                    h +=  2 * focusSize;
                } else {
                    if (containerParent instanceof JComboBox) {
                        x += (focusSize + 2);
                        y += (focusSize + 1);
                        w -= (2 * focusSize + 1);
                        h -= (2 * focusSize + 2);
                    } else {
                        x += focusSize;
                        y += focusSize;
                        w -= 2 * focusSize;
                        h -= 2 * focusSize;
                    }
                }
                ENGINE.paintFocus(g, context, id, gtkState,
                        "entry", x, y, w, h);
            }
            ENGINE.finishPainting();
        }
    }

    private void paintTreeCellEditorBackground(SynthContext context, Graphics g,
                                               int x, int y, int w, int h) {
        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState)) {
                ENGINE.startPainting(g, x, y, w, h, id, gtkState);
                ENGINE.paintFlatBox(g, context, id, gtkState, ShadowType.NONE,
                        "entry_bg", x, y, w, h, ColorType.TEXT_BACKGROUND);
                ENGINE.finishPainting();
            }
        }
    }


    //
    // ROOT_PANE
    //
    public void paintRootPaneBackground(SynthContext context, Graphics g,
                                        int x, int y, int w, int h) {
        // Does not call into ENGINE for better performance
        fillArea(context, g, x, y, w, h, GTKColorType.BACKGROUND);
    }

    //
    // TOGGLE_BUTTON
    //
    public void paintToggleButtonBackground(SynthContext context,
                                            Graphics g,
                                            int x, int y, int w, int h) {
        Region id = context.getRegion();
        JToggleButton toggleButton = (JToggleButton)context.getComponent();
        boolean paintBG = toggleButton.isContentAreaFilled() &&
                          toggleButton.isBorderPainted();
        boolean paintFocus = toggleButton.isFocusPainted();
        boolean toolButton = (toggleButton.getParent() instanceof JToolBar);
        paintButtonBackgroundImpl(context, g, id, "button",
                                  x, y, w, h,
                                  paintBG, paintFocus, false, toolButton);
    }


    //
    // SCROLL_BAR
    //
    public void paintScrollBarBackground(SynthContext context,
                                          Graphics g,
                                          int x, int y, int w,int h) {
        Region id = context.getRegion();
        boolean focused =
                (context.getComponentState() & SynthConstants.FOCUSED) != 0;
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (ENGINE.paintCachedImage(g, x, y, w, h, id, focused)) {
                return;
            }
            ENGINE.startPainting(g, x, y, w, h, id, focused);

            // Note: the scrollbar insets already include the "trough-border",
            // which is needed to position the scrollbar buttons properly.
            // But when we render, we need to take the trough border out
            // of the equation so that we paint the entire area covered by
            // the trough border and the scrollbar content itself.
            Insets insets = context.getComponent().getInsets();
            GTKStyle style = (GTKStyle)context.getStyle();
            int troughBorder =
                style.getClassSpecificIntValue(context, "trough-border", 1);
            insets.left   -= troughBorder;
            insets.right  -= troughBorder;
            insets.top    -= troughBorder;
            insets.bottom -= troughBorder;

            ENGINE.paintBox(g, context, id, SynthConstants.PRESSED,
                            ShadowType.IN, "trough",
                            x + insets.left,
                            y + insets.top,
                            w - insets.left - insets.right,
                            h - insets.top - insets.bottom);

            if (focused) {
                ENGINE.paintFocus(g, context, id,
                        SynthConstants.ENABLED, "trough", x, y, w, h);
            }
            ENGINE.finishPainting();
        }
    }


    //
    // SCROLL_BAR_THUMB
    //
    public void paintScrollBarThumbBackground(SynthContext context,
            Graphics g, int x, int y, int w, int h, int dir) {
        Region id = context.getRegion();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                id, context.getComponentState());

        // The clearlooks engine paints scrollbar thumbs differently
        // depending on the current scroll value (specifically, it will avoid
        // rendering a certain line when the thumb is at the starting or
        // ending position).  Therefore, we normalize the current value to
        // the range [0,100] here and then pass it down to setRangeValue()
        // so that the native widget is configured appropriately.  Note that
        // there are really only four values that matter (min, middle, max,
        // or fill) so we restrict to one of those four values to avoid
        // blowing out the image cache.
        JScrollBar sb = (JScrollBar)context.getComponent();
        boolean rtl =
            sb.getOrientation() == JScrollBar.HORIZONTAL &&
            !sb.getComponentOrientation().isLeftToRight();
        double min = 0;
        double max = 100;
        double visible = 20;
        double value;
        if (sb.getMaximum() - sb.getMinimum() == sb.getVisibleAmount()) {
            // In this case, the thumb fills the entire track, so it is
            // touching both ends at the same time
            value = 0;
            visible = 100;
        } else if (sb.getValue() == sb.getMinimum()) {
            // At minimum
            value = rtl ? 100 : 0;
        } else if (sb.getValue() >= sb.getMaximum() - sb.getVisibleAmount()) {
            // At maximum
            value = rtl ? 0 : 100;
        } else {
            // Somewhere in between
            value = 50;
        }

        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState,
                                          dir, value, visible, rtl))
            {
                ENGINE.startPainting(g, x, y, w, h, id, gtkState,
                                     dir, value, visible, rtl);
                Orientation orientation = (dir == JScrollBar.HORIZONTAL ?
                    Orientation.HORIZONTAL : Orientation.VERTICAL);
                ENGINE.setRangeValue(context, id, value, min, max, visible);
                ENGINE.paintSlider(g, context, id, gtkState,
                        ShadowType.OUT, "slider", x, y, w, h, orientation);
                ENGINE.finishPainting();
            }
        }
    }

    //
    // TOOL_TIP
    //
    public void paintToolTipBackground(SynthContext context, Graphics g,
                                        int x, int y, int w,int h) {
        Region id = context.getRegion();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                ENGINE.startPainting(g, x, y, w, h, id);
                ENGINE.paintFlatBox(g, context, id, SynthConstants.ENABLED,
                        ShadowType.OUT, "tooltip", x, y, w, h,
                        ColorType.BACKGROUND);
                ENGINE.finishPainting();
            }
        }
    }


    //
    // TREE_CELL
    //
    public void paintTreeCellBackground(SynthContext context, Graphics g,
                                        int x, int y, int w, int h) {
        Region id = context.getRegion();
        int state = context.getComponentState();
        int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, state)) {
                ENGINE.startPainting(g, x, y, w, h, id, state);
                // the string arg should alternate based on row being painted,
                // but we currently don't pass that in.
                ENGINE.paintFlatBox(g, context, id, gtkState, ShadowType.NONE,
                        "cell_odd", x, y, w, h, ColorType.TEXT_BACKGROUND);
                ENGINE.finishPainting();
            }
        }
    }

    public void paintTreeCellFocus(SynthContext context, Graphics g,
                                    int x, int y, int w, int h) {
        Region id = Region.TREE_CELL;
        int state = context.getComponentState();
        paintFocus(context, g, id, state, "treeview", x, y, w, h);
    }


    //
    // TREE
    //
    public void paintTreeBackground(SynthContext context, Graphics g,
                                    int x, int y, int w, int h) {
        // As far as I can tell, these don't call into the ENGINE.
        fillArea(context, g, x, y, w, h, GTKColorType.TEXT_BACKGROUND);
    }


    //
    // VIEWPORT
    //
    public void paintViewportBackground(SynthContext context, Graphics g,
                                        int x, int y, int w, int h) {
        // As far as I can tell, these don't call into the ENGINE.
        // Also note that you don't want this to call into the ENGINE
        // as if it where to paint a background JViewport wouldn't scroll
        // correctly.
        fillArea(context, g, x, y, w, h, GTKColorType.TEXT_BACKGROUND);
    }

    void paintFocus(SynthContext context, Graphics g, Region id,
            int state, String detail, int x, int y, int w, int h) {
        int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, "focus")) {
                ENGINE.startPainting(g, x, y, w, h, id, gtkState, "focus");
                ENGINE.paintFocus(g, context, id, gtkState, detail, x, y, w, h);
                ENGINE.finishPainting();
            }
        }
    }

    void paintMetacityElement(SynthContext context, Graphics g,
            int gtkState, String detail, int x, int y, int w, int h,
            ShadowType shadow, ArrowType direction) {
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(
                    g, x, y, w, h, gtkState, detail, shadow, direction)) {
                ENGINE.startPainting(
                        g, x, y, w, h, gtkState, detail, shadow, direction);
                if (detail == "metacity-arrow") {
                    ENGINE.paintArrow(g, context, Region.INTERNAL_FRAME_TITLE_PANE,
                            gtkState, shadow, direction, "", x, y, w, h);

                } else if (detail == "metacity-box") {
                    ENGINE.paintBox(g, context, Region.INTERNAL_FRAME_TITLE_PANE,
                            gtkState, shadow, "", x, y, w, h);

                } else if (detail == "metacity-vline") {
                    ENGINE.paintVline(g, context, Region.INTERNAL_FRAME_TITLE_PANE,
                            gtkState, "", x, y, w, h);
                }
                ENGINE.finishPainting();
            }
        }
    }

    void paintIcon(SynthContext context, Graphics g,
            Method paintMethod, int x, int y, int w, int h) {
        int state = context.getComponentState();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g, x, y, w, h, state, paintMethod)) {
                ENGINE.startPainting(g, x, y, w, h, state, paintMethod);
                try {
                    paintMethod.invoke(this, context, g, state, x, y, w, h);
                } catch (IllegalAccessException iae) {
                    assert false;
                } catch (InvocationTargetException ite) {
                    assert false;
                }
                ENGINE.finishPainting();
            }
        }
    }

    void paintIcon(SynthContext context, Graphics g,
            Method paintMethod, int x, int y, int w, int h, Object direction) {
        int state = context.getComponentState();
        synchronized (UNIXToolkit.GTK_LOCK) {
            if (! ENGINE.paintCachedImage(g,
                    x, y, w, h, state, paintMethod, direction)) {
                ENGINE.startPainting(g,
                        x, y, w, h, state, paintMethod, direction);
                try {
                    paintMethod.invoke(this, context,
                            g, state, x, y, w, h, direction);
                } catch (IllegalAccessException iae) {
                    assert false;
                } catch (InvocationTargetException ite) {
                    assert false;
                }
                ENGINE.finishPainting();
            }
        }
    }

    // All icon painting methods are called from under GTK_LOCK

    public void paintTreeExpandedIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {
        ENGINE.paintExpander(g, context, Region.TREE,
                GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
                ExpanderStyle.EXPANDED, "treeview", x, y, w, h);
    }

    public void paintTreeCollapsedIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {
        ENGINE.paintExpander(g, context, Region.TREE,
                GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
                ExpanderStyle.COLLAPSED, "treeview", x, y, w, h);
    }

    public void paintCheckBoxIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {
        GTKStyle style = (GTKStyle)context.getStyle();
        int size = style.getClassSpecificIntValue(context,
                        "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE);
        int offset = style.getClassSpecificIntValue(context,
                        "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING);

        ENGINE.paintCheck(g, context, Region.CHECK_BOX, "checkbutton",
                x+offset, y+offset, size, size);
    }

    public void paintRadioButtonIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {
        GTKStyle style = (GTKStyle)context.getStyle();
        int size = style.getClassSpecificIntValue(context,
                        "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE);
        int offset = style.getClassSpecificIntValue(context,
                        "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING);

        ENGINE.paintOption(g, context, Region.RADIO_BUTTON, "radiobutton",
                x+offset, y+offset, size, size);
    }

    public void paintMenuArrowIcon(SynthContext context, Graphics g,
            int state, int x, int y, int w, int h, ArrowType dir) {
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                context.getRegion(), state);
        ShadowType shadow = ShadowType.OUT;
        if (gtkState == SynthConstants.MOUSE_OVER) {
            shadow = ShadowType.IN;
        }
        ENGINE.paintArrow(g, context, Region.MENU_ITEM, gtkState, shadow,
                dir, "menuitem", x + 3, y + 3, 7, 7);
    }

    public void paintCheckBoxMenuItemCheckIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {

        GTKStyle style = (GTKStyle)context.getStyle();
        int size = style.getClassSpecificIntValue(context,"indicator-size",
                GTKIconFactory.DEFAULT_TOGGLE_MENU_ITEM_SIZE);

        ENGINE.paintCheck(g, context, Region.CHECK_BOX_MENU_ITEM, "check",
                x + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
                y + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
                size, size);
    }

    public void paintRadioButtonMenuItemCheckIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {

        GTKStyle style = (GTKStyle)context.getStyle();
        int size = style.getClassSpecificIntValue(context,"indicator-size",
                GTKIconFactory.DEFAULT_TOGGLE_MENU_ITEM_SIZE);

        ENGINE.paintOption(g, context, Region.RADIO_BUTTON_MENU_ITEM, "option",
                x + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
                y + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
                size, size);
    }

    public void paintToolBarHandleIcon(SynthContext context, Graphics g,
            int state, int x, int y, int w, int h, Orientation orientation) {
        int gtkState = GTKLookAndFeel.synthStateToGTKState(
                context.getRegion(), state);

        // The orientation parameter passed down by Synth refers to the
        // orientation of the toolbar, but the one we pass to GTK refers
        // to the orientation of the handle.  Therefore, we need to swap
        // the value here: horizontal toolbars have vertical handles, and
        // vice versa.
        orientation = (orientation == Orientation.HORIZONTAL) ?
            Orientation.VERTICAL : Orientation.HORIZONTAL;

        ENGINE.paintHandle(g, context, Region.TOOL_BAR, gtkState,
                ShadowType.OUT, "handlebox", x, y, w, h, orientation);
    }

    public void paintAscendingSortIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {
        ENGINE.paintArrow(g, context, Region.TABLE, SynthConstants.ENABLED,
                ShadowType.IN, ArrowType.UP, "arrow", x, y, w, h);
    }

    public void paintDescendingSortIcon(SynthContext context,
            Graphics g, int state, int x, int y, int w, int h) {
        ENGINE.paintArrow(g, context, Region.TABLE, SynthConstants.ENABLED,
                ShadowType.IN, ArrowType.DOWN, "arrow", x, y, w, h);
    }

    /*
     * Fill an area with color determined from this context's Style using the
     * specified GTKColorType
     */
    private void fillArea(SynthContext context, Graphics g,
                          int x, int y, int w, int h, ColorType colorType) {
        if (context.getComponent().isOpaque()) {
            Region id = context.getRegion();
            int gtkState = GTKLookAndFeel.synthStateToGTKState(id,
                    context.getComponentState());
            GTKStyle style = (GTKStyle)context.getStyle();

            g.setColor(style.getGTKColor(context, gtkState, colorType));
            g.fillRect(x, y, w, h);
        }
    }

    // Refer to GTKLookAndFeel for details on this.
    static class ListTableFocusBorder extends AbstractBorder implements
                          UIResource {

        private boolean selectedCell;
        private boolean focusedCell;

        public static ListTableFocusBorder getSelectedCellBorder() {
            return new ListTableFocusBorder(true, true);
        }

        public static ListTableFocusBorder getUnselectedCellBorder() {
            return new ListTableFocusBorder(false, true);
        }

        public static ListTableFocusBorder getNoFocusCellBorder() {
            return new ListTableFocusBorder(false, false);
        }

        public ListTableFocusBorder(boolean selectedCell, boolean focusedCell) {
            this.selectedCell = selectedCell;
            this.focusedCell = focusedCell;
        }

        private SynthContext getContext(Component c) {
            SynthContext context = null;

            ComponentUI ui = null;
            if (c instanceof JLabel) {
                ui = ((JLabel)c).getUI();
            }

            if (ui instanceof SynthUI) {
                context = ((SynthUI)ui).getContext((JComponent)c);
            }

            return context;
        }

        public void paintBorder(Component c, Graphics g, int x, int y,
                                int w, int h) {
            if (focusedCell) {
                SynthContext context = getContext(c);
                int state = (selectedCell? SynthConstants.SELECTED:
                             SynthConstants.FOCUSED | SynthConstants.ENABLED);

                if (context != null) {
                    GTKPainter.INSTANCE.paintFocus(context, g,
                            Region.TABLE, state, "", x, y, w, h);
                }
            }
        }

        public Insets getBorderInsets(Component c, Insets i) {
            SynthContext context = getContext(c);

            if (context != null) {
                i = context.getStyle().getInsets(context, i);
            }

            return i;
        }

        public boolean isBorderOpaque() {
            return true;
        }
    }

    // TitledBorder implementation for GTK L&F
    static class TitledBorder extends AbstractBorder implements UIResource {

        public void paintBorder(Component c, Graphics g, int x, int y,
                                int w, int h) {
            SynthContext context = getContext((JComponent)c);
            Region id = context.getRegion();
            int state = context.getComponentState();
            int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);

            synchronized (UNIXToolkit.GTK_LOCK) {
                if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
                    ENGINE.startPainting(g, x, y, w, h, id);
                    ENGINE.paintShadow(g, context, id, gtkState, ShadowType.ETCHED_IN,
                                      "frame", x, y, w, h);
                    ENGINE.finishPainting();
                }
            }
        }

        public Insets getBorderInsets(Component c, Insets i) {
            SynthContext context = getContext((JComponent)c);
            return context.getStyle().getInsets(context, i);
        }

        public boolean isBorderOpaque() {
            return true;
        }

        private SynthStyle getStyle(JComponent c) {
            return SynthLookAndFeel.getStyle(c, GTKEngine.CustomRegion.TITLED_BORDER);
        }

        private SynthContext getContext(JComponent c) {
            int state = SynthConstants.DEFAULT;
            return new SynthContext(c, GTKEngine.CustomRegion.TITLED_BORDER,
                                    getStyle(c), state);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java GTKPainter.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.