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.inspector;
020
021import java.awt.BorderLayout;
022import java.awt.Color;
023import java.awt.Component;
024import java.awt.Dimension;
025import java.awt.Point;
026import java.awt.event.ActionEvent;
027import java.awt.event.ActionListener;
028
029import javax.swing.JPanel;
030import javax.swing.JScrollPane;
031import javax.swing.JTabbedPane;
032import javax.swing.ScrollPaneConstants;
033import javax.swing.event.ChangeEvent;
034import javax.swing.event.ChangeListener;
035
036import icy.gui.component.ExtTabbedPanel;
037import icy.gui.component.ExternalizablePanel;
038import icy.gui.component.button.IcyToggleButton;
039import icy.gui.main.ActiveSequenceListener;
040import icy.gui.main.ActiveViewerListener;
041import icy.gui.main.MainFrame;
042import icy.gui.system.MemoryMonitorPanel;
043import icy.gui.system.OutputConsolePanel;
044import icy.gui.system.OutputConsolePanel.OutputConsoleChangeListener;
045import icy.gui.viewer.Viewer;
046import icy.gui.viewer.ViewerEvent;
047import icy.main.Icy;
048import icy.preferences.GeneralPreferences;
049import icy.resource.ResourceUtil;
050import icy.resource.icon.IcyIcon;
051import icy.sequence.Sequence;
052import icy.sequence.SequenceEvent;
053import icy.system.thread.ThreadUtil;
054
055/**
056 * This window shows all details about the current sequence.
057 * 
058 * @author Fabrice de Chaumont & Stephane
059 */
060public class InspectorPanel extends ExternalizablePanel implements ActiveViewerListener, ActiveSequenceListener
061{
062    private static final long serialVersionUID = 5538230736731006318L;
063
064    /**
065     * GUI
066     */
067    final ExtTabbedPanel mainPane;
068
069    final SequencePanel sequencePanel;
070    final RoisPanel roisPanel;
071    final LayersPanel layersPanel;
072    final UndoManagerPanel historyPanel;
073    final OutputConsolePanel outputConsolePanel;
074    // final ChatPanel chatPanel;
075
076    final IcyToggleButton virtualModeBtn;
077
078    /**
079     * The width of the inner component of the inspector should not exceed 300.
080     */
081    public InspectorPanel()
082    {
083        super("Inspector", "inspector", new Point(600, 140), new Dimension(300, 600));
084
085        // tab panel
086        mainPane = new ExtTabbedPanel();
087        mainPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
088
089        // main panels
090        sequencePanel = new SequencePanel();
091        // final JPanel pluginsPanel = new PluginsPanel();
092        roisPanel = new RoisPanel();
093        layersPanel = new LayersPanel();
094        historyPanel = new UndoManagerPanel();
095        outputConsolePanel = new OutputConsolePanel();
096        // chatPanel = new ChatPanel();
097
098        // virtual mode button (set the same size as memory monitor)
099        virtualModeBtn = new IcyToggleButton(new IcyIcon(ResourceUtil.ICON_HDD_STREAM, 48));
100        virtualModeBtn.setToolTipText("Enable / disable the virtual mode (all images are created in virtual mode)");
101        virtualModeBtn.setHideActionText(true);
102        virtualModeBtn.setFlat(true);
103        virtualModeBtn.setFocusable(false);
104        virtualModeBtn.setSelected(GeneralPreferences.getVirtualMode());
105        virtualModeBtn.addActionListener(new ActionListener()
106        {
107            @Override
108            public void actionPerformed(ActionEvent e)
109            {
110                // switch virtual mode state
111                GeneralPreferences.setVirtualMode(!GeneralPreferences.getVirtualMode());
112
113                // refresh title (display virtual mode or not)
114                final MainFrame mainFrame = Icy.getMainInterface().getMainFrame();
115                if (mainFrame != null)
116                    mainFrame.refreshTitle();
117            }
118        });
119
120        // add main tab panels
121        mainPane.addTab("Sequence", null, new JScrollPane(sequencePanel,
122                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER),
123                "Sequence informations");
124        // mainPane.add("Active Plugin", pluginsPanel);
125        mainPane.addTab("ROI", null, roisPanel, "Manage / edit your ROI");
126        mainPane.addTab("Layer", null, layersPanel, "Show all layers details");
127        mainPane.addTab("History", null, historyPanel, "Actions history");
128        mainPane.addTab("Output", null, outputConsolePanel, "Console output");
129        // mainPane.addTab("Chat", null, chatPanel, "Chat room");
130
131        // minimum required size for sequence infos panel
132        final Dimension minDim = new Dimension(300, 480);
133        getFrame().setMinimumSizeInternal(minDim);
134        getFrame().setMinimumSizeExternal(minDim);
135        setMinimumSize(minDim);
136        setLayout(new BorderLayout());
137
138        add(mainPane, BorderLayout.CENTER);
139
140        // build bottom panel for inspector
141        final JPanel bottomPanel = new JPanel();
142        bottomPanel.setLayout(new BorderLayout());
143
144        // add virtual button and memory monitor
145        bottomPanel.add(virtualModeBtn, BorderLayout.EAST);
146        bottomPanel.add(new MemoryMonitorPanel(), BorderLayout.CENTER);
147
148        add(bottomPanel, BorderLayout.SOUTH);
149
150        validate();
151        setVisible(true);
152
153        // get default color of tab background
154        final Color defaultBgColor = mainPane.getBackgroundAt(0);
155
156        mainPane.addChangeListener(new ChangeListener()
157        {
158            @Override
159            public void stateChanged(ChangeEvent e)
160            {
161                final int index = getIndexOfTab(outputConsolePanel);
162
163                // set back default tab color
164                if ((index != -1) && (mainPane.getSelectedIndex() == index))
165                    mainPane.setBackgroundAt(index, defaultBgColor);
166            }
167        });
168
169        outputConsolePanel.addOutputConsoleChangeListener(new OutputConsoleChangeListener()
170        {
171            @Override
172            public void outputConsoleChanged(OutputConsolePanel source, boolean isError)
173            {
174                final int index = getIndexOfTab(outputConsolePanel);
175
176                if ((index != -1) && (mainPane.getSelectedIndex() != index))
177                {
178                    final boolean fIsError = isError;
179
180                    ThreadUtil.invokeLater(new Runnable()
181                    {
182                        @Override
183                        public void run()
184                        {
185                            // change output console tab color when new data
186                            if (fIsError)
187                                mainPane.setBackgroundAt(index, Color.red);
188                            else if (!mainPane.getBackgroundAt(index).equals(Color.red))
189                                mainPane.setBackgroundAt(index, Color.blue);
190                        }
191                    });
192                }
193            }
194        });
195
196        // add focused sequence & viewer listener
197        Icy.getMainInterface().addActiveViewerListener(this);
198        Icy.getMainInterface().addActiveSequenceListener(this);
199    }
200
201    /**
202     * @return the mainPane
203     */
204    public ExtTabbedPanel getMainPane()
205    {
206        return mainPane;
207    }
208
209    /**
210     * @return the sequencePanel
211     */
212    public SequencePanel getSequencePanel()
213    {
214        return sequencePanel;
215    }
216
217    /**
218     * @return the roisPanel
219     */
220    public RoisPanel getRoisPanel()
221    {
222        return roisPanel;
223    }
224
225    /**
226     * @return the layersPanel
227     */
228    public LayersPanel getLayersPanel()
229    {
230        return layersPanel;
231    }
232
233    /**
234     * @return the historyPanel
235     */
236    public UndoManagerPanel getHistoryPanel()
237    {
238        return historyPanel;
239    }
240
241    /**
242     * @return the outputConsolePanel
243     */
244    public OutputConsolePanel getOutputConsolePanel()
245    {
246        return outputConsolePanel;
247    }
248
249    /**
250     * @deprecated IRC has been removed since Icy 1.9.8.0
251     */
252    public ChatPanel getChatPanel()
253    {
254        return null;
255        // return chatPanel;
256    }
257
258    public static boolean getVirtualMode()
259    {
260        return GeneralPreferences.getVirtualMode();
261    }
262
263    public void setVirtualMode(boolean value)
264    {
265        virtualModeBtn.setSelected(value);
266        GeneralPreferences.setVirtualMode(value);
267    }
268
269    /**
270     * Call this to disable 'virtual mode' button
271     */
272    public void imageCacheDisabled()
273    {
274        // image cache is disabled so we can't use caching
275        virtualModeBtn.setEnabled(false);
276        virtualModeBtn.setSelected(false);
277        virtualModeBtn.setToolTipText("Image cache is disabled, cannot use the virtual mode");
278
279        // refresh title (display virtual mode or not)
280        final MainFrame mainFrame = Icy.getMainInterface().getMainFrame();
281        if (mainFrame != null)
282            mainFrame.refreshTitle();
283    }
284
285    /**
286     * Return the index of specified tab component
287     */
288    protected int getIndexOfTab(Component component)
289    {
290        return mainPane.indexOfComponent(component);
291    }
292
293    @Override
294    public void viewerActivated(Viewer viewer)
295    {
296        sequencePanel.viewerActivated(viewer);
297        layersPanel.viewerActivated(viewer);
298    }
299
300    @Override
301    public void viewerDeactivated(Viewer viewer)
302    {
303        // nothing to do here
304    }
305
306    /**
307     * Called when focused viewer has changed
308     */
309    @Override
310    public void activeViewerChanged(ViewerEvent event)
311    {
312        sequencePanel.activeViewerChanged(event);
313        layersPanel.activeViewerChanged(event);
314    }
315
316    @Override
317    public void sequenceActivated(Sequence sequence)
318    {
319        sequencePanel.sequenceActivated(sequence);
320        roisPanel.sequenceActivated(sequence);
321        historyPanel.sequenceActivated(sequence);
322    }
323
324    @Override
325    public void sequenceDeactivated(Sequence sequence)
326    {
327        // nothing to do here
328    }
329
330    /**
331     * Called by mainInterface when focused sequence has changed
332     */
333    @Override
334    public void activeSequenceChanged(SequenceEvent event)
335    {
336        sequencePanel.activeSequenceChanged(event);
337        roisPanel.activeSequenceChanged(event);
338    }
339}