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

Java example source code file (BorderedComponent.java)

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

arrowicon, awt, border, borderedcomponent, dimension, edge_spacing, event, focusborder, graphics, gui, insets, jcomponent, jlabel, jpanel, labeledborder, plaf, rectangle, swing, text_spacing, titledborder

The BorderedComponent.java Java example source code

/*
 * Copyright (c) 2004, 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 sun.tools.jconsole;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicGraphicsUtils;


import static javax.swing.SwingConstants.*;

import static sun.tools.jconsole.JConsole.*;

@SuppressWarnings("serial")
public class BorderedComponent extends JPanel implements ActionListener {
    JButton moreOrLessButton;
    String valueLabelStr;
    JLabel label;
    JComponent comp;
    boolean collapsed = false;

    private Icon collapseIcon;
    private Icon expandIcon;

    private static Image getImage(String name) {
        Toolkit tk = Toolkit.getDefaultToolkit();
        name = "resources/" + name + ".png";
        return tk.getImage(BorderedComponent.class.getResource(name));
    }

    public BorderedComponent(String text) {
        this(text, null, false);
    }

    public BorderedComponent(String text, JComponent comp) {
        this(text, comp, false);
    }

    public BorderedComponent(String text, JComponent comp, boolean collapsible) {
        super(null);

        this.comp = comp;

        // Only add border if text is not null
        if (text != null) {
            TitledBorder border;
            if (collapsible) {
                final JLabel textLabel = new JLabel(text);
                JPanel borderLabel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0)) {
                    public int getBaseline(int w, int h) {
                        Dimension dim = textLabel.getPreferredSize();
                        return textLabel.getBaseline(dim.width, dim.height) + textLabel.getY();
                    }
                };
                borderLabel.add(textLabel);
                border = new LabeledBorder(borderLabel);
                textLabel.setForeground(border.getTitleColor());

                if (IS_WIN) {
                    collapseIcon = new ImageIcon(getImage("collapse-winlf"));
                    expandIcon = new ImageIcon(getImage("expand-winlf"));
                } else {
                    collapseIcon = new ArrowIcon(SOUTH, textLabel);
                    expandIcon = new ArrowIcon(EAST, textLabel);
                }

                moreOrLessButton = new JButton(collapseIcon);
                moreOrLessButton.setContentAreaFilled(false);
                moreOrLessButton.setBorderPainted(false);
                moreOrLessButton.setMargin(new Insets(0, 0, 0, 0));
                moreOrLessButton.addActionListener(this);
                String toolTip =
                    Messages.BORDERED_COMPONENT_MORE_OR_LESS_BUTTON_TOOLTIP;
                moreOrLessButton.setToolTipText(toolTip);
                borderLabel.add(moreOrLessButton);
                borderLabel.setSize(borderLabel.getPreferredSize());
                add(borderLabel);
            } else {
                border = new TitledBorder(text);
            }
            setBorder(new CompoundBorder(new FocusBorder(this), border));
        } else {
            setBorder(new FocusBorder(this));
        }
        if (comp != null) {
            add(comp);
        }
    }

    public void setComponent(JComponent comp) {
        if (this.comp != null) {
            remove(this.comp);
        }
        this.comp = comp;
        if (!collapsed) {
            LayoutManager lm = getLayout();
            if (lm instanceof BorderLayout) {
                add(comp, BorderLayout.CENTER);
            } else {
                add(comp);
            }
        }
        revalidate();
    }

    public void setValueLabel(String str) {
        this.valueLabelStr = str;
        if (label != null) {
            label.setText(Resources.format(Messages.CURRENT_VALUE,
                                           valueLabelStr));
        }
    }

    public void actionPerformed(ActionEvent ev) {
        if (collapsed) {
            if (label != null) {
                remove(label);
            }
            add(comp);
            moreOrLessButton.setIcon(collapseIcon);
        } else {
            remove(comp);
            if (valueLabelStr != null) {
                if (label == null) {
                    label = new JLabel(Resources.format(Messages.CURRENT_VALUE,
                                                        valueLabelStr));
                }
                add(label);
            }
            moreOrLessButton.setIcon(expandIcon);
        }
        collapsed = !collapsed;

        JComponent container = (JComponent)getParent();
        if (container != null &&
            container.getLayout() instanceof VariableGridLayout) {

            ((VariableGridLayout)container.getLayout()).setFillRow(this, !collapsed);
            container.revalidate();
        }
    }

    public Dimension getMinimumSize() {
        if (getLayout() != null) {
            // A layout manager has been set, so delegate to it
            return super.getMinimumSize();
        }

        if (moreOrLessButton != null) {
            Dimension d = moreOrLessButton.getMinimumSize();
            Insets i = getInsets();
            d.width  += i.left + i.right;
            d.height += i.top + i.bottom;
            return d;
        } else {
            return super.getMinimumSize();
        }
    }

    public void doLayout() {
        if (getLayout() != null) {
            // A layout manager has been set, so delegate to it
            super.doLayout();
            return;
        }

        Dimension d = getSize();
        Insets i = getInsets();

        if (collapsed) {
            if (label != null) {
                Dimension p = label.getPreferredSize();
                label.setBounds(i.left,
                                i.top + (d.height - i.top - i.bottom - p.height) / 2,
                                p.width,
                                p.height);
            }
        } else {
            if (comp != null) {
                comp.setBounds(i.left,
                               i.top,
                               d.width - i.left - i.right,
                               d.height - i.top - i.bottom);
            }
        }
    }

    private static class ArrowIcon implements Icon {
        private int direction;
        private JLabel textLabel;

        public ArrowIcon(int direction, JLabel textLabel) {
            this.direction = direction;
            this.textLabel = textLabel;
        }

        public void paintIcon(Component c, Graphics g, int x, int y) {
            int w = getIconWidth();
            int h = w;
            Polygon p = new Polygon();
            switch (direction) {
              case EAST:
                p.addPoint(x + 2,     y);
                p.addPoint(x + w - 2, y + h / 2);
                p.addPoint(x + 2,     y + h - 1);
                break;

              case SOUTH:
                p.addPoint(x,         y + 2);
                p.addPoint(x + w / 2, y + h - 2);
                p.addPoint(x + w - 1, y + 2);
                break;
            }
            g.fillPolygon(p);
        }

        public int getIconWidth() {
            return getIconHeight();
        }

        public int getIconHeight() {
            Graphics g = textLabel.getGraphics();
            if (g != null) {
                int h = g.getFontMetrics(textLabel.getFont()).getAscent() * 6/10;
                if (h % 2 == 0) {
                    h += 1;     // Make it odd
                }
                return h;
            } else {
                return 7;
            }
        }
    }


    /**
     * A subclass of <code>TitledBorder which implements an arbitrary border
     * with the addition of a JComponent (JLabel, JPanel, etc) in the
     * default position.
     * <p>
     * If the border property value is not
     * specified in the constructor or by invoking the appropriate
     * set method, the property value will be defined by the current
     * look and feel, using the following property name in the
     * Defaults Table:
     * <ul>
     * <li>"TitledBorder.border"
     * </ul>
     */
    protected static class LabeledBorder extends TitledBorder {
        protected JComponent label;

        private Point compLoc = new Point();

        /**
         * Creates a LabeledBorder instance.
         *
         * @param label  the label the border should display
         */
        public LabeledBorder(JComponent label)     {
            this(null, label);
        }

        /**
         * Creates a LabeledBorder instance with the specified border
         * and an empty label.
         *
         * @param border  the border
         */
        public LabeledBorder(Border border)       {
            this(border, null);
        }

        /**
         * Creates a LabeledBorder instance with the specified border and
         * label.
         *
         * @param border  the border
         * @param label  the label the border should display
         */
        public LabeledBorder(Border border, JComponent label) {
            super(border);

            this.label = label;

            if (label instanceof JLabel &&
                label.getForeground() instanceof ColorUIResource) {

                label.setForeground(getTitleColor());
            }

        }

        /**
         * Paints the border for the specified component with the
         * specified position and size.
         * @param c the component for which this border is being painted
         * @param g the paint graphics
         * @param x the x position of the painted border
         * @param y the y position of the painted border
         * @param width the width of the painted border
         * @param height the height of the painted border
         */
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {

            Border border = getBorder();

            if (label == null) {
                if (border != null) {
                    border.paintBorder(c, g, x, y, width, height);
                }
                return;
            }

            Rectangle grooveRect = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING,
                                                 width - (EDGE_SPACING * 2),
                                                 height - (EDGE_SPACING * 2));

            Dimension   labelDim = label.getPreferredSize();
            int baseline = label.getBaseline(labelDim.width, labelDim.height);
            int         ascent = Math.max(0, baseline);
            int         descent = labelDim.height - ascent;
            int         diff;
            Insets      insets;

            if (border != null) {
                insets = border.getBorderInsets(c);
            } else {
                insets = new Insets(0, 0, 0, 0);
            }

            diff = Math.max(0, ascent/2 + TEXT_SPACING - EDGE_SPACING);
            grooveRect.y += diff;
            grooveRect.height -= diff;
            compLoc.y = grooveRect.y + insets.top/2 - (ascent + descent) / 2 - 1;

            int justification;
            if (c.getComponentOrientation().isLeftToRight()) {
                justification = LEFT;
            } else {
                justification = RIGHT;
            }

            switch (justification) {
                case LEFT:
                    compLoc.x = grooveRect.x + TEXT_INSET_H + insets.left;
                    break;
                case RIGHT:
                    compLoc.x = (grooveRect.x + grooveRect.width
                                 - (labelDim.width + TEXT_INSET_H + insets.right));
                    break;
            }

            // If title is positioned in middle of border AND its fontsize
            // is greater than the border's thickness, we'll need to paint
            // the border in sections to leave space for the component's background
            // to show through the title.
            //
            if (border != null) {
                if (grooveRect.y > compLoc.y - ascent) {
                    Rectangle clipRect = new Rectangle();

                    // save original clip
                    Rectangle saveClip = g.getClipBounds();

                    // paint strip left of text
                    clipRect.setBounds(saveClip);
                    if (computeIntersection(clipRect, x, y, compLoc.x-1-x, height)) {
                        g.setClip(clipRect);
                        border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                      grooveRect.width, grooveRect.height);
                    }

                    // paint strip right of text
                    clipRect.setBounds(saveClip);
                    if (computeIntersection(clipRect, compLoc.x+ labelDim.width +1, y,
                                   x+width-(compLoc.x+ labelDim.width +1), height)) {
                        g.setClip(clipRect);
                        border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                      grooveRect.width, grooveRect.height);
                    }

                    // paint strip below text
                    clipRect.setBounds(saveClip);
                    if (computeIntersection(clipRect,
                                            compLoc.x - 1, compLoc.y + ascent + descent,
                                            labelDim.width + 2,
                                            y + height - compLoc.y - ascent - descent)) {
                        g.setClip(clipRect);
                        border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                  grooveRect.width, grooveRect.height);
                    }

                    // restore clip
                    g.setClip(saveClip);

                } else {
                    border.paintBorder(c, g, grooveRect.x, grooveRect.y,
                                      grooveRect.width, grooveRect.height);
                }

                label.setLocation(compLoc);
                label.setSize(labelDim);
            }
        }

        /**
         * Reinitialize the insets parameter with this Border's current Insets.
         * @param c the component for which this border insets value applies
         * @param insets the object to be reinitialized
         */
        public Insets getBorderInsets(Component c, Insets insets) {
            Border border = getBorder();
            if (border != null) {
                if (border instanceof AbstractBorder) {
                    ((AbstractBorder)border).getBorderInsets(c, insets);
                } else {
                    // Can't reuse border insets because the Border interface
                    // can't be enhanced.
                    Insets i = border.getBorderInsets(c);
                    insets.top = i.top;
                    insets.right = i.right;
                    insets.bottom = i.bottom;
                    insets.left = i.left;
                }
            } else {
                insets.left = insets.top = insets.right = insets.bottom = 0;
            }

            insets.left += EDGE_SPACING + TEXT_SPACING;
            insets.right += EDGE_SPACING + TEXT_SPACING;
            insets.top += EDGE_SPACING + TEXT_SPACING;
            insets.bottom += EDGE_SPACING + TEXT_SPACING;

            if (c == null || label == null) {
                return insets;
            }

            insets.top += label.getHeight();

            return insets;
        }

        /**
         * Returns the label of the labeled border.
         */
        public JComponent getLabel() {
            return label;
        }


        /**
         * Sets the title of the titled border.
         * param title the title for the border
         */
        public void setLabel(JComponent label) {
            this.label = label;
        }



        /**
         * Returns the minimum dimensions this border requires
         * in order to fully display the border and title.
         * @param c the component where this border will be drawn
         */
        public Dimension getMinimumSize(Component c) {
            Insets insets = getBorderInsets(c);
            Dimension minSize = new Dimension(insets.right + insets.left,
                                              insets.top + insets.bottom);
            minSize.width += label.getWidth();

            return minSize;
        }


        private static boolean computeIntersection(Rectangle dest,
                                                   int rx, int ry, int rw, int rh) {
            int x1 = Math.max(rx, dest.x);
            int x2 = Math.min(rx + rw, dest.x + dest.width);
            int y1 = Math.max(ry, dest.y);
            int y2 = Math.min(ry + rh, dest.y + dest.height);
            dest.x = x1;
            dest.y = y1;
            dest.width = x2 - x1;
            dest.height = y2 - y1;

            if (dest.width <= 0 || dest.height <= 0) {
                return false;
            }
            return true;
        }
    }


    protected static class FocusBorder extends AbstractBorder implements FocusListener {
        private Component comp;
        private Color focusColor;
        private boolean focusLostTemporarily = false;

        public FocusBorder(Component comp) {
            this.comp = comp;

            comp.addFocusListener(this);

            // This is the best guess for a L&F specific color
            focusColor = UIManager.getColor("TabbedPane.focus");
        }

        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            if (comp.hasFocus() || focusLostTemporarily) {
                Color color = g.getColor();
                g.setColor(focusColor);
                BasicGraphicsUtils.drawDashedRect(g, x, y, width, height);
                g.setColor(color);
            }
        }

        public Insets getBorderInsets(Component c, Insets insets) {
            insets.set(2, 2, 2, 2);
            return insets;
        }


        public void focusGained(FocusEvent e) {
            comp.repaint();
        }

        public void focusLost(FocusEvent e) {
            // We will still paint focus even if lost temporarily
            focusLostTemporarily = e.isTemporary();
            if (!focusLostTemporarily) {
                comp.repaint();
            }
        }
    }
}

Other Java examples (source code examples)

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

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

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 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.