diff --git a/src/main/java/bdv/viewer/ViewerPanel.java b/src/main/java/bdv/viewer/ViewerPanel.java index 444d4adfb16b6da95aab374d7e56fcda5a334e8a..80cca1688e812848bcc25ef2bcde7d6339d57dce 100644 --- a/src/main/java/bdv/viewer/ViewerPanel.java +++ b/src/main/java/bdv/viewer/ViewerPanel.java @@ -45,6 +45,7 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.LayoutManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; @@ -72,6 +73,7 @@ import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.Timer; import javax.swing.border.EmptyBorder; +import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -170,7 +172,7 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis */ protected final InteractiveDisplayCanvasComponent< AffineTransform3D > display; - protected final JSlider sliderTime; + protected final TimeSlider sliderTime; /** * A {@link ThreadGroup} for (only) the threads used by this @@ -427,10 +429,10 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis sliderPanel.add( timeKeyframePanel ); timeKeyframePanel.setLayout( new BoxLayout( timeKeyframePanel, BoxLayout.Y_AXIS ) ); - sliderTime = new JSlider( 0, numTimepoints - 1, 0 ); -// sliderTime.setMinimumSize( new Dimension( 36, 26 ) ); -// sliderTime.setMaximumSize( new Dimension( 32767, 26 ) ); - sliderTime.setSnapToTicks( true ); + + sliderTime = new DefaultTimeSlider(); + sliderTime.updateNumTimepoints( 0, numTimepoints ); + sliderTime.addTimePointListener( this::setTimepoint ); timeKeyframePanel.add( sliderTime ); @@ -439,16 +441,6 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis keyframePanel.setPreferredSize( new Dimension( 36, 26 ) ); timeKeyframePanel.add( keyframePanel ); - sliderTime.addChangeListener( new ChangeListener() - { - @Override - public void stateChanged( final ChangeEvent e ) - { - if ( e.getSource().equals( sliderTime ) ) - setTimepoint( sliderTime.getValue() ); - } - } ); - add( display, BorderLayout.CENTER ); if ( numTimepoints > 1 ) add( sliderPanel, BorderLayout.SOUTH ); @@ -886,12 +878,10 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis */ public synchronized void setTimepoint( final int timepoint ) { - if ( state.getCurrentTimepoint() != timepoint ) + if ( state.getCurrentTimepoint() != timepoint && timepoint >= 0 && timepoint < state.getNumTimepoints() ) { state.setCurrentTimepoint( timepoint ); - sliderTime.setValue( timepoint ); - for ( final TimePointListener l : timePointListeners ) - l.timePointChanged( timepoint ); + sliderTime.setTimepoint( timepoint ); requestRepaint(); } } @@ -902,7 +892,7 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis public synchronized void nextTimePoint() { if ( state.getNumTimepoints() > 1 ) - sliderTime.setValue( sliderTime.getValue() + 1 ); + setTimepoint( state.getCurrentTimepoint() + 1 ); } /** @@ -911,7 +901,7 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis public synchronized void previousTimePoint() { if ( state.getNumTimepoints() > 1 ) - sliderTime.setValue( sliderTime.getValue() - 1 ); + setTimepoint( state.getCurrentTimepoint() - 1 ); } /** @@ -952,7 +942,7 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis for ( final TimePointListener l : timePointListeners ) l.timePointChanged( timepoint ); } - sliderTime.setModel( new DefaultBoundedRangeModel( state.getCurrentTimepoint(), 0, 0, numTimepoints - 1 ) ); + sliderTime.updateNumTimepoints( state.getCurrentTimepoint(), numTimepoints ); revalidate(); requestRepaint(); } @@ -1348,4 +1338,78 @@ public class ViewerPanel extends JPanel implements OverlayRenderer, TransformLis return t; } } + + // TODO: move to separate file, add to ViewerOptions + public static abstract class TimeSlider extends JPanel + { + public TimeSlider( final LayoutManager layout, final boolean isDoubleBuffered ) + { + super( layout, isDoubleBuffered ); + } + + public TimeSlider( final LayoutManager layout ) + { + super( layout ); + } + + public TimeSlider( final boolean isDoubleBuffered ) + { + super( isDoubleBuffered ); + } + + public TimeSlider() + { + super(); + } + + public abstract void updateNumTimepoints( int currentTimepoint, int numTimepoints ); + + public abstract void setTimepoint( int timepoint ); + + public abstract void addTimePointListener( TimePointListener listener ); + } + + // TODO: move to separate file + public static class DefaultTimeSlider extends TimeSlider + { + private final CopyOnWriteArrayList< TimePointListener > listeners; + + private final JSlider slider; + + public DefaultTimeSlider() + { + super( new BorderLayout() ); + listeners = new CopyOnWriteArrayList<>(); + slider = new JSlider( SwingConstants.HORIZONTAL ); + slider.addChangeListener( new ChangeListener() + { + @Override + public void stateChanged( final ChangeEvent e ) + { + for ( final TimePointListener l : listeners ) + l.timePointChanged( slider.getValue() ); + } + } ); + slider.setSnapToTicks( true ); + add( slider, BorderLayout.CENTER ); + } + + @Override + public void updateNumTimepoints( final int currentTimepoint, final int numTimepoints ) + { + slider.setModel( new DefaultBoundedRangeModel( currentTimepoint, 0, 0, numTimepoints - 1 ) ); + } + + @Override + public void setTimepoint( final int timepoint ) + { + slider.setValue( timepoint ); + } + + @Override + public synchronized void addTimePointListener( final TimePointListener listener ) + { + listeners.add( listener ); + } + } }