/* *------------------------------------------------------------------------------ * Copyright (C) 2015 University of Dundee. All rights reserved. * * * This program 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 2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.agents.metadata.editor; import java.awt.Color; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JToggleButton; import javax.swing.SwingUtilities; import javax.swing.border.Border; import org.openmicroscopy.shoola.agents.metadata.IconManager; import org.openmicroscopy.shoola.util.ui.UIUtilities; import com.google.common.base.CharMatcher; /** * A Component for editing texts * * @author Dominik Lindner      <a * href="mailto:d.lindner@dundee.ac.uk">d.lindner@dundee.ac.uk</a> */ public class EditableTextComponent extends JPanel { /** The default number of characters to show in non-edit mode */ public static final int DEFAULT_NUMBER_OF_CHARACTERS = 30; /** Property name for an edit event */ public static final String EDIT_PROPERTY = "EDIT_PROPERTY"; /** The border in edit mode */ private static final Border EDIT_BORDER_BLACK = BorderFactory .createLineBorder(Color.BLACK); /** Button to edit the text. */ private JToggleButton editButton; /** The text component */ private JTextArea textPane; /** The default border in non-edit mode */ private Border defaultBorder; /** The original text */ private String originalText; /** The current text */ private String text; /** Number of characters to show in non-edit mode */ private int showCharacters; /** Flag to indicate to allow empty text */ private boolean permitEmpty; /** Reference to the button listener */ private ItemListener buttonListener; /** Tooltip text for the edit button */ private String tooltip; /** * Creates a new instance * * @param modifiable * Flag to make the component editable * @param permitEmpty * Flag to allow empty text * @param tooltip * Tooltip text for the edit button (can be <code>null</code>) */ public EditableTextComponent(boolean modifiable, boolean permitEmpty, String tooltip) { this("", DEFAULT_NUMBER_OF_CHARACTERS, modifiable, permitEmpty, tooltip); } /** * Creates a new instance * * @param text * The text to show * @param showCharacters * The number of characters to show in non-edit mode * @param modifiable * Flag to make the component editable * @param permitEmpty * Flag to allow empty text * @param tooltip * Tooltip text for the edit button (can be <code>null</code>) */ public EditableTextComponent(String text, int showCharacters, boolean modifiable, boolean permitEmpty, String tooltip) { this.showCharacters = showCharacters; this.permitEmpty = permitEmpty; this.tooltip = tooltip; initComponent(); buildUI(text, modifiable); } /** * Initializes the components */ private void initComponent() { textPane = new JTextArea(); textPane.setOpaque(false); textPane.setBackground(UIUtilities.BACKGROUND_COLOR); textPane.setEditable(false); Font f = textPane.getFont(); textPane.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent arg0) { } @Override public void keyReleased(KeyEvent arg0) { if (arg0.getKeyCode() == KeyEvent.VK_ENTER) { save(); } } @Override public void keyPressed(KeyEvent arg0) { } }); defaultBorder = textPane.getBorder(); textPane.setFont(f.deriveFont(Font.BOLD)); IconManager icons = IconManager.getInstance(); editButton = new JToggleButton(icons.getIcon(IconManager.EDIT_12)); editButton.setOpaque(false); UIUtilities.unifiedButtonLookAndFeel(editButton); editButton.setBackground(UIUtilities.BACKGROUND_COLOR); if (tooltip != null) editButton.setToolTipText(tooltip); buttonListener = new ItemListener() { public void itemStateChanged(ItemEvent e) { JToggleButton b = (JToggleButton) e.getSource(); if (b.isSelected()) { editField(true); } else { save(); editField(false); } } }; editButton.addItemListener(buttonListener); } /** * Build/Refreshes the UI * * @param text * The text to show * @param modifiable * Flag to make the component editable */ protected void buildUI(String text, boolean modifiable) { this.originalText = text; this.text = text; removeAll(); editButton.setEnabled(modifiable); textPane.setEditable(modifiable); textPane.setText(UIUtilities.formatPartialName(text, showCharacters)); textPane.setToolTipText(text); // disable line wrap and only enable it in editing mode; // otherwise keeping it enabled has a weird effect on the layout textPane.setLineWrap(false); setBackground(UIUtilities.BACKGROUND_COLOR); setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(2, 2, 2, 2); c.gridy = 0; c.gridx = 0; c.weightx = 1; add(textPane, c); c.gridx++; c.fill = GridBagConstraints.NONE; c.weightx = 0; c.anchor = GridBagConstraints.EAST; add(editButton, c); } /** * Toggle between edit and non-edit mode * * @param edit * Pass <code>true</code> to switch to edit mode, * <code>false</code> otherwise */ private void editField(boolean edit) { if (edit) { textPane.setEditable(true); textPane.setLineWrap(true); textPane.setText(text); textPane.setBorder(EDIT_BORDER_BLACK); textPane.setMaximumSize(textPane.getSize()); textPane.requestFocus(); textPane.select(0, 0); textPane.setCaretPosition(0); } else { textPane.setEditable(false); textPane.setLineWrap(false); textPane.setText(UIUtilities .formatPartialName(text, showCharacters)); textPane.setBorder(defaultBorder); textPane.setMaximumSize(textPane.getSize()); editButton.removeItemListener(buttonListener); editButton.setSelected(false); editButton.addItemListener(buttonListener); } } /** * Fires the {@link #EDIT_PROPERTY} property and returns to non-edit mode */ private void save() { this.text = CharMatcher.JAVA_ISO_CONTROL.removeFrom(textPane.getText()); if (this.text.trim().isEmpty() && !permitEmpty) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { EditableTextComponent.this.text = originalText; editField(false); } }); return; } firePropertyChange(EDIT_PROPERTY, originalText, text); originalText = text; SwingUtilities.invokeLater(new Runnable() { @Override public void run() { editField(false); } }); } /** * Sets the text * * @param text * The text show */ void setText(String text) { this.text = text; this.originalText = text; textPane.setText(UIUtilities.formatPartialName(text, showCharacters)); } }