/* * Copyright (c) 2007, 2011, 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.tools.visualvm.uisupport; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.basic.BasicComboBoxEditor; import javax.swing.plaf.basic.BasicComboBoxRenderer; /** * 1.3.8 - added initial support for vertical toolbar, not fully implemented * * @author Jiri Sedlacek */ public final class TransparentToolBar extends JPanel { private static Boolean NEEDS_PANEL; private static int PREFERRED_HEIGHT = -1; private static int BUTTON_HEIGHT = -1; private final JToolBar toolbar; private final ItemListener listener = new ItemListener(); private final boolean horizontal; public TransparentToolBar() { this(true); } public TransparentToolBar(boolean horizontal) { this.horizontal = horizontal; setOpaque(false); setBorder(createToolBarBorder(horizontal)); if (needsPanel()) { // Toolbar is a JPanel (GTK) toolbar = null; setLayout(new BoxLayout(this, horizontal ? BoxLayout.X_AXIS : BoxLayout.Y_AXIS)); } else { // Toolbar is a JToolBar (default) toolbar = createToolBar(horizontal); toolbar.setBorder(BorderFactory.createEmptyBorder()); setLayout(new BorderLayout()); add(toolbar, BorderLayout.CENTER); } addHierarchyListener(new HierarchyListener() { public void hierarchyChanged(HierarchyEvent e) { if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { if (isShowing()) { removeHierarchyListener(this); for (Component c : getComponents()) { if (c instanceof AbstractButton) { listener.refresh((AbstractButton)c); } } } } } }); } public Dimension getPreferredSize() { Dimension dim = getPreferredSizeSuper(); if (horizontal) { if (PREFERRED_HEIGHT == -1) { TransparentToolBar tb = new TransparentToolBar(); Icon icon = new Icon() { public int getIconWidth() { return 16; } public int getIconHeight() { return 16; } public void paintIcon(Component c, Graphics g, int x, int y) {} }; JButton b = new JButton("Button", icon); // NOI18N tb.addItem(b); JToggleButton t = new JToggleButton("Button", icon); // NOI18N tb.addItem(t); JComboBox c = new JComboBox(); c.setEditor(new BasicComboBoxEditor()); c.setRenderer(new BasicComboBoxRenderer()); tb.addItem(c); tb.addSeparator(); PREFERRED_HEIGHT = tb.getPreferredSizeSuper().height; } dim.height = Math.max(dim.height, PREFERRED_HEIGHT); } return dim; } private Dimension getPreferredSizeSuper() { return super.getPreferredSize(); } public Component addItem(Action action) { return addItem(createActionComponent(action)); } public Component addItem(Component c) { return addItem(c, -1); } public Component addItem(Component c, int index) { if (c instanceof JComponent) ((JComponent)c).setOpaque(false); if (c instanceof JButton) ((JButton)c).setDefaultCapable(false); if (UISupport.isAquaLookAndFeel() && c instanceof AbstractButton) ((AbstractButton)c).putClientProperty("JButton.buttonType", "gradient"); // NOI18N if (toolbar != null) { toolbar.add(c, index); } else { add(c, index); if (c instanceof AbstractButton) { AbstractButton b = (AbstractButton) c; b.addMouseListener(listener); b.addChangeListener(listener); b.addFocusListener(listener); b.setRolloverEnabled(true); listener.refresh(b); } } repaint(); return c; } public void removeItem(Component c) { if (toolbar != null) { toolbar.remove(c); } else { if (c instanceof AbstractButton) { c.removeMouseListener(listener); ((AbstractButton) c).removeChangeListener(listener); c.removeFocusListener(listener); } remove(c); } repaint(); } public void removeItem(int index) { if (toolbar != null) { toolbar.remove(index); } else { removeItem(getComponent(index)); } } public int getItemsCount() { if (toolbar != null) { return toolbar.getComponentCount(); } else { return super.getComponentCount(); } } public void addSeparator() { JToolBar.Separator separator = new JToolBar.Separator(); separator.setOrientation(horizontal ? JToolBar.Separator.VERTICAL : JToolBar.Separator.HORIZONTAL); addItem(separator); } public void addSpace(int width) { Dimension dim = horizontal ? new Dimension(width, 0) : new Dimension(0, width); JToolBar.Separator separator = new JToolBar.Separator(dim); separator.setOrientation(horizontal ? JToolBar.Separator.VERTICAL : JToolBar.Separator.HORIZONTAL); addItem(separator); } public void addFiller() { Dimension minDim = new Dimension(0, 0); Dimension maxDim = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); Box.Filler filler = new Box.Filler(minDim, minDim, maxDim) { protected void paintComponent(Graphics g) {} }; addItem(filler); } public static JComponent withSeparator(TransparentToolBar toolbar) { JPanel panel = new JPanel(new BorderLayout(0, 0)); panel.setOpaque(false); panel.add(toolbar, BorderLayout.CENTER); panel.add(new SeparatorLine(true), toolbar.horizontal ? BorderLayout.SOUTH : BorderLayout.EAST); return panel; } private JButton createActionComponent(Action a) { JButton b = new JButton(); if (a != null && (a.getValue(Action.SMALL_ICON) != null || a.getValue(Action.LARGE_ICON_KEY) != null)) { b.setHideActionText(true); } b.setHorizontalTextPosition(JButton.CENTER); b.setVerticalTextPosition(JButton.BOTTOM); b.setAction(a); return b; } private static JToolBar createToolBar(final boolean horizontal) { JToolBar tb = new JToolBar(horizontal ? JToolBar.HORIZONTAL : JToolBar.VERTICAL) { public void layout() { super.layout(); if (horizontal) { if (BUTTON_HEIGHT == -1) BUTTON_HEIGHT = getButtonHeight(); Insets i = getInsets(); int height = getHeight() - i.top - i.bottom; for (Component comp : getComponents()) { if (comp.isVisible() && (comp instanceof JButton || comp instanceof JToggleButton)) { Rectangle b = comp.getBounds(); b.height = BUTTON_HEIGHT; b.y = i.top + (height - b.height) / 2; comp.setBounds(b); } } } } }; if (UISupport.isNimbusLookAndFeel()) tb.setLayout(new BoxLayout(tb, horizontal ? BoxLayout.X_AXIS : BoxLayout.Y_AXIS)); tb.setBorderPainted(false); tb.setFloatable(false); tb.setRollover(true); tb.setOpaque(false); return tb; } private static Border createToolBarBorder(boolean horizontal) { if (horizontal) { if (UISupport.isAquaLookAndFeel()) { return BorderFactory.createEmptyBorder(-1, 2, -1, 2); } else if (UISupport.isNimbusLookAndFeel()) { return BorderFactory.createEmptyBorder(1, 2, 1, 2); } else { return BorderFactory.createEmptyBorder(2, 2, 2, 2); } } else { if (UISupport.isAquaLookAndFeel()) { return BorderFactory.createEmptyBorder(-1, 0, -1, 0); } else { return BorderFactory.createEmptyBorder(); } } } private static int getButtonHeight() { Icon icon = new Icon() { public int getIconWidth() { return 16; } public int getIconHeight() { return 16; } public void paintIcon(Component c, Graphics g, int x, int y) {} }; JButton b = new JButton("Button", icon); // NOI18N JToolBar tb = new JToolBar(); tb.setBorder(BorderFactory.createEmptyBorder()); tb.setBorderPainted(false); tb.add(b); int bsize = tb.getPreferredSize().height; JToggleButton t = new JToggleButton("Button", icon); // NOI18N tb = new JToolBar(); tb.setBorder(BorderFactory.createEmptyBorder()); tb.setBorderPainted(false); tb.add(t); int tbsize = tb.getPreferredSize().height; if (UISupport.isAquaLookAndFeel()) return Math.max(bsize, tbsize) + 4; else if (UISupport.isMetalLookAndFeel()) return Math.max(bsize, tbsize) - 2; return Math.max(bsize, tbsize); } private static boolean needsPanel() { if (NEEDS_PANEL == null) NEEDS_PANEL = UISupport.isGTKLookAndFeel(); return NEEDS_PANEL; } private static final class ItemListener extends MouseAdapter implements ChangeListener, FocusListener { private static final String PROP_HOVERED = "BUTTON_HOVERED"; // NOI18N public void mouseEntered(MouseEvent e) { AbstractButton b = (AbstractButton) e.getSource(); b.putClientProperty(PROP_HOVERED, Boolean.TRUE); refresh(b); } public void mouseExited(MouseEvent e) { AbstractButton b = (AbstractButton) e.getSource(); b.putClientProperty(PROP_HOVERED, Boolean.FALSE); refresh(b); } public void stateChanged(ChangeEvent e) { refresh((AbstractButton) e.getSource()); } public void focusGained(FocusEvent e) { refresh((AbstractButton) e.getSource()); } public void focusLost(FocusEvent e) { refresh((AbstractButton) e.getSource()); } private void refresh(final AbstractButton b) { b.setBackground(UISupport.getDefaultBackground()); boolean hovered = Boolean.TRUE.equals(b.getClientProperty(PROP_HOVERED)); boolean filled = b.isEnabled() && (hovered || b.isSelected() || b.isFocusOwner()); b.setOpaque(filled); b.setContentAreaFilled(filled); b.repaint(); } } }