/**
* 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;
}
}