001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.gui.menu;
020
021import icy.action.GeneralActions;
022import icy.gui.component.button.IcyCommandButton;
023import icy.gui.component.button.IcyCommandToggleButton;
024import icy.gui.main.MainFrame;
025import icy.gui.util.LookAndFeelUtil;
026import icy.gui.util.RibbonUtil;
027import icy.image.ImageUtil;
028import icy.imagej.ImageJWrapper;
029import icy.imagej.ImageJWrapper.ImageJActiveImageListener;
030import icy.main.Icy;
031import icy.resource.ResourceUtil;
032import icy.resource.icon.BasicResizableIcon;
033import icy.resource.icon.IcyIcon;
034import icy.system.SystemUtil;
035
036import java.awt.Image;
037import java.beans.PropertyChangeEvent;
038import java.beans.PropertyChangeListener;
039
040import javax.swing.JPanel;
041
042import org.pushingpixels.flamingo.api.common.CommandToggleButtonGroup;
043import org.pushingpixels.flamingo.api.common.RichTooltip;
044import org.pushingpixels.flamingo.api.ribbon.JRibbonBand;
045import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent;
046import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority;
047import org.pushingpixels.flamingo.api.ribbon.RibbonTask;
048
049import ij.Executer;
050import ij.ImageJ;
051import ij.WindowManager;
052import ij.gui.ImageWindow;
053
054/**
055 * @author Stephane
056 */
057public class ImageJTask extends RibbonTask implements PropertyChangeListener
058{
059    static final Image detachForIJ = ResourceUtil.getImage("help/ij_detached.jpg");
060
061    private static class ImageJRibbonBand extends JRibbonBand
062    {
063        /**
064         * 
065         */
066        private static final long serialVersionUID = 4431425194428863269L;
067
068        public static final String NAME = "ImageJ";
069
070        // ImageJ instance
071        ImageJWrapper imageJ;
072
073        // internal
074        final JRibbonComponent imageJComp;
075
076        public ImageJRibbonBand()
077        {
078            super(NAME, new BasicResizableIcon(ImageUtil.load(ImageJ.class.getResource("/microscope.gif"))));
079
080            // initialize some static ImageJ stuff
081
082            // home directory
083            SystemUtil.setProperty("plugins.dir", "ij");
084            // background color
085            ImageJ.backgroundColor = LookAndFeelUtil.getBackground(this);
086
087            try
088            {
089                // create ImageJ wrapper
090                imageJ = new ImageJWrapper();
091            }
092            catch (Throwable t)
093            {
094                // ImageJ can't initialize --> just display an error message
095                System.err.println(t.getMessage());
096                imageJ = null;
097            }
098
099            if (imageJ != null)
100                imageJComp = new JRibbonComponent(imageJ.getSwingPanel());
101            else
102                imageJComp = new JRibbonComponent(new JPanel());
103
104            // add ImageJ GUI wrapper to ribbon
105            addRibbonComponent(imageJComp, 3);
106
107            RibbonUtil.setRestrictiveResizePolicies(this);
108        }
109    }
110
111    private static class ImageJToolRibbonBand extends JRibbonBand
112    {
113        /**
114         * 
115         */
116        private static final long serialVersionUID = -6873081018953405306L;
117
118        public static final String NAME = "Tools";
119
120        /**
121         * internals
122         */
123        final IcyCommandButton button;
124        final IcyCommandToggleButton detachedBtn;
125        final CommandToggleButtonGroup detachedGrp;
126
127        public ImageJToolRibbonBand()
128        {
129            super(NAME, new IcyIcon("brackets"));
130
131            // convert operation
132            button = new IcyCommandButton(GeneralActions.toIJAction);
133
134            addCommandButton(button, RibbonElementPriority.TOP);
135
136            // detach windows button
137            detachedBtn = new IcyCommandToggleButton(GeneralActions.detachedModeAction);
138
139            final RichTooltip richToolTip = new RichTooltip("Detached windows",
140                    "Icy need to be set in detached mode to use ImageJ efficiently and enable image conversion.");
141            richToolTip.setMainImage(detachForIJ);
142            richToolTip.addDescriptionSection(
143                    "This button has the same effect as the detached mode button in the top toolbar.");
144            detachedBtn.setActionRichTooltip(richToolTip);
145
146            detachedGrp = new CommandToggleButtonGroup();
147            detachedGrp.add(detachedBtn);
148
149            addCommandButton(detachedBtn, RibbonElementPriority.TOP);
150
151            RibbonUtil.setPermissiveResizePolicies(this);
152        }
153
154        public void setActionToIJ()
155        {
156            button.setAction(GeneralActions.toIJAction);
157            updateButtonsState();
158        }
159
160        public void setActionToIcy()
161        {
162            button.setAction(GeneralActions.toIcyAction);
163            updateButtonsState();
164        }
165
166        public void updateButtonsState()
167        {
168            final boolean isDetached = Icy.getMainInterface().isDetachedMode();
169
170            detachedGrp.setSelected(detachedBtn, isDetached);
171
172            if (button.getAction() == GeneralActions.toIcyAction)
173                button.setEnabled(isDetached && (WindowManager.getCurrentImage() != null));
174            else
175                button.setEnabled(isDetached && (Icy.getMainInterface().getActiveSequence() != null));
176        }
177    }
178
179    public static final String NAME = "ImageJ";
180
181    protected final ImageJToolRibbonBand ijToolBand;
182
183    public ImageJTask()
184    {
185        super(NAME, new ImageJRibbonBand(), new ImageJToolRibbonBand());
186
187        ijToolBand = (ImageJToolRibbonBand) getBand(1);
188
189        getImageJ().addActiveImageListener(new ImageJActiveImageListener()
190        {
191            @Override
192            public void imageActived(ImageWindow iw)
193            {
194                if (iw != null)
195                    ijToolBand.setActionToIcy();
196                else if (Icy.getMainInterface().getActiveSequence() != null)
197                    ijToolBand.setActionToIJ();
198                else
199                    ijToolBand.updateButtonsState();
200            }
201        });
202    }
203
204    /**
205     * Initialization stuff which cannot be done at construction time
206     */
207    public void init()
208    {
209        // refresh band state
210        propertyChange(null);
211
212        final MainFrame mainFrame = Icy.getMainInterface().getMainFrame();
213        // we listen detach mode change
214        if (mainFrame != null)
215            mainFrame.addPropertyChangeListener(MainFrame.PROPERTY_DETACHEDMODE, this);
216    }
217
218    /**
219     * @return the imageJ
220     */
221    public ImageJWrapper getImageJ()
222    {
223        return ((ImageJRibbonBand) getBand(0)).imageJ;
224    }
225
226    /**
227     * Quit imageJ
228     */
229    public void quitImageJ()
230    {
231        new Executer("Quit", null);
232    }
233
234    public void onSequenceActivationChange()
235    {
236        if (Icy.getMainInterface().getActiveSequence() != null)
237            ijToolBand.setActionToIJ();
238        else if (WindowManager.getCurrentImage() != null)
239            ijToolBand.setActionToIcy();
240        else
241            ijToolBand.updateButtonsState();
242    }
243
244    /**
245     * Handle {@link MainFrame#PROPERTY_DETACHEDMODE} property change here.
246     */
247    @Override
248    public void propertyChange(PropertyChangeEvent evt)
249    {
250        ijToolBand.updateButtonsState();
251    }
252}