/** * 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; 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.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import com.rapidminer.gui.look.Colors; import com.rapidminer.gui.look.RapidLookAndFeel; import com.rapidminer.gui.look.borders.TextFieldBorder; import com.rapidminer.gui.tools.ResourceAction.IconType; import com.rapidminer.tools.I18N; /** * This component combines a {@link JTextField} with a {@link ResourceAction}. The icon of the * action is shown on the right side of the textfield, and can be clicked to invoke the action. If * the text field is empty the action will not be painted and cannot be invoked. * * @author Marco Boeck, Nils Woehler * */ public class TextFieldWithAction extends JPanel { private static final long serialVersionUID = 1645009541373049543L; /** flag indicating if the user is hovering over the action icon */ private boolean hovered; private ImageIcon actionIcon = null; private ImageIcon hoverActionIcon = null; private JTextField field; /** * Creates a new {@link TextFieldWithAction} instance. * * @param field * the textfield into which the action icon should be placed * @param action * the action to invoke when clicking the icon in the textfield */ public TextFieldWithAction(final JTextField field, final ResourceAction action) { this(field, action, null); } /** * Creates a new {@link TextFieldWithAction} instance. * * @param field * the textfield into which the action icon should be placed * @param action * the action to invoke when clicking the icon in the textfield * @param hoverAction * the action to invoke when hovering the icon in the textfield */ public TextFieldWithAction(final JTextField field, final ResourceAction action, final ImageIcon hoverIcon) { if (field == null) { throw new IllegalArgumentException("field must not be null!"); } if (action == null) { throw new IllegalArgumentException("action must not be null!"); } this.field = field; setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL; add(field, gbc); actionIcon = SwingTools.createIcon("16/" + action.getIconName(), action.getIconType() == IconType.MONO); hoverActionIcon = hoverIcon; final JLabel actionLabel = new JLabel(actionIcon) { private static final long serialVersionUID = 1L; @Override public void paintComponent(Graphics g) { // override this so the action is only visible, when there is text in the text field if (!(field.getText().isEmpty() || field.getText() == null)) { Graphics2D g2 = (Graphics2D) g; // only in the case there is no hover action icon given if (hoverActionIcon == null && hovered) { int xStart = 0; int yStart = 0; int xEnd = getWidth(); int yEnd = getHeight(); // fill background g2.setPaint(Colors.TEXTFIELD_BACKGROUND); g2.fillRect(xStart, yStart, xEnd, yEnd); } super.paintComponent(g2); } } }; actionLabel.setToolTipText(I18N.getMessage(I18N.getGUIBundle(), "gui.action." + action.getKey() + ".tip")); actionLabel.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { if (!(field.getText().isEmpty() || field.getText() == null) && SwingUtilities.isLeftMouseButton(e)) { action.actionPerformed(new ActionEvent(actionLabel, ActionEvent.ACTION_PERFORMED, "click")); } } @Override public void mouseEntered(MouseEvent e) { hovered = true; if (hoverActionIcon != null) { actionLabel.setIcon(hoverActionIcon); } actionLabel.repaint(); } @Override public void mouseExited(MouseEvent e) { hovered = false; if (hoverActionIcon != null) { actionLabel.setIcon(actionIcon); } actionLabel.repaint(); } }); field.getDocument().addDocumentListener(new DocumentListener() { @Override public void removeUpdate(DocumentEvent e) { actionLabel.repaint(); } @Override public void insertUpdate(DocumentEvent e) { actionLabel.repaint(); } @Override public void changedUpdate(DocumentEvent e) { actionLabel.repaint(); } }); field.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { TextFieldWithAction.this.repaint(); } @Override public void focusGained(FocusEvent e) { TextFieldWithAction.this.repaint(); } }); gbc.insets = new Insets(0, 1, 0, 1); gbc.weightx = 0.0; gbc.fill = GridBagConstraints.NONE; add(actionLabel, gbc); // add textfield border to panel setBorder(new TextFieldBorder()); // hide textfield border field.setBorder(null); } @Override public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; // paint background and then field background to simulate round border textfield if (isOpaque()) { g2.setColor(getBackground()); g2.fillRect(0, 0, getWidth(), getHeight()); } g2.setColor(field.getBackground()); g2.fillRoundRect(0, 0, getWidth(), getHeight(), RapidLookAndFeel.CORNER_DEFAULT_RADIUS, RapidLookAndFeel.CORNER_DEFAULT_RADIUS); } @Override public boolean hasFocus() { return field.isFocusOwner(); } }