/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program 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 * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.tools.components; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.MouseListener; import java.awt.geom.GeneralPath; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JToolBar; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import com.rapidminer.gui.tools.ArrowButton; import com.rapidminer.gui.tools.ViewToolBar; import com.vlsolutions.swing.toolbars.VLToolBar; /** * * @author Tobias Malbrecht * @deprecated use {@link DropDownPopupButton} instead */ @Deprecated public abstract class DropDownButton extends JButton { private static final long serialVersionUID = -5987392204641149649L; private final PopupMenuListener popupMenuListener = new PopupMenuListener() { @Override public void popupMenuWillBecomeVisible(PopupMenuEvent e) { popupVisible = true; mainButton.getModel().setRollover(true); arrowButton.getModel().setSelected(true); } @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { popupVisible = false; mainButton.getModel().setRollover(false); arrowButton.getModel().setSelected(false); ((JPopupMenu) e.getSource()).removePopupMenuListener(this); } @Override public void popupMenuCanceled(PopupMenuEvent e) { popupVisible = false; } }; private final ChangeListener changeListener = new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (e.getSource() == mainButton.getModel()) { if (popupVisible && !mainButton.getModel().isRollover()) { mainButton.getModel().setRollover(true); return; } arrowButton.getModel().setRollover(mainButton.getModel().isRollover()); arrowButton.setSelected(mainButton.getModel().isArmed() && mainButton.getModel().isPressed()); } else { if (popupVisible && !arrowButton.getModel().isSelected()) { arrowButton.getModel().setSelected(true); return; } mainButton.getModel().setRollover(arrowButton.getModel().isRollover()); } } }; private final class DefaultArrowAction extends AbstractAction { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent ae) { JPopupMenu popup = getPopupMenu(); popup.addPopupMenuListener(popupMenuListener); popup.show(mainButton, isRightAlign() ? -popup.getPreferredSize().width + mainButton.getWidth() + arrowButton.getWidth() : 0, mainButton.getHeight()); } } protected JButton mainButton = this; private boolean rightAlign = false; @Deprecated public static class DropDownArrowButton extends ArrowButton { private static final long serialVersionUID = -398619111521186260L; private float sizeFactor = 1; private DropDownButton attachedButton; public DropDownArrowButton(DropDownButton attachedButton) { super(SwingConstants.SOUTH); this.attachedButton = attachedButton; } @Override public void paintComponent(Graphics g) { super.paintComponent(g); GeneralPath arrow = new GeneralPath(); int w, h; h = (int) (2 * sizeFactor); w = (int) (4 * sizeFactor); arrow.moveTo(getWidth() / 2 - w, getHeight() / 2); arrow.lineTo(getWidth() / 2 + w, getHeight() / 2); arrow.lineTo(getWidth() / 2, getHeight() / 2 + 2 * h); arrow.closePath(); if (isEnabled()) { g.setColor(Color.BLACK); } else { g.setColor(Color.GRAY); } ((Graphics2D) g).fill(arrow); } /** * * This method gets the factor for enlargement or reduction of the arrow, if it should be * displayed in a non-standard size. * */ public float getSizeFactor() { return sizeFactor; } /** * * This method determines the factor for enlargement or reduction of the arrow, if it should * be displayed in a non-standard size. Standard is a width of 4 px and a height of 8 px. * * @param sizeFactor */ public void setSizeFactor(float sizeFactor) { this.sizeFactor = sizeFactor; } @Override public Dimension getPreferredSize() { Dimension dim = new Dimension((int) super.getPreferredSize().getWidth(), (int) attachedButton.getPreferredSize().getHeight()); return dim; } @Override public Dimension getSize() { Dimension dim = new Dimension((int) super.getSize().getWidth(), (int) attachedButton.getSize().getHeight()); return dim; } @Override public Dimension getMaximumSize() { Dimension dim = new Dimension((int) super.getMaximumSize().getWidth(), (int) attachedButton.getMaximumSize().getHeight()); return dim; } @Override public Dimension getMinimumSize() { Dimension dim = new Dimension((int) super.getMinimumSize().getWidth(), (int) attachedButton.getMinimumSize().getHeight()); return dim; } } protected final DropDownArrowButton arrowButton = new DropDownArrowButton(this); protected boolean popupVisible = false; public DropDownButton(Action mainAction, Action arrowAction, boolean showButton) { super(mainAction != null ? mainAction : arrowAction); // if main action is null, use // dropdown action for it as well so // user is not confused mainButton.setText(null); mainButton.setOpaque(showButton); mainButton.setBorderPainted(showButton); mainButton.setMargin(new Insets(0, 0, 0, 0)); mainButton.getModel().addChangeListener(changeListener); arrowButton.getModel().addChangeListener(changeListener); arrowButton.setFocusable(false); if (arrowAction != null) { arrowButton.addActionListener(arrowAction); } else { arrowButton.addActionListener(new DefaultArrowAction()); } arrowButton.setMargin(new Insets(0, 0, 0, 0)); mainButton.addPropertyChangeListener("enabled", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { arrowButton.setEnabled(mainButton.isEnabled()); } }); } public DropDownButton(Action action, boolean showText) { this(action, null, showText); } /** * Shows no text on buttons. */ public DropDownButton(Action action) { this(action, false); } public void addArrowButtonMouseListener(MouseListener l) { arrowButton.addMouseListener(l); } public void removeArrowButtonMouseListener(MouseListener l) { arrowButton.removeMouseListener(l); } protected abstract JPopupMenu getPopupMenu(); public void add(Action action) { getPopupMenu().add(action); } public void add(JMenuItem item) { getPopupMenu().add(item); } public JButton addToToolBar(JToolBar toolbar) { toolbar.add(mainButton); toolbar.add(arrowButton); return mainButton; } public JButton addToToolBar(JToolBar toolbar, Object mainButtonConstraints, Object arrowButtonConstraints) { toolbar.add(mainButton, mainButtonConstraints); toolbar.add(arrowButton, arrowButtonConstraints); return mainButton; } public JButton addToToolbar(JPanel toolbar, Object mainButtonConstraints, Object arrowButtonConstraints) { toolbar.add(mainButton, mainButtonConstraints); toolbar.add(arrowButton, arrowButtonConstraints); return mainButton; } public JButton addToToolBar(VLToolBar toolbar) { toolbar.add(mainButton); toolbar.add(arrowButton); return mainButton; } public JButton addToToolBar(ViewToolBar toolbar, int alignment) { toolbar.add(mainButton, alignment); toolbar.add(arrowButton, alignment); return mainButton; } public JButton addToToolbar(JToolBar toolbar, Object mainButtonConstraints, Object arrowButtonConstraints) { toolbar.add(mainButton, mainButtonConstraints); toolbar.add(arrowButton, arrowButtonConstraints); return mainButton; } public JButton addToFlowLayoutPanel(JPanel panel) { panel.add(mainButton); panel.add(arrowButton); return mainButton; } public JButton addArrowToFlowLayoutPanel(JPanel panel) { panel.add(mainButton); panel.add(arrowButton); return mainButton; } public JPanel getArrowButtonBorderPanel() { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(0, 0, GridBagConstraints.RELATIVE, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0); panel.add(mainButton, gbc); // , BorderLayout.CENTER); gbc.gridx = 1; gbc.gridy = 0; gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 0; panel.add(arrowButton, gbc); // , BorderLayout.EAST); mainButton.setBorder(null); arrowButton.setBorder(null); panel.setBackground(UIManager.getColor("Button.background")); return panel; } // factory methods public static DropDownButton makeDropDownButton(Action mainAction, Action... actions) { return makeDropDownButton(mainAction, false, actions); } public static DropDownButton makeDropDownButton(Action mainAction, boolean showButton, Action... actions) { final JPopupMenu menu = new JPopupMenu(); for (Action action : actions) { menu.add(action); } return new DropDownButton(mainAction, showButton) { private static final long serialVersionUID = -7359018188605409766L; @Override protected JPopupMenu getPopupMenu() { return menu; } }; } public boolean isArrowButtonVisible() { return arrowButton.isVisible(); } public void setArrowSizeFactor(float factor) { arrowButton.setSizeFactor(factor); } /** * After this is called, ckicks on the main button act like clicking on the arrow button. <br/> * This is useful if the main action is only used to set icon/tooltip, but not a real action. */ public void setUsePopupActionOnMainButton() { mainButton.addActionListener(new DefaultArrowAction()); } public float getArrowSizeFactor() { return arrowButton.getSizeFactor(); } public boolean isPopupMenuVisible() { return popupVisible; } public static DropDownButton makeDropDownButton(Action action) { final JPopupMenu menu = new JPopupMenu(); return new DropDownButton(action) { private static final long serialVersionUID = -7359018188605409766L; @Override protected JPopupMenu getPopupMenu() { return menu; } }; } @Override public void setEnabled(boolean b) { super.setEnabled(b); if (arrowButton != null) { arrowButton.setEnabled(b); } } public boolean isRightAlign() { return rightAlign; } public void setRightAlign(boolean rightAlign) { this.rightAlign = rightAlign; } }