/* * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * muCommander 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 for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.mucommander.ui.button; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.AbstractButton; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import com.mucommander.commons.runtime.OsFamily; import com.mucommander.commons.runtime.OsVersion; import com.mucommander.ui.icon.IconManager; /* * MySwing: Advanced Swing Utilites * Copyright (C) 2005 Santhosh Kumar T * <p/> * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * <p/> * This library 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 * Lesser General Public License for more details. */ /** * Provides a way for toolbar buttons to be displayed when the toolbar itself doesn't have enough space for all buttons. * The buttons that are cropped are displayed in a secondary toolbar, using a vertical layout. * <p> * To use this Feature replace: * <code> * frame.getContentPane().add(toolbar, BorderLayout.NORTH); * </code> * with * <code> * frame.getContentPane().add(MoreButton.wrapToolBar(toolBar), BorderLayout.NORTH); * </code> * </p> * <p> * This class is based on the code of Santhosh Kumar T, see * <a href="http://www.jroller.com/santhosh/entry/jtoolbar_with_more_button">this link</a> for more information. * </p> * * @author Santhosh Kumar T, Leo Welsch */ public class ToolbarMoreButton extends JToggleButton implements ActionListener { private static JToolBar moreToolbar; JToolBar toolbar; protected ToolbarMoreButton(final JToolBar toolbar) { super(IconManager.getIcon(IconManager.COMMON_ICON_SET, "more.png")); this.toolbar = toolbar; addActionListener(this); setFocusPainted(false); setMargin(new Insets(0, 0, 0, 0)); setContentAreaFilled(false); setBorderPainted(false); // Use new JButton decorations introduced in Mac OS X 10.5 (Leopard) if (OsFamily.MAC_OS_X.isCurrent() && OsVersion.MAC_OS_X_10_5.isCurrentOrHigher()) { putClientProperty("JComponent.sizeVariant", "small"); putClientProperty("JButton.buttonType", "textured"); } // paint border only when necessary addMouseListener(new MouseAdapter() { @Override public void mouseExited(MouseEvent e) { setBorderPainted(false); } @Override public void mouseEntered(MouseEvent e) { setBorderPainted(true); } }); // hide & seek toolbar.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { int nbToolbarComponents = toolbar.getComponentCount(); final boolean aFlag = nbToolbarComponents>0 && !isVisible(toolbar.getComponent(nbToolbarComponents-1), null); setVisible(aFlag); moreToolbar.setVisible(aFlag); } }); } // check visibility // partially visible is treated as not visible private boolean isVisible(Component comp, Rectangle rect) { if (rect == null) { rect = toolbar.getVisibleRect(); } return comp.getLocation().x + comp.getWidth() <= rect.getWidth(); } public void actionPerformed(ActionEvent e) { Component[] comp = toolbar.getComponents(); Rectangle visibleRect = toolbar.getVisibleRect(); for (int i = 0; i < comp.length; i++) { if (!isVisible(comp[i], visibleRect)) { JPopupMenu popup = new JPopupMenu(); for (; i < comp.length; i++) { if (comp[i] instanceof AbstractButton) { AbstractButton button = (AbstractButton) comp[i]; if (button.getAction() != null) { popup.add(button.getAction()); } } else if (comp[i] instanceof JSeparator) { popup.addSeparator(); } } // on popup close make more-button unselected popup.addPopupMenuListener(new PopupMenuListener() { public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { setSelected(false); } public void popupMenuCanceled(PopupMenuEvent e) { } public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } }); popup.show(this, 0, getHeight()); } } } public static JPanel wrapToolBar(JToolBar toolbar) { moreToolbar = new JToolBar(); moreToolbar.setRollover(true); moreToolbar.setFloatable(false); moreToolbar.add(new ToolbarMoreButton(toolbar)); moreToolbar.setBorderPainted(false); JPanel panel = new JPanel(new BorderLayout()); panel.add(toolbar, BorderLayout.CENTER); panel.add(moreToolbar, BorderLayout.EAST); return panel; } }