/* * 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.main.toolbar; import java.awt.Component; import java.awt.Dimension; import java.awt.Insets; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Hashtable; import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JPopupMenu; import javax.swing.JToolBar; import com.mucommander.commons.conf.ConfigurationEvent; import com.mucommander.commons.conf.ConfigurationListener; import com.mucommander.commons.file.FileURL; import com.mucommander.commons.runtime.OsFamily; import com.mucommander.commons.runtime.OsVersion; import com.mucommander.conf.MuConfigurations; import com.mucommander.conf.MuPreference; import com.mucommander.conf.MuPreferences; import com.mucommander.desktop.DesktopManager; import com.mucommander.ui.action.ActionManager; import com.mucommander.ui.action.MuAction; import com.mucommander.ui.action.impl.GoBackAction; import com.mucommander.ui.action.impl.GoForwardAction; import com.mucommander.ui.action.impl.OpenLocationAction; import com.mucommander.ui.action.impl.ToggleToolBarAction; import com.mucommander.ui.button.NonFocusableButton; import com.mucommander.ui.button.PopupButton; import com.mucommander.ui.button.RolloverButtonAdapter; import com.mucommander.ui.icon.IconManager; import com.mucommander.ui.main.MainFrame; /** * This class is the icon toolbar attached to a MainFrame, triggering events when buttons are clicked. * * @author Maxence Bernard, Arik Hadas */ public class ToolBar extends JToolBar implements ConfigurationListener, MouseListener, ToolBarAttributesListener { private MainFrame mainFrame; /** Holds a reference to the RolloverButtonAdapter instance so that it doesn't get garbage-collected */ private RolloverButtonAdapter rolloverButtonAdapter; /** Dimension of button separators */ private final static Dimension SEPARATOR_DIMENSION = new Dimension(10, 16); /** Whether to use the new JButton decorations introduced in Mac OS X 10.5 (Leopard) */ private final static boolean USE_MAC_OS_X_CLIENT_PROPERTIES = OsFamily.MAC_OS_X.isCurrent() && OsVersion.MAC_OS_X_10_5.isCurrentOrHigher(); /** Current icon scale value */ // The math.max(1.0f, ...) part is to workaround a bug which cause(d) this value to be set to 0.0 in the configuration file. private static float scaleFactor = Math.max(1.0f, MuConfigurations.getPreferences().getVariable(MuPreference.TOOLBAR_ICON_SCALE, MuPreferences.DEFAULT_TOOLBAR_ICON_SCALE)); /** * Creates a new toolbar and attaches it to the given frame. */ public ToolBar(MainFrame mainFrame) { this.mainFrame = mainFrame; // Decoration properties setBorderPainted(false); setFloatable(false); putClientProperty("JToolBar.isRollover", Boolean.TRUE); // Listen to mouse events in order to popup a menu when toolbar is right-clicked addMouseListener(this); // Listen to configuration changes to reload toolbar buttons when icon size has changed MuConfigurations.addPreferencesListener(this); // Rollover-enable the button and hold a reference to the RolloverButtonAdapter instance so that it doesn't // get garbage-collected rolloverButtonAdapter = new RolloverButtonAdapter(); // Create buttons for each actions and add them to the toolbar addButtons(ToolBarAttributes.getActions()); ToolBarAttributes.addToolBarAttributesListener(this); } private void addButtons(String[] actionIds) { for (String actionId : actionIds) { if(actionId==null) addSeparator(SEPARATOR_DIMENSION); else { // Get a MuAction instance MuAction action = ActionManager.getActionInstance(actionId, mainFrame); // Do not add buttons for actions that do not have an icon if(action.getIcon()!=null) addButton(action); } } if(USE_MAC_OS_X_CLIENT_PROPERTIES) { int nbComponents = getComponentCount(); // Set the 'segment position' required for the 'segmented capsule' style for(int i=0; i<nbComponents; i++) { Component comp = getComponent(i); if(!(comp instanceof JButton)) continue; boolean hasPrevious = i!=0 && (getComponent(i-1) instanceof JButton); boolean hasNext = i!=nbComponents-1 && (getComponent(i+1) instanceof JButton); String segmentPosition; if(hasPrevious && hasNext) segmentPosition = "middle"; else if(hasPrevious) segmentPosition = "last"; else if(hasNext) segmentPosition = "first"; else segmentPosition = "only"; ((JButton)comp).putClientProperty("JButton.segmentPosition", segmentPosition); } } } /** * Adds a button to this toolbar using the given action. */ private void addButton(MuAction action) { JButton button; if(action instanceof GoBackAction || action instanceof GoForwardAction) button = new HistoryPopupButton(action); else button = new NonFocusableButton(action); // Remove label button.setText(null); // Add tooltip using the action's label and accelerator String toolTipText = action.getLabel(); String acceleratorText = action.getAcceleratorText(); if(acceleratorText!=null) toolTipText += " ("+acceleratorText+")"; button.setToolTipText(toolTipText); // Sets the button icon, taking into account the icon scale factor setButtonIcon(button); if(USE_MAC_OS_X_CLIENT_PROPERTIES) { button.putClientProperty("JButton.buttonType", "segmentedTextured"); button.setRolloverEnabled(true); } // On other platforms, use a custom rollover effect else { // Init rollover RolloverButtonAdapter.setButtonDecoration(button); button.addMouseListener(rolloverButtonAdapter); } add(button); } /** * Sets the specified button's icon to the proper scale. * * @param button the button to update */ private void setButtonIcon(JButton button) { // Note: the action's icon must not be changed and remain in its original, non-scaled size ImageIcon icon = IconManager.getScaledIcon((ImageIcon)button.getAction().getValue(Action.SMALL_ICON), scaleFactor); if(!USE_MAC_OS_X_CLIENT_PROPERTIES) // Add padding around the icon so the button feels less crowded icon = IconManager.getPaddedIcon(icon, new Insets(3, 4, 3, 4)); button.setIcon(icon); } /////////////////////////////////// // ConfigurationListener methods // /////////////////////////////////// /** * Listens to certain configuration variables. */ public void configurationChanged(ConfigurationEvent event) { String var = event.getVariable(); // Rescale buttons icon if (var.equals(MuPreferences.TOOLBAR_ICON_SCALE)) { scaleFactor = event.getFloatValue(); Component components[] = getComponents(); int nbComponents = components.length; for(int i=0; i<nbComponents; i++) { if(components[i] instanceof JButton) { setButtonIcon((JButton)components[i]); } } } } /////////////////////////// // MouseListener methods // /////////////////////////// public void mouseClicked(MouseEvent e) { Object source = e.getSource(); // Right clicking on the toolbar brings up a popup menu if(source == this) { if (DesktopManager.isRightMouseButton(e)) { // if (e.isPopupTrigger()) { // Doesn't work under Mac OS X (CTRL+click doesn't return true) JPopupMenu popupMenu = new JPopupMenu(); popupMenu.add(ActionManager.getActionInstance(ToggleToolBarAction.Descriptor.ACTION_ID, mainFrame)); popupMenu.show(this, e.getX(), e.getY()); popupMenu.setVisible(true); } } } public void mouseEntered(MouseEvent e) { Object source = e.getSource(); if(source instanceof JButton) ((JButton)source).setBorderPainted(true); } public void mouseExited(MouseEvent e) { Object source = e.getSource(); if(source instanceof JButton) ((JButton)source).setBorderPainted(false); } public void mouseReleased(MouseEvent e) { } public void mousePressed(MouseEvent e) { } /////////////////////////////////////// // ToolBarAttributesListener methods // /////////////////////////////////////// public void toolBarActionsChanged() { removeAll(); addButtons(ToolBarAttributes.getActions()); } /** * PopupButton used for 'Go back' and 'Go forward' actions which displays the list of back/forward folders in the * popup menu and allows to recall them by clicking on them. */ private class HistoryPopupButton extends PopupButton { private MuAction action; private HistoryPopupButton(MuAction action) { super(action); this.action = action; } @Override public JPopupMenu getPopupMenu() { FileURL history[] = action instanceof GoBackAction? mainFrame.getActivePanel().getFolderHistory().getBackFolders() :mainFrame.getActivePanel().getFolderHistory().getForwardFolders(); int historyLen = history.length; // If no back/forward folder, do not display popup menu if(history.length==0) return null; JPopupMenu popupMenu = new JPopupMenu(); for(int i=0; i<historyLen; i++) popupMenu.add(new OpenLocationAction(mainFrame, new Hashtable<String, Object>(), history[i])); return popupMenu; } } }