/*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2014 University of Dundee & Open Microscopy Environment.
* 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.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.openmicroscopy.shoola.agents.util.EditorUtil;
import org.openmicroscopy.shoola.util.ui.MultilineLabel;
import org.openmicroscopy.shoola.util.ui.TextFieldLimit;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
import omero.gateway.model.ChannelData;
import omero.gateway.model.DatasetData;
import omero.gateway.model.PlateData;
/**
* Edits the channels.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @since 4.4
*/
class ChannelEditUI
extends JPanel
implements ActionListener, DocumentListener
{
/** Bound property indicating to apply the renaming to all the images.*/
static final String APPLY_TO_ALL_PROPERTY = "ApplyToAll";
/** Bound property indicating to cancel the renaming.*/
static final String CANCEL_PROPERTY = "Cancel";
/** Bound property indicating to save the renaming for the image.*/
static final String SAVE_PROPERTY = "Save";
/**
* Message displayed before apply the renaming to all images in the dataset.
*/
private static final String WARNING_DATASET =
"Update channel names for all images in the dataset? " +
"This cannot be undone.";
/**
* Message displayed before apply the renaming to all images in the plate.
*/
private static final String WARNING_PLATE =
"Update channel names for all images in the plate? " +
"This cannot be undone.";
/** Action id indicating to save the changes if any.*/
private static final int SAVE = 0;
/** Action id indicating to cancel the saving.*/
private static final int CANCEL = 1;
/** Action id indicating to apply the changes to all.*/
private static final int APPLY_TO_ALL = 2;
/** The text of the {@link #applyToAll}.*/
private static final String APPLY_TO_ALL_TEXT = "Apply to All";
/** The text of the {@link #save}.*/
private static final String SAVE_TEXT = "Save";
/** The text of the {@link #save}.*/
private static final String CONTINUE_TEXT = "Continue";
/** The text of the {@link #cancelButton}.*/
private static final String CANCEL_TEXT = "Cancel";
/** The tool tip text of the {@link #applyToAll}.*/
private static final String APPLY_TO_ALL_TIP =
"Save and apply to all images.";
/** The tool tip text of the {@link #save}.*/
private static final String SAVE_TIP = "Save Channel Names.";
/** The tool tip text of the {@link #cancelButton}.*/
private static final String CANCEL_TIP = "Cancel.";
/** Map hosting the fields used to edit the corresponding channel.*/
private Map<JTextField, ChannelData> fields;
/** Save the changes if any.*/
private JButton saveButton;
/** Cancel the saving.*/
private JButton cancelButton;
/** Apply the changes to all the images.*/
private JButton applyToAll;
/** The data object hosting all the images to update.*/
private Object parent;
/** Component used to display a warning before saving.*/
private JTextArea messageLabel;
/** The channels to display.*/
private Map channels;
/** Initializes the components composing the display.*/
private void initComponents()
{
fields = new LinkedHashMap<JTextField, ChannelData>(channels.size());
ChannelData channel;
JTextField field;
Iterator k = channels.keySet().iterator();
while (k.hasNext()) {
channel = (ChannelData) k.next();
field = new TextFieldLimit(EditorUtil.MAX_CHAR-1);
field.setBackground(UIUtilities.BACKGROUND_COLOR);
field.setText(channel.getChannelLabeling());
field.getDocument().addDocumentListener(this);
fields.put(field, channel);
}
saveButton = new JButton(SAVE_TEXT);
saveButton.setToolTipText(SAVE_TIP);
saveButton.addActionListener(this);
saveButton.setActionCommand(""+SAVE);
saveButton.setEnabled(false);
cancelButton = new JButton(CANCEL_TEXT);
cancelButton.setToolTipText(CANCEL_TIP);
cancelButton.addActionListener(this);
cancelButton.setActionCommand(""+CANCEL);
applyToAll = new JButton(APPLY_TO_ALL_TEXT);
applyToAll.setToolTipText(APPLY_TO_ALL_TIP);
applyToAll.addActionListener(this);
applyToAll.setActionCommand(""+APPLY_TO_ALL);
Border border = new CompoundBorder(
BorderFactory.createLineBorder(Color.gray),
new EmptyBorder(2, 2, 2, 2));
saveButton.setOpaque(true);
saveButton.setBackground(UIUtilities.LIGHT_GREY);
saveButton.setBorder(border);
cancelButton.setOpaque(true);
cancelButton.setBackground(UIUtilities.LIGHT_GREY);
cancelButton.setBorder(border);
applyToAll.setOpaque(true);
applyToAll.setBackground(UIUtilities.LIGHT_GREY);
applyToAll.setBorder(border);
messageLabel = new MultilineLabel();
messageLabel.setBackground(UIUtilities.BACKGROUND_COLOR);
saveButton.setVisible(!(parent instanceof PlateData));
}
/** Builds and lays out the UI.*/
private void buildGUI()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBackground(UIUtilities.BACKGROUND_COLOR);
Iterator<Entry<JTextField, ChannelData>>
i = fields.entrySet().iterator();
while (i.hasNext()) {
add(i.next().getKey());
}
add(messageLabel);
add(buildControls());
}
/**
* Builds and lays out the controls.
*
* @return See above.
*/
private JPanel buildControls()
{
JPanel bar = new JPanel();
bar.setLayout(new FlowLayout(FlowLayout.LEFT));
bar.setBackground(UIUtilities.BACKGROUND_COLOR);
bar.add(saveButton);
if (parent instanceof DatasetData || parent instanceof PlateData)
bar.add(applyToAll);
bar.add(cancelButton);
return bar;
}
/** Saves the changes.*/
private void save()
{
Entry<JTextField, ChannelData> e;
Iterator<Entry<JTextField, ChannelData>>
i = fields.entrySet().iterator();
List<ChannelData> channels = new ArrayList<ChannelData>(fields.size());
ChannelData channel;
while (i.hasNext()) {
e = i.next();
channel = e.getValue();
channel.setName(e.getKey().getText());
channels.add(channel);
}
//Apply the
if (!applyToAll.isVisible())
firePropertyChange(APPLY_TO_ALL_PROPERTY, null, channels);
else firePropertyChange(SAVE_PROPERTY, null, channels);
resetControls();
}
/** Resets the controls.*/
private void resetControls()
{
saveButton.setEnabled(false);
saveButton.setVisible(!(parent instanceof PlateData));
saveButton.setText(SAVE_TEXT);
messageLabel.setText("");
applyToAll.setVisible(true);
}
/**
* Displays a warning before saving the changes depending on the
* {@link #parent} object.
*/
private void applyToAll()
{
if (parent instanceof DatasetData)
messageLabel.setText(WARNING_DATASET);
else if (parent instanceof PlateData)
messageLabel.setText(WARNING_PLATE);
applyToAll.setVisible(false);
saveButton.setEnabled(true);
saveButton.setVisible(true);
saveButton.setText(CONTINUE_TEXT);
repaint();
}
/** Cancel the saving.*/
private void cancel()
{
resetControls();
//Reset the fields' values.
Entry<JTextField, ChannelData> e;
Iterator<Entry<JTextField, ChannelData>>
i = fields.entrySet().iterator();
while (i.hasNext()) {
e = i.next();
e.getKey().setText(e.getValue().getChannelLabeling());
}
firePropertyChange(CANCEL_PROPERTY, Boolean.valueOf(false),
Boolean.valueOf(true));
}
/**
* Enables or not the {@link #saveButton} depending on the value entered.
*/
private void handleNameChange()
{
Entry<JTextField, ChannelData> e;
Iterator<Entry<JTextField, ChannelData>>
i = fields.entrySet().iterator();
boolean enabled = false;
while (i.hasNext()) {
e = i.next();
if (!e.getKey().getText().equals(
e.getValue().getChannelLabeling())) {
enabled = true;
break;
}
}
saveButton.setEnabled(enabled);
}
/**
* Creates a new instance.
*
* @param channels The channels to handle.
* @param parent The data object hosting all the images to update.
*/
ChannelEditUI(Map channels, Object parent)
{
if (channels == null || channels.size() == 0)
throw new IllegalArgumentException("No Channels specified.");
this.parent = parent;
this.channels = channels;
initComponents();
buildGUI();
}
/**
* Handles event fired by the controls.
* @see ActionListener#actionPerformed(ActionEvent)
*/
public void actionPerformed(ActionEvent evt)
{
int index = Integer.parseInt(evt.getActionCommand());
switch (index) {
case SAVE:
save();
break;
case CANCEL:
cancel();
break;
case APPLY_TO_ALL:
applyToAll();
}
}
/**
* Enables or not the {@link #saveButton} depending on the value entered.
*
* @see DocumentListener#insertUpdate(DocumentEvent)
*/
public void insertUpdate(DocumentEvent evt) { handleNameChange(); }
/**
* Enables or not the {@link #saveButton} depending on the value entered.
*
* @see DocumentListener#removeUpdate(DocumentEvent)
*/
public void removeUpdate(DocumentEvent evt) { handleNameChange(); }
/**
* Implemented as specified by {@link DocumentListener} I/F but
* no operation in our case.
*/
public void changedUpdate(DocumentEvent evt) {}
}