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