/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy 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 3 of the License, or
* (at your option) any later version.
*
* Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.gui.menu;
import icy.action.SequenceOperationActions;
import icy.action.SequenceOperationActions.ExtractChannelAction;
import icy.action.SequenceOperationActions.RemoveChannelAction;
import icy.gui.component.IcyTextField;
import icy.gui.component.button.IcyButton;
import icy.gui.component.button.IcyCommandButton;
import icy.gui.component.button.IcyCommandMenuButton;
import icy.gui.component.button.IcyCommandToggleMenuButton;
import icy.gui.util.ComponentUtil;
import icy.gui.util.RibbonUtil;
import icy.main.Icy;
import icy.resource.ResourceUtil;
import icy.resource.icon.IcyIcon;
import icy.sequence.Sequence;
import icy.system.thread.ThreadUtil;
import icy.type.DataType;
import icy.util.StringUtil;
import org.pushingpixels.flamingo.api.common.CommandToggleButtonGroup;
import org.pushingpixels.flamingo.api.common.JCommandButton;
import org.pushingpixels.flamingo.api.common.JCommandButton.CommandButtonKind;
import org.pushingpixels.flamingo.api.common.RichTooltip;
import org.pushingpixels.flamingo.api.common.popup.JCommandPopupMenu;
import org.pushingpixels.flamingo.api.common.popup.JPopupPanel;
import org.pushingpixels.flamingo.api.common.popup.PopupPanelCallback;
import org.pushingpixels.flamingo.api.ribbon.JRibbonBand;
import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent;
import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority;
import org.pushingpixels.flamingo.api.ribbon.RibbonTask;
/**
* @author Stephane
*/
public class SequenceOperationTask extends RibbonTask
{
public static class CopyConvertBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = -2677243480668715388L;
public static final String NAME = "Copy / Convert";
final IcyCommandButton cloneButton;
final IcyCommandButton convertButton;
final IcyCommandButton convertButtonRaw;
public CopyConvertBand()
{
super(NAME, new IcyIcon(ResourceUtil.ICON_TOOLS));
setToolTipText("Copy and data type conversion operation");
// clone sequence
cloneButton = new IcyCommandButton(SequenceOperationActions.cloneSequenceAction);
addCommandButton(cloneButton, RibbonElementPriority.MEDIUM);
// data type conversion
convertButton = new IcyCommandButton("Conversion", new IcyIcon(ResourceUtil.ICON_BAND_RIGHT));
convertButton.setCommandButtonKind(CommandButtonKind.POPUP_ONLY);
convertButton.setPopupRichTooltip(new RichTooltip("Data type conversion",
"Convert the sequence to the selected data type (values are scaled to fit the new type)"));
convertButton.setPopupCallback(new PopupPanelCallback()
{
@Override
public JPopupPanel getPopupPanel(JCommandButton commandButton)
{
final JCommandPopupMenu result = new JCommandPopupMenu();
final Sequence sequence = Icy.getMainInterface().getActiveSequence();
if (sequence != null)
{
final CommandToggleButtonGroup group = new CommandToggleButtonGroup();
result.addMenuButton(getConvertButton(sequence, DataType.UBYTE, true, group));
result.addMenuButton(getConvertButton(sequence, DataType.BYTE, true, group));
result.addMenuButton(getConvertButton(sequence, DataType.USHORT, true, group));
result.addMenuButton(getConvertButton(sequence, DataType.SHORT, true, group));
result.addMenuButton(getConvertButton(sequence, DataType.UINT, true, group));
result.addMenuButton(getConvertButton(sequence, DataType.INT, true, group));
result.addMenuButton(getConvertButton(sequence, DataType.FLOAT, true, group));
result.addMenuButton(getConvertButton(sequence, DataType.DOUBLE, true, group));
}
return result;
}
});
addCommandButton(convertButton, RibbonElementPriority.MEDIUM);
// data type conversion
convertButtonRaw = new IcyCommandButton("Raw conversion", new IcyIcon(ResourceUtil.ICON_BAND_RIGHT));
convertButtonRaw.setCommandButtonKind(CommandButtonKind.POPUP_ONLY);
convertButtonRaw
.setPopupRichTooltip(new RichTooltip("Raw data type conversion",
"Convert the sequence to the selected data type (values remain unchanged or are clamped in case of overflow)"));
convertButtonRaw.setPopupCallback(new PopupPanelCallback()
{
@Override
public JPopupPanel getPopupPanel(JCommandButton commandButton)
{
final JCommandPopupMenu result = new JCommandPopupMenu();
final Sequence sequence = Icy.getMainInterface().getActiveSequence();
if (sequence != null)
{
final CommandToggleButtonGroup group = new CommandToggleButtonGroup();
result.addMenuButton(getConvertButton(sequence, DataType.UBYTE, false, group));
result.addMenuButton(getConvertButton(sequence, DataType.BYTE, false, group));
result.addMenuButton(getConvertButton(sequence, DataType.USHORT, false, group));
result.addMenuButton(getConvertButton(sequence, DataType.SHORT, false, group));
result.addMenuButton(getConvertButton(sequence, DataType.UINT, false, group));
result.addMenuButton(getConvertButton(sequence, DataType.INT, false, group));
result.addMenuButton(getConvertButton(sequence, DataType.FLOAT, false, group));
result.addMenuButton(getConvertButton(sequence, DataType.DOUBLE, false, group));
}
return result;
}
});
addCommandButton(convertButtonRaw, RibbonElementPriority.MEDIUM);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
public IcyCommandToggleMenuButton getConvertButton(final Sequence sequence, final DataType dataType,
final boolean scaled, CommandToggleButtonGroup group)
{
final IcyCommandToggleMenuButton result = new IcyCommandToggleMenuButton(
SequenceOperationActions.getConvertSequenceAction(dataType, scaled));
group.add(result);
// sequence has same datatype ?
if (sequence.getDataType_() == dataType)
{
// select and disable it
group.setSelected(result, true);
result.setEnabled(false);
}
else
group.setSelected(result, false);
return result;
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = seq != null;
final boolean notEmpty = enabled && !seq.isEmpty();
cloneButton.setEnabled(enabled);
convertButton.setEnabled(notEmpty);
convertButtonRaw.setEnabled(notEmpty);
}
}
public static class RenderingBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = -2677243480668715388L;
public static final String NAME = "Rendering";
final IcyCommandButton argbButton;
final IcyCommandButton rgbButton;
final IcyCommandButton grayButton;
public RenderingBand()
{
super(NAME, new IcyIcon(ResourceUtil.ICON_TOOLS));
setToolTipText("Color and gray rendering");
// ARGB rendering
argbButton = new IcyCommandButton(SequenceOperationActions.argbSequenceAction);
addCommandButton(argbButton, RibbonElementPriority.MEDIUM);
// RGB rendering
rgbButton = new IcyCommandButton(SequenceOperationActions.rgbSequenceAction);
addCommandButton(rgbButton, RibbonElementPriority.MEDIUM);
// Gray rendering
grayButton = new IcyCommandButton(SequenceOperationActions.graySequenceAction);
addCommandButton(grayButton, RibbonElementPriority.MEDIUM);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = (seq != null) && !seq.isEmpty();
argbButton.setEnabled(enabled);
rgbButton.setEnabled(enabled);
grayButton.setEnabled(enabled);
}
}
public static class PlanarOperationBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = -7475753600896040618L;
private static final String NAME = "Plane (XY)";
final IcyCommandButton cropButton;
final IcyCommandButton canvasResizeButton;
final IcyCommandButton imageResizeButton;
// final IcyCommandButton mergeButton;
public PlanarOperationBand()
{
super(NAME, new IcyIcon(ResourceUtil.ICON_PICTURE));
setToolTipText("XY (plane) operation");
// fast crop operation
cropButton = new IcyCommandButton(SequenceOperationActions.cropSequenceAction);
addCommandButton(cropButton, RibbonElementPriority.MEDIUM);
// canvas resize operation
canvasResizeButton = new IcyCommandButton(SequenceOperationActions.canvasResizeAction);
addCommandButton(canvasResizeButton, RibbonElementPriority.MEDIUM);
// image resize operation
imageResizeButton = new IcyCommandButton(SequenceOperationActions.imageResizeAction);
addCommandButton(imageResizeButton, RibbonElementPriority.MEDIUM);
// merge operation
// mergeButton = new IcyCommandButton("Merge...");
// mergeButton.setActionRichTooltip(new RichTooltip("Resize image",
// "Resize an image using different policies."));
// mergeButton.addActionListener(new ActionListener()
// {
// @Override
// public void actionPerformed(ActionEvent e)
// {
// }
// });
// not yet implemented
// addCommandButton(mergeButton, RibbonElementPriority.MEDIUM);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = (seq != null) && !seq.isEmpty();
cropButton.setEnabled(enabled);
canvasResizeButton.setEnabled(enabled);
imageResizeButton.setEnabled(enabled);
// mergeButton.setEnabled(enabled);
}
}
public static class ChannelOperationBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = -2677243480668715388L;
public static final String NAME = "Channel (C)";
final IcyCommandButton extractButton;
final IcyCommandButton removeButton;
final IcyCommandButton mergeButton;
public ChannelOperationBand()
{
super(NAME, new IcyIcon(ResourceUtil.ICON_TOOLS));
setToolTipText("Channel operation");
// single channel extraction
extractButton = new IcyCommandButton("Extract", new IcyIcon(ResourceUtil.ICON_INDENT_DECREASE));
extractButton.setCommandButtonKind(CommandButtonKind.POPUP_ONLY);
extractButton.setPopupRichTooltip(new RichTooltip("Single channel extraction",
"Create a new single channel sequence from selected channel of active sequence."));
extractButton.setPopupCallback(new PopupPanelCallback()
{
@Override
public JPopupPanel getPopupPanel(JCommandButton commandButton)
{
final JCommandPopupMenu result = new JCommandPopupMenu();
final Sequence sequence = Icy.getMainInterface().getActiveSequence();
if (sequence != null)
{
for (int c = 0; c < sequence.getSizeC(); c++)
{
final IcyCommandMenuButton button;
if (c < SequenceOperationActions.extractChannelActions.length)
button = new IcyCommandMenuButton(SequenceOperationActions.extractChannelActions[c]);
else
button = new IcyCommandMenuButton(new ExtractChannelAction(c));
result.addMenuButton(button);
}
result.addMenuButton(new IcyCommandMenuButton(SequenceOperationActions.extractAllChannelAction));
}
return result;
}
});
addCommandButton(extractButton, RibbonElementPriority.MEDIUM);
// single channel remove
removeButton = new IcyCommandButton("Remove", new IcyIcon(ResourceUtil.ICON_INDENT_REMOVE));
removeButton.setCommandButtonKind(CommandButtonKind.POPUP_ONLY);
removeButton.setPopupRichTooltip(new RichTooltip("Remove channel",
"Remove the selected channel from active sequence."));
removeButton.setPopupCallback(new PopupPanelCallback()
{
@Override
public JPopupPanel getPopupPanel(JCommandButton commandButton)
{
final JCommandPopupMenu result = new JCommandPopupMenu();
final Sequence sequence = Icy.getMainInterface().getActiveSequence();
if (sequence != null)
{
for (int c = 0; c < sequence.getSizeC(); c++)
{
final IcyCommandMenuButton button;
if (c < SequenceOperationActions.removeChannelActions.length)
button = new IcyCommandMenuButton(SequenceOperationActions.removeChannelActions[c]);
else
button = new IcyCommandMenuButton(new RemoveChannelAction(c));
result.addMenuButton(button);
}
}
return result;
}
});
addCommandButton(removeButton, RibbonElementPriority.MEDIUM);
// channel merge operation
mergeButton = new IcyCommandButton(SequenceOperationActions.mergeChannelsAction);
addCommandButton(mergeButton, RibbonElementPriority.MEDIUM);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = (seq != null);
final boolean several = enabled && (seq.getSizeC() > 1);
extractButton.setEnabled(several);
removeButton.setEnabled(several);
mergeButton.setEnabled(enabled);
}
}
public static class ZOperationBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = 8301134961618666184L;
public static final String NAME = "Stack (Z)";
final IcyCommandButton reverseButton;
final IcyCommandButton extractButton;
final IcyCommandButton removeButton;
final IcyCommandButton advancedRemoveButton;
final IcyCommandButton addButton;
final IcyCommandButton mergeButton;
public ZOperationBand()
{
super(NAME, new IcyIcon(ResourceUtil.ICON_LAYER_V1));
setToolTipText("Z (stack) operation");
// reverse slices
reverseButton = new IcyCommandButton(SequenceOperationActions.reverseSlicesAction);
addCommandButton(reverseButton, RibbonElementPriority.MEDIUM);
// slice extraction
extractButton = new IcyCommandButton(SequenceOperationActions.extractSliceAction);
addCommandButton(extractButton, RibbonElementPriority.MEDIUM);
// slice remove
removeButton = new IcyCommandButton(SequenceOperationActions.removeSliceAction);
addCommandButton(removeButton, RibbonElementPriority.MEDIUM);
// ADVANCED
startGroup();
// add slices
addButton = new IcyCommandButton(SequenceOperationActions.addSlicesAction);
addCommandButton(addButton, RibbonElementPriority.MEDIUM); // advanced Z slice remove
// slices merge
mergeButton = new IcyCommandButton(SequenceOperationActions.mergeSlicesAction);
addCommandButton(mergeButton, RibbonElementPriority.MEDIUM);
// advanced slice remove
advancedRemoveButton = new IcyCommandButton(SequenceOperationActions.removeSlicesAction);
addCommandButton(advancedRemoveButton, RibbonElementPriority.MEDIUM);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = (seq != null);
final boolean notEmpty = enabled && !seq.isEmpty();
final boolean several = enabled && (seq.getSizeZ() > 1);
reverseButton.setEnabled(several);
extractButton.setEnabled(several);
removeButton.setEnabled(several);
addButton.setEnabled(notEmpty);
mergeButton.setEnabled(enabled);
advancedRemoveButton.setEnabled(several);
}
}
public static class TOperationBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = 3728386745443331069L;
public static final String NAME = "Frame (T)";
final IcyCommandButton reverseButton;
final IcyCommandButton extractButton;
final IcyCommandButton removeButton;
final IcyCommandButton advancedRemoveButton;
final IcyCommandButton addButton;
final IcyCommandButton mergeButton;
public TOperationBand()
{
super(NAME, new IcyIcon(ResourceUtil.ICON_LAYER_H1));
setToolTipText("T (frame) operation");
// reverse frames
reverseButton = new IcyCommandButton(SequenceOperationActions.reverseFramesAction);
addCommandButton(reverseButton, RibbonElementPriority.MEDIUM);
// frame extraction
extractButton = new IcyCommandButton(SequenceOperationActions.extractFrameAction);
addCommandButton(extractButton, RibbonElementPriority.MEDIUM);
// frame remove
removeButton = new IcyCommandButton(SequenceOperationActions.removeFrameAction);
addCommandButton(removeButton, RibbonElementPriority.MEDIUM);
// ADVANCED
startGroup();
// add frames
addButton = new IcyCommandButton(SequenceOperationActions.addFramesAction);
addCommandButton(addButton, RibbonElementPriority.MEDIUM);
// frames merge
mergeButton = new IcyCommandButton(SequenceOperationActions.mergeFramesAction);
addCommandButton(mergeButton, RibbonElementPriority.MEDIUM);
// advanced frame remove
advancedRemoveButton = new IcyCommandButton(SequenceOperationActions.removeFramesAction);
addCommandButton(advancedRemoveButton, RibbonElementPriority.MEDIUM);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = (seq != null);
final boolean notEmpty = enabled && !seq.isEmpty();
final boolean several = enabled && (seq.getSizeT() > 1);
reverseButton.setEnabled(several);
extractButton.setEnabled(several);
removeButton.setEnabled(several);
addButton.setEnabled(notEmpty);
mergeButton.setEnabled(enabled);
advancedRemoveButton.setEnabled(several);
}
}
public static class ZTConversionBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = 8210688977085548878L;
private static final String NAME = "Z / T conversion";
final IcyCommandButton convertToZButton;
final IcyCommandButton convertToTButton;
final IcyCommandButton advancedConvertButton;
public ZTConversionBand()
{
super(NAME, new IcyIcon(ResourceUtil.ICON_LAYER_V2));
setToolTipText("Z/T conversion");
// convert to Z stack
convertToZButton = new IcyCommandButton(SequenceOperationActions.convertToSlicesAction);
addCommandButton(convertToZButton, RibbonElementPriority.MEDIUM);
// convert to T stack
convertToTButton = new IcyCommandButton(SequenceOperationActions.convertToFramesAction);
addCommandButton(convertToTButton, RibbonElementPriority.MEDIUM);
// advanced conversion
advancedConvertButton = new IcyCommandButton(SequenceOperationActions.advancedZTConvertAction);
addCommandButton(advancedConvertButton, RibbonElementPriority.MEDIUM);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = (seq != null);
final boolean severalZ = enabled && (seq.getSizeZ() > 1);
final boolean severalT = enabled && (seq.getSizeT() > 1);
convertToTButton.setEnabled(severalZ);
convertToZButton.setEnabled(severalT);
advancedConvertButton.setEnabled(severalZ || severalT);
}
}
public static class ModifyRibbonBand extends JRibbonBand
{
/**
*
*/
private static final long serialVersionUID = -2677243480668715388L;
public static final String NAME = "Fill operation";
final IcyTextField fillValueField;
// final IcyButton fillImage;
final IcyButton fillSequence;
public ModifyRibbonBand()
{
super(NAME, new IcyIcon("document"));
setToolTipText("Fill operation");
fillValueField = new IcyTextField();
ComponentUtil.setFixedWidth(fillValueField, 90);
fillValueField.setToolTipText("Value used for filling");
fillValueField.setText("0");
fillSequence = new IcyButton(SequenceOperationActions.fillSequenceAction);
fillSequence.setFlat(true);
JRibbonComponent comp;
comp = new JRibbonComponent(fillSequence);
comp.setResizingAware(true);
addRibbonComponent(comp);
comp = new JRibbonComponent(fillValueField);
comp.setResizingAware(true);
addRibbonComponent(comp);
RibbonUtil.setRestrictiveResizePolicies(this);
updateButtonsState();
}
public double getFillValue()
{
double value = StringUtil.parseDouble(fillValueField.getText(), 0);
final Sequence sequence = Icy.getMainInterface().getActiveSequence();
if ((sequence != null) && (!sequence.isFloatDataType()))
{
final double bounds[] = sequence.getDataType_().getDefaultBounds();
// limit value to data type bounds
if (value < bounds[0])
value = bounds[0];
if (value > bounds[1])
value = bounds[1];
}
// set value back if incorrect
fillValueField.setText(Double.toString(value));
return value;
}
void updateButtonsState()
{
final Sequence seq = Icy.getMainInterface().getActiveSequence();
final boolean enabled = (seq != null) && !seq.isEmpty();
fillValueField.setEnabled(enabled);
fillSequence.setEnabled(enabled);
}
}
public static final String NAME = "Sequence operation";
final CopyConvertBand copyConvertBand;
final RenderingBand colorConvertBand;
final ZTConversionBand stackConversionBand;
final PlanarOperationBand planarOperationBand;
final ChannelOperationBand channelOperationBand;
final ZOperationBand zStackOperationBand;
final TOperationBand tStackOperationBand;
final ModifyRibbonBand modifyBand;
final Runnable buttonUpdater;
public SequenceOperationTask()
{
super(NAME, new CopyConvertBand(), new PlanarOperationBand(), new ChannelOperationBand(), new ZOperationBand(),
new TOperationBand(), new ZTConversionBand(), new RenderingBand(), new ModifyRibbonBand());
copyConvertBand = (CopyConvertBand) getBand(0);
planarOperationBand = (PlanarOperationBand) getBand(1);
channelOperationBand = (ChannelOperationBand) getBand(2);
zStackOperationBand = (ZOperationBand) getBand(3);
tStackOperationBand = (TOperationBand) getBand(4);
stackConversionBand = (ZTConversionBand) getBand(5);
colorConvertBand = (RenderingBand) getBand(6);
modifyBand = (ModifyRibbonBand) getBand(7);
copyConvertBand.updateButtonsState();
colorConvertBand.updateButtonsState();
channelOperationBand.updateButtonsState();
planarOperationBand.updateButtonsState();
stackConversionBand.updateButtonsState();
zStackOperationBand.updateButtonsState();
tStackOperationBand.updateButtonsState();
modifyBand.updateButtonsState();
buttonUpdater = new Runnable()
{
@Override
public void run()
{
// sleep a bit
ThreadUtil.sleep(1);
ThreadUtil.invokeNow(new Runnable()
{
@Override
public void run()
{
copyConvertBand.updateButtonsState();
colorConvertBand.updateButtonsState();
channelOperationBand.updateButtonsState();
planarOperationBand.updateButtonsState();
stackConversionBand.updateButtonsState();
zStackOperationBand.updateButtonsState();
tStackOperationBand.updateButtonsState();
modifyBand.updateButtonsState();
}
});
}
};
}
public double getFillValue()
{
return modifyBand.getFillValue();
}
/**
* call this method on sequence change
*/
public void onSequenceChange()
{
ThreadUtil.runSingle(buttonUpdater);
}
}