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 it under the terms of the GNU General Public License as
007 * published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
008 * 
009 * Icy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
011 * 
012 * You should have received a copy of the GNU General Public License along with Icy. If not, see
013 * <http://www.gnu.org/licenses/>.
014 */
015package icy.action;
016
017import java.awt.Image;
018import java.awt.datatransfer.DataFlavor;
019import java.awt.event.ActionEvent;
020import java.awt.event.KeyEvent;
021import java.awt.image.BufferedImage;
022import java.lang.reflect.Field;
023import java.util.ArrayList;
024import java.util.Arrays;
025import java.util.List;
026
027import org.pushingpixels.flamingo.api.common.RichTooltip;
028
029import icy.clipboard.Clipboard;
030import icy.clipboard.TransferableImage;
031import icy.gui.dialog.ConfirmDialog;
032import icy.gui.frame.AboutFrame;
033import icy.gui.main.MainFrame;
034import icy.gui.menu.search.SearchBar;
035import icy.gui.viewer.Viewer;
036import icy.image.ImageUtil;
037import icy.imagej.ImageJUtil;
038import icy.main.Icy;
039import icy.network.NetworkUtil;
040import icy.plugin.PluginUpdater;
041import icy.preferences.GeneralPreferences;
042import icy.resource.ResourceUtil;
043import icy.resource.icon.IcyIcon;
044import icy.sequence.Sequence;
045import icy.system.IcyExceptionHandler;
046import icy.system.SystemUtil;
047import icy.system.audit.Audit;
048import icy.system.thread.ThreadUtil;
049import icy.update.IcyUpdater;
050import icy.util.ClassUtil;
051import ij.ImagePlus;
052import ij.WindowManager;
053
054/**
055 * General actions.
056 * 
057 * @author Stephane
058 */
059public class GeneralActions
060{
061    public static IcyAbstractAction searchAction = new IcyAbstractAction("Search",
062            new IcyIcon(ResourceUtil.ICON_SEARCH), "Application search tool", KeyEvent.VK_F,
063            SystemUtil.getMenuCtrlMask())
064    {
065        /**
066         * 
067         */
068        private static final long serialVersionUID = -7457421618693984393L;
069
070        @Override
071        public boolean doAction(ActionEvent e)
072        {
073            final MainFrame mf = Icy.getMainInterface().getMainFrame();
074
075            if (mf != null)
076            {
077                final SearchBar sb = mf.getSearchBar();
078
079                if (sb != null)
080                {
081                    sb.setFocus();
082                    return true;
083                }
084            }
085            return false;
086        }
087    };
088
089    public static IcyAbstractAction exitApplicationAction = new IcyAbstractAction("Exit",
090            new IcyIcon(ResourceUtil.ICON_ON_OFF))
091    {
092        /**
093         * 
094         */
095        private static final long serialVersionUID = -3238298900158332179L;
096
097        @Override
098        public boolean doAction(ActionEvent e)
099        {
100            Icy.exit(false);
101            return true;
102        }
103    };
104
105    public static IcyAbstractAction detachedModeAction = new IcyAbstractAction("Detached Mode",
106            new IcyIcon(ResourceUtil.ICON_DETACHED_WINDOW), "Detached mode ON/OFF",
107            "Switch application to detached / attached mode")
108    {
109        /**
110         * 
111         */
112        private static final long serialVersionUID = 6632773548066123185L;
113
114        @Override
115        public boolean doAction(ActionEvent e)
116        {
117            final boolean value = !Icy.getMainInterface().isDetachedMode();
118
119            // set detached mode
120            Icy.getMainInterface().setDetachedMode(value);
121            // and save state
122            GeneralPreferences.setMultiWindowMode(value);
123
124            return true;
125        }
126    };
127
128    public static IcyAbstractAction copyImageAction = new IcyAbstractAction("Copy image",
129            new IcyIcon(ResourceUtil.ICON_PICTURE_COPY), "Copy image to clipboard",
130            "Copy the active image to the system clipboard.", KeyEvent.VK_C, SystemUtil.getMenuCtrlMask(), true,
131            "Copying image to the clipboard...")
132    {
133        /**
134         * 
135         */
136        private static final long serialVersionUID = 8181120519734955113L;
137
138        @Override
139        public boolean doAction(ActionEvent e)
140        {
141            final Viewer viewer = Icy.getMainInterface().getActiveViewer();
142
143            if (viewer != null)
144            {
145                final Sequence seq = viewer.getSequence();
146
147                if (seq != null)
148                {
149                    try
150                    {
151                        final BufferedImage img = viewer.getRenderedImage(viewer.getPositionT(), viewer.getPositionZ(),
152                                viewer.getPositionC(), false);
153
154                        // put image in system clipboard
155                        Clipboard.putSystem(new TransferableImage(img), null);
156                        // clear content of Icy clipboard
157                        Clipboard.clear();
158
159                        return true;
160                    }
161                    catch (Throwable e1)
162                    {
163                        System.err.println("Can't copy image to clipboard:");
164                        IcyExceptionHandler.showErrorMessage(e1, false);
165                    }
166                }
167            }
168
169            return false;
170        }
171
172        @Override
173        public boolean isEnabled()
174        {
175            return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null);
176        }
177    };
178
179    public static IcyAbstractAction pasteImageAction = new IcyAbstractAction("Paste image",
180            new IcyIcon(ResourceUtil.ICON_PICTURE_PASTE), "Paste image from clipboard",
181            "Paste image from the system clipboard in a new sequence.", KeyEvent.VK_V, SystemUtil.getMenuCtrlMask(),
182            true, "Creating new sequence from clipboard image...")
183    {
184        /**
185         * 
186         */
187        private static final long serialVersionUID = 8181120519734955113L;
188
189        @Override
190        public boolean doAction(ActionEvent e)
191        {
192            try
193            {
194                if (Clipboard.hasTypeSystem(DataFlavor.imageFlavor))
195                {
196                    final Image img = (Image) Clipboard.getSystem(DataFlavor.imageFlavor);
197                    Icy.getMainInterface().addSequence(new Sequence("Clipboard image", ImageUtil.toBufferedImage(img)));
198                    return true;
199                }
200            }
201            catch (Throwable e1)
202            {
203                System.err.println("Can't paste image from clipboard:");
204                IcyExceptionHandler.showErrorMessage(e1, false);
205            }
206
207            return false;
208        }
209
210        @Override
211        public boolean isEnabled()
212        {
213            try
214            {
215                return super.isEnabled() && Clipboard.hasTypeSystem(DataFlavor.imageFlavor);
216            }
217            catch (Throwable e)
218            {
219                return false;
220            }
221        }
222    };
223
224    public static IcyAbstractAction toIJAction = new IcyAbstractAction("Convert to IJ",
225            new IcyIcon(ResourceUtil.ICON_TOIJ), "Convert to ImageJ",
226            "Convert the selected Icy sequence to ImageJ image.", true, "Converting to ImageJ image...")
227    {
228        /**
229         * 
230         */
231        private static final long serialVersionUID = -5506310360653637920L;
232
233        @Override
234        public boolean doAction(ActionEvent e)
235        {
236            final Sequence seq = Icy.getMainInterface().getActiveSequence();
237
238            if (seq != null)
239            {
240                final ImagePlus ip = ImageJUtil.convertToImageJImage(seq, true, progressFrame);
241
242                ThreadUtil.invokeLater(new Runnable()
243                {
244                    @Override
245                    public void run()
246                    {
247                        // show the image
248                        ip.show();
249                    }
250                });
251
252                return true;
253            }
254
255            return false;
256        }
257
258        @Override
259        public RichTooltip getRichToolTip()
260        {
261            final RichTooltip result = super.getRichToolTip();
262
263            result.addFooterSection("Icy needs to be in detached mode to enabled this feature.");
264
265            return result;
266        };
267
268        @Override
269        public boolean isEnabled()
270        {
271            return super.isEnabled() && (Icy.getMainInterface().getActiveSequence() != null);
272        }
273
274    };
275
276    public static IcyAbstractAction toIcyAction = new IcyAbstractAction("Convert to Icy",
277            new IcyIcon(ResourceUtil.ICON_TOICY), "Convert to Icy",
278            "Convert the selected ImageJ image to Icy sequence.", true, "Converting to Icy image...")
279    {
280        /**
281         * 
282         */
283        private static final long serialVersionUID = 5713619465058087088L;
284
285        @Override
286        public boolean doAction(ActionEvent e)
287        {
288            final ImagePlus ip = WindowManager.getCurrentImage();
289
290            if (ip != null)
291            {
292                final Sequence seq = ImageJUtil.convertToIcySequence(ip, progressFrame);
293
294                ThreadUtil.invokeLater(new Runnable()
295                {
296                    @Override
297                    public void run()
298                    {
299                        // show the sequence
300                        new Viewer(seq);
301                    }
302                });
303
304                return true;
305            }
306
307            return false;
308        }
309
310        @Override
311        public RichTooltip getRichToolTip()
312        {
313            final RichTooltip result = super.getRichToolTip();
314
315            result.addFooterSection("Icy needs to be in detached mode to enabled this feature.");
316
317            return result;
318        };
319
320        @Override
321        public boolean isEnabled()
322        {
323            return super.isEnabled() && (WindowManager.getCurrentImage() != null);
324        }
325    };
326
327    public static IcyAbstractAction onlineHelpAction = new IcyAbstractAction("Online help (F1)",
328            new IcyIcon(ResourceUtil.ICON_HELP), "Open a browser and display support forum", KeyEvent.VK_F1)
329    {
330        /**
331         * 
332         */
333        private static final long serialVersionUID = -8702011381533907199L;
334
335        @Override
336        public boolean doAction(ActionEvent e)
337        {
338            // open browser on help page
339            NetworkUtil.openBrowser(NetworkUtil.WEBSITE_URL + "support");
340            return true;
341        }
342    };
343
344    public static IcyAbstractAction websiteAction = new IcyAbstractAction("Website",
345            new IcyIcon(ResourceUtil.ICON_BROWSER))
346    {
347        /**
348         * 
349         */
350        private static final long serialVersionUID = 4447276299627488427L;
351
352        @Override
353        public boolean doAction(ActionEvent e)
354        {
355            // open browser on help page
356            NetworkUtil.openBrowser(NetworkUtil.WEBSITE_URL);
357            return true;
358        }
359    };
360
361    public static IcyAbstractAction linkAction = new IcyAbstractAction("Link", new IcyIcon(ResourceUtil.ICON_LINK),
362            "Link / unlink online user account",
363            "Link / unlink with online user account.\nGive access to extra features as plugin rating")
364    {
365
366        /**
367         * 
368         */
369        private static final long serialVersionUID = 3449298011169150396L;
370
371        @Override
372        public boolean doAction(ActionEvent e)
373        {
374            if (Audit.isUserLinked())
375            {
376                // ask for confirmation
377                if (!Icy.getMainInterface().isHeadLess()
378                        && !ConfirmDialog.confirm("Do you want to unlink user account ?"))
379                    return false;
380
381                // unlink user
382                Audit.unlinkUser();
383            }
384            else
385            {
386                // update link first
387                Audit.updateUserLink();
388
389                // still not linked --> link user
390                if (!Audit.isUserLinked())
391                    Audit.linkUser();
392            }
393
394            // refresh user infos (in title)
395            final MainFrame frame = Icy.getMainInterface().getMainFrame();
396            if (frame != null)
397                frame.refreshTitle();
398
399            return true;
400        }
401    };
402
403    public static IcyAbstractAction checkUpdateAction = new IcyAbstractAction("Check for update",
404            new IcyIcon(ResourceUtil.ICON_DOWNLOAD), "Check for updates",
405            "Search updates for application and plugins in all referenced repositories.")
406    {
407        /**
408         * 
409         */
410        private static final long serialVersionUID = 5070966391369409880L;
411
412        @Override
413        public boolean doAction(ActionEvent e)
414        {
415            // check core update
416            if (!IcyUpdater.isCheckingForUpdate())
417                IcyUpdater.checkUpdate(false);
418            // check plugin update
419            if (!PluginUpdater.isCheckingForUpdate())
420                PluginUpdater.checkUpdate(false);
421
422            return true;
423        }
424
425        @Override
426        public boolean isEnabled()
427        {
428            return super.isEnabled() && !(IcyUpdater.isCheckingForUpdate() || PluginUpdater.isCheckingForUpdate());
429        }
430
431    };
432
433    public static IcyAbstractAction aboutAction = new IcyAbstractAction("About", new IcyIcon(ResourceUtil.ICON_INFO),
434            "About Icy", "Information about ICY's authors, license and copyrights.")
435    {
436        /**
437         * 
438         */
439        private static final long serialVersionUID = 2564352020620899851L;
440
441        @Override
442        public boolean doAction(ActionEvent e)
443        {
444            new AboutFrame(0);
445            return true;
446        }
447    };
448
449    public static IcyAbstractAction changeLogAction = new IcyAbstractAction("ChangeLog", new IcyIcon("notepad_2.png"),
450            "ChangeLog", "See the changelog informations.")
451    {
452        /**
453         * 
454         */
455        private static final long serialVersionUID = 2564352020620899851L;
456
457        @Override
458        public boolean doAction(ActionEvent e)
459        {
460            new AboutFrame(1);
461            return true;
462        }
463    };
464
465    /**
466     * Return all actions of this class
467     */
468    public static List<IcyAbstractAction> getAllActions()
469    {
470        final List<IcyAbstractAction> result = new ArrayList<IcyAbstractAction>();
471
472        for (Field field : GeneralActions.class.getFields())
473        {
474            final Class<?> type = field.getType();
475
476            try
477            {
478                if (ClassUtil.isSubClass(type, IcyAbstractAction[].class))
479                    result.addAll(Arrays.asList(((IcyAbstractAction[]) field.get(null))));
480                else if (ClassUtil.isSubClass(type, IcyAbstractAction.class))
481                    result.add((IcyAbstractAction) field.get(null));
482            }
483            catch (Exception e)
484            {
485                // ignore
486            }
487        }
488
489        return result;
490    }
491}