/* * 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.viewer; import icy.gui.component.IcySlider; import icy.gui.component.button.IcyToggleButton; import icy.gui.util.ComponentUtil; import icy.gui.util.GuiUtil; import icy.resource.ResourceUtil; import icy.resource.icon.IcyIcon; import icy.system.thread.ThreadUtil; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.SwingConstants; import javax.swing.Timer; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * @author Stephane */ public class TNavigationPanel extends JPanel { /** * */ private static final long serialVersionUID = 9123780562399386045L; private static final int DEFAULT_FRAME_RATE = 15; final JSlider slider; final JLabel leftLabel; final JLabel rightLabel; final IcyToggleButton play; final IcyToggleButton loop; final JSpinner frameRate; final Timer timer; public TNavigationPanel() { super(true); slider = new IcySlider(SwingConstants.HORIZONTAL); slider.setFocusable(false); slider.setMaximum(0); slider.setMinimum(0); slider.setToolTipText("Move cursor to navigate in T dimension"); slider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { rightLabel.setText(Integer.toString(slider.getMaximum())); leftLabel.setText(Integer.toString(slider.getValue())); validate(); } }); ComponentUtil.setFixedHeight(slider, 22); timer = new Timer(1000 / DEFAULT_FRAME_RATE, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // only if slider is not adjusting T position if (!slider.getValueIsAdjusting()) { final int oldT = getTPosition(); incTPosition(); // end reached ? if (oldT == getTPosition()) { // loop mode --> reset if (isRepeat()) setTPosition(0); else { // end play stopPlay(); // and reset position setTPosition(0); } } } } }); play = new IcyToggleButton(new IcyIcon(ResourceUtil.ICON_PLAY)); play.setFlat(true); play.setToolTipText("play"); play.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (isPlaying()) stopPlay(); else startPlay(); } }); loop = new IcyToggleButton(new IcyIcon(ResourceUtil.ICON_ARROW_RIGHT, 16)); loop.setFlat(true); loop.setToolTipText("Enable loop playback"); loop.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setRepeat(!isRepeat()); } }); frameRate = new JSpinner(new SpinnerNumberModel(DEFAULT_FRAME_RATE, 1, 60, 1)); frameRate.setFocusable(false); // no manual edition and edition focus final JTextField tf = ((JSpinner.DefaultEditor) frameRate.getEditor()).getTextField(); tf.setEditable(false); tf.setFocusable(false); frameRate.setToolTipText("Change playback frame rate"); frameRate.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { final int f = ((Integer) frameRate.getValue()).intValue(); // adjust timer delay setTimerDelay(1000 / f); } }); ComponentUtil.setFixedSize(frameRate, new Dimension(50, 22)); leftLabel = new JLabel("0"); leftLabel.setToolTipText("T position"); rightLabel = new JLabel("0"); rightLabel.setToolTipText("T sequence size"); final JPanel leftPanel = GuiUtil.createLineBoxPanel(Box.createHorizontalStrut(8), GuiUtil.createBoldLabel("T"), Box.createHorizontalStrut(10), leftLabel); rightLabel.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { // so left label is adjusted to right label size ComponentUtil.setFixedWidth(leftLabel, rightLabel.getWidth()); leftPanel.revalidate(); } }); final JPanel rightPanel = new JPanel(); rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.LINE_AXIS)); final JLabel frameRateLabel = new JLabel("FPS"); frameRateLabel.setToolTipText("Frames Per Second"); rightPanel.add(rightLabel); rightPanel.add(Box.createHorizontalStrut(12)); rightPanel.add(play); rightPanel.add(loop); rightPanel.add(Box.createHorizontalStrut(8)); rightPanel.add(frameRate); rightPanel.add(Box.createHorizontalStrut(4)); rightPanel.add(frameRateLabel); rightPanel.add(Box.createHorizontalStrut(4)); // setBorder(BorderFactory.createLineBorder(BorderFactory.createTitledBorder("").getTitleColor())); setBorder(BorderFactory.createTitledBorder("").getBorder()); setLayout(new BorderLayout()); add(leftPanel, BorderLayout.WEST); add(slider, BorderLayout.CENTER); add(rightPanel, BorderLayout.EAST); validate(); } protected void incTPosition() { setTPosition(getTPosition() + 1); } protected void decTPosition() { setTPosition(Math.max(0, getTPosition() - 1)); } protected void setTimerDelay(int delay) { timer.setDelay(delay); } protected int getTPosition() { return slider.getValue(); } protected void setTPosition(final int t) { // we want to be sure the T position is changed in EDT ThreadUtil.invokeNow(new Runnable() { @Override public void run() { slider.setValue(t); } }); } /** * Returns the frame rate (given in frame per second) for play command. */ public int getFrameRate() { return ((Integer) frameRate.getValue()).intValue(); } /** * Sets the frame rate (given in frame per second) for play command. */ public void setFrameRate(int fps) { frameRate.setValue(Integer.valueOf(fps)); } /** * Returns true if <code>repeat</code> is enabled for play command. */ public boolean isRepeat() { return loop.getToolTipText().startsWith("Disable"); } /** * Set <code>repeat</code> mode for play command. */ public void setRepeat(boolean value) { if (value) { loop.setIcon(new IcyIcon(ResourceUtil.ICON_RELOAD, 16)); loop.setSelected(true); loop.setToolTipText("Disable loop playback"); } else { loop.setIcon(new IcyIcon(ResourceUtil.ICON_ARROW_RIGHT, 16)); loop.setSelected(false); loop.setToolTipText("Enable loop playback"); } } /** * Returns true if currently playing. */ public boolean isPlaying() { return timer.isRunning(); } /** * Start sequence play. * * @see #stopPlay() * @see #setRepeat(boolean) */ public void startPlay() { timer.start(); play.setIcon(new IcyIcon(ResourceUtil.ICON_PAUSE)); play.setSelected(true); play.setToolTipText("pause"); } /** * Stop sequence play. * * @see #startPlay() */ public void stopPlay() { timer.stop(); play.setIcon(new IcyIcon(ResourceUtil.ICON_PLAY)); play.setSelected(false); play.setToolTipText("play"); } /** * @see icy.gui.component.IcySlider#setPaintLabels(boolean) */ public void setPaintLabels(boolean b) { slider.setPaintLabels(b); } /** * @see icy.gui.component.IcySlider#setPaintTicks(boolean) */ public void setPaintTicks(boolean b) { slider.setPaintTicks(b); } /** * @see javax.swing.JSlider#addChangeListener(javax.swing.event.ChangeListener) */ public void addChangeListener(ChangeListener l) { slider.addChangeListener(l); } /** * @see javax.swing.JSlider#removeChangeListener(javax.swing.event.ChangeListener) */ public void removeChangeListener(ChangeListener l) { slider.removeChangeListener(l); } /** * Remove all change listener */ public void removeAllChangeListener() { for (ChangeListener l : slider.getListeners(ChangeListener.class)) slider.removeChangeListener(l); } /** * @see javax.swing.JSlider#getValue() */ public int getValue() { return slider.getValue(); } /** * @param n * @see javax.swing.JSlider#setValue(int) */ public void setValue(int n) { slider.setValue(n); } /** * @see javax.swing.JSlider#getMinimum() */ public int getMinimum() { return slider.getMinimum(); } /** * @see javax.swing.JSlider#setMinimum(int) */ public void setMinimum(int minimum) { slider.setMinimum(minimum); } /** * @see javax.swing.JSlider#getMaximum() */ public int getMaximum() { return slider.getMaximum(); } /** * @see javax.swing.JSlider#setMaximum(int) */ public void setMaximum(int maximum) { slider.setMaximum(maximum); } /** * @see javax.swing.JSlider#getPaintTicks() */ public boolean getPaintTicks() { return slider.getPaintTicks(); } /** * @see javax.swing.JSlider#getPaintTrack() */ public boolean getPaintTrack() { return slider.getPaintTrack(); } /** * @see javax.swing.JSlider#setPaintTrack(boolean) */ public void setPaintTrack(boolean b) { slider.setPaintTrack(b); } /** * @see javax.swing.JSlider#getPaintLabels() */ public boolean getPaintLabels() { return slider.getPaintLabels(); } }