View Javadoc

1   /**
2    * Copyright (c) 2011, The University of Southampton and the individual contributors.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    *   * 	Redistributions of source code must retain the above copyright notice,
9    * 	this list of conditions and the following disclaimer.
10   *
11   *   *	Redistributions in binary form must reproduce the above copyright notice,
12   * 	this list of conditions and the following disclaimer in the documentation
13   * 	and/or other materials provided with the distribution.
14   *
15   *   *	Neither the name of the University of Southampton nor the names of its
16   * 	contributors may be used to endorse or promote products derived from this
17   * 	software without specific prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package org.openimaj.content.slideshow;
31  
32  import java.awt.BorderLayout;
33  import java.awt.Color;
34  import java.awt.Component;
35  import java.awt.Dimension;
36  import java.awt.Graphics;
37  import java.awt.Graphics2D;
38  import java.awt.GridBagConstraints;
39  import java.awt.GridBagLayout;
40  import java.awt.event.KeyEvent;
41  import java.awt.event.KeyListener;
42  import java.awt.event.MouseAdapter;
43  import java.awt.event.MouseEvent;
44  import java.awt.image.BufferedImage;
45  import java.io.IOException;
46  import java.util.List;
47  
48  import javax.swing.JPanel;
49  import javax.swing.JScrollPane;
50  import javax.swing.RootPaneContainer;
51  import javax.swing.UIManager;
52  
53  /**
54   * Implementation of a slideshow made up of {@link Slide}s. Binds the left and
55   * right arrow keys to forward/backward, 'q' to quit and 'f' to toggle
56   * fullscreen mode. If the current slide being displayed is also a
57   * {@link KeyListener} then keypresses other than these will be passed to the
58   * slide.
59   *
60   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
61   *
62   */
63  public abstract class Slideshow implements KeyListener {
64  	protected RootPaneContainer container;
65  
66  	protected List<Slide> slides;
67  	protected int currentSlideIndex = -1;
68  	protected Component currentSlideComp;
69  
70  	protected int slideWidth;
71  	protected int slideHeight;
72  
73  	protected Slide currentSlide;
74  
75  	private JPanel contentPanel;
76  
77  	/**
78  	 * Default constructor.
79  	 *
80  	 * @param container
81  	 *            the root window
82  	 * @param slides
83  	 *            the slides
84  	 * @param slideWidth
85  	 *            the width to display the slides
86  	 * @param slideHeight
87  	 *            the height to display the slides
88  	 * @param background
89  	 *            a background image to display behind the slides (the slides
90  	 *            need to be transparent!)
91  	 * @throws IOException
92  	 *             if the first slide can't be loaded
93  	 */
94  	public Slideshow(RootPaneContainer container, List<Slide> slides, final int slideWidth, final int slideHeight,
95  			BufferedImage background) throws IOException
96  	{
97  		this.container = container;
98  
99  		this.slideWidth = slideWidth;
100 		this.slideHeight = slideHeight;
101 
102 		final BufferedImage bg;
103 		if (background == null) {
104 			bg = new BufferedImage(slideWidth, slideHeight, BufferedImage.TYPE_3BYTE_BGR);
105 			final Graphics2D g = bg.createGraphics();
106 			g.setColor(UIManager.getColor("Panel.background"));
107 			g.fillRect(0, 0, bg.getWidth(), bg.getHeight());
108 		} else {
109 			bg = background;
110 		}
111 
112 		contentPanel = new JPanel() {
113 			private static final long serialVersionUID = 1L;
114 
115 			@Override
116 			public void paintComponent(Graphics g)
117 			{
118 				super.paintComponent(g);
119 				g.drawImage(bg, 0, 0, slideWidth, slideHeight, null);
120 			};
121 		};
122 		contentPanel.setOpaque(false);
123 		contentPanel.setSize(slideWidth, slideHeight);
124 		contentPanel.setPreferredSize(new Dimension(slideWidth, slideHeight));
125 		contentPanel.setLayout(new GridBagLayout());
126 
127 		final JPanel scrollContent = new JPanel();
128 		scrollContent.setLayout(new GridBagLayout());
129 		scrollContent.setSize(contentPanel.getSize());
130 		scrollContent.setPreferredSize(contentPanel.getSize());
131 		scrollContent.add(contentPanel);
132 		scrollContent.setBackground(Color.BLACK);
133 
134 		container.getContentPane().setBackground(Color.BLACK);
135 
136 		final JScrollPane scroller = new JScrollPane(scrollContent);
137 		scroller.setBackground(Color.BLACK);
138 		scroller.setBorder(null);
139 		container.getContentPane().add(scroller, BorderLayout.CENTER);
140 
141 		((Component) container).addKeyListener(this);
142 
143 		this.slides = slides;
144 
145 		displayNextSlide();
146 		pack();
147 
148 		((Component) container).setVisible(true);
149 	}
150 
151 	protected abstract void pack();
152 
153 	/**
154 	 * Display the next slide
155 	 *
156 	 * @throws IOException
157 	 */
158 	public void displayNextSlide() throws IOException {
159 		if (currentSlideIndex < slides.size() - 1) {
160 			currentSlideIndex++;
161 			displaySlide(slides.get(currentSlideIndex));
162 		}
163 	}
164 
165 	/**
166 	 * Display the previous slide
167 	 *
168 	 * @throws IOException
169 	 */
170 	public void displayPrevSlide() throws IOException {
171 		if (currentSlideIndex > 0) {
172 			currentSlideIndex--;
173 			displaySlide(slides.get(currentSlideIndex));
174 		}
175 	}
176 
177 	protected void displaySlide(Slide slide) throws IOException {
178 		if (currentSlideComp != null) {
179 			contentPanel.remove(currentSlideComp);
180 			currentSlide.close();
181 		}
182 
183 		currentSlide = slide;
184 		currentSlideComp = currentSlide.getComponent(slideWidth, slideHeight);
185 		currentSlideComp.setPreferredSize(new Dimension(slideWidth, slideHeight));
186 		currentSlideComp.setMaximumSize(new Dimension(slideWidth, slideHeight));
187 
188 		contentPanel.add(currentSlideComp, new GridBagConstraints());
189 
190 		currentSlideComp.setFocusable(true);
191 		currentSlideComp.requestFocus();
192 		currentSlideComp.addKeyListener(this);
193 		currentSlideComp.addMouseListener(new MouseAdapter() {
194 			@Override
195 			public void mouseClicked(MouseEvent e) {
196 				currentSlideComp.requestFocus();
197 			}
198 		});
199 
200 		contentPanel.validate();
201 		((Component) container).repaint();
202 	}
203 
204 	@Override
205 	public void keyTyped(KeyEvent e) {
206 		if (currentSlide instanceof KeyListener) {
207 			((KeyListener) currentSlide).keyTyped(e);
208 		}
209 	}
210 
211 	@Override
212 	public void keyPressed(KeyEvent e) {
213 		try {
214 			switch (e.getKeyCode()) {
215 			case KeyEvent.VK_LEFT:
216 				displayPrevSlide();
217 				break;
218 			case KeyEvent.VK_RIGHT:
219 				displayNextSlide();
220 				break;
221 			case KeyEvent.VK_F:
222 				toggleFullscreen();
223 				break;
224 			case KeyEvent.VK_ESCAPE:
225 				setFullscreen(false);
226 				break;
227 			case KeyEvent.VK_Q:
228 				System.exit(0);
229 			}
230 		} catch (final Exception ex) {
231 			ex.printStackTrace();
232 		}
233 
234 		if (currentSlide instanceof KeyListener) {
235 			((KeyListener) currentSlide).keyPressed(e);
236 		}
237 	}
238 
239 	private void toggleFullscreen() {
240 		setFullscreen(!isFullscreen());
241 	}
242 
243 	protected abstract boolean isFullscreen();
244 
245 	/**
246 	 * Method allows changing whether this window is displayed in fullscreen or
247 	 * windowed mode.
248 	 *
249 	 * @param fullscreen
250 	 *            true = change to fullscreen, false = change to windowed
251 	 */
252 	public abstract void setFullscreen(boolean fullscreen);
253 
254 	@Override
255 	public void keyReleased(KeyEvent e) {
256 		if (currentSlide instanceof KeyListener) {
257 			((KeyListener) currentSlide).keyReleased(e);
258 		}
259 	}
260 }