PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/WorldWindX/src/main/java/gov/nasa/worldwindx/examples/util/SlideShowAnnotationController.java

http://geoforge.googlecode.com/
Java | 644 lines | 507 code | 108 blank | 29 comment | 115 complexity | d66a8b20ac96cce26bd6e4cf299d3e50 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, GPL-3.0, LGPL-2.1, LGPL-2.0
  1. /* Copyright (C) 2001, 2009 United States Government as represented by
  2. the Administrator of the National Aeronautics and Space Administration.
  3. All Rights Reserved.
  4. */
  5. package gov.nasa.worldwindx.examples.util;
  6. import gov.nasa.worldwind.*;
  7. import gov.nasa.worldwind.avlist.AVKey;
  8. import gov.nasa.worldwind.cache.*;
  9. import gov.nasa.worldwind.util.*;
  10. import javax.imageio.ImageIO;
  11. import java.awt.image.*;
  12. import java.io.IOException;
  13. import java.net.URL;
  14. /**
  15. * @author dcollins
  16. * @version $Id: SlideShowAnnotationController.java 1 2011-07-16 23:22:47Z dcollins $
  17. */
  18. @SuppressWarnings( {"TypeParameterExplicitlyExtendsObject"})
  19. public class SlideShowAnnotationController extends DialogAnnotationController
  20. {
  21. public static final String BUFFERED_IMAGE_CACHE_SIZE = "gov.nasa.worldwind.avkey.BufferedImageCacheSize";
  22. public static final String BUFFERED_IMAGE_CACHE_NAME = java.awt.image.BufferedImage.class.getName();
  23. protected static final long SLIDESHOW_UPDATE_DELAY_MILLIS = 2000;
  24. protected static final long DEFAULT_BUFFERED_IMAGE_CACHE_SIZE = 30000000;
  25. protected static java.awt.Dimension SMALL_IMAGE_PREFERRED_SIZE = new java.awt.Dimension(320, 240);
  26. protected static java.awt.Dimension LARGE_IMAGE_PREFERRED_SIZE = new java.awt.Dimension(600, 450);
  27. protected int index;
  28. protected String state;
  29. protected java.util.List<Object> imageSources;
  30. // Concurrent task components.
  31. protected Thread readThread;
  32. protected javax.swing.Timer updateTimer;
  33. public SlideShowAnnotationController(WorldWindow worldWindow, SlideShowAnnotation annotation,
  34. Iterable<?> imageSources)
  35. {
  36. super(worldWindow, annotation);
  37. this.state = AVKey.STOP;
  38. this.index = -1;
  39. this.imageSources = new java.util.ArrayList<Object>();
  40. if (imageSources != null)
  41. {
  42. for (Object source : imageSources)
  43. {
  44. if (source != null)
  45. this.imageSources.add(source);
  46. }
  47. }
  48. if (!WorldWind.getMemoryCacheSet().containsCache(BUFFERED_IMAGE_CACHE_NAME))
  49. {
  50. long size = Configuration.getLongValue(BUFFERED_IMAGE_CACHE_SIZE, DEFAULT_BUFFERED_IMAGE_CACHE_SIZE);
  51. MemoryCache cache = new BasicMemoryCache((long) (0.85 * size), size);
  52. WorldWind.getMemoryCacheSet().addCache(BUFFERED_IMAGE_CACHE_NAME, cache);
  53. }
  54. this.initializeSlideShow();
  55. }
  56. public SlideShowAnnotationController(WorldWindow worldWindow, SlideShowAnnotation annotation)
  57. {
  58. this(worldWindow, annotation, null);
  59. }
  60. protected void initializeSlideShow()
  61. {
  62. SlideShowAnnotation annotation = (SlideShowAnnotation) this.getAnnotation();
  63. // Set the image preferred size.
  64. this.setPreferredImageSize(SMALL_IMAGE_PREFERRED_SIZE);
  65. if (this.imageSources.size() <= 1)
  66. {
  67. annotation.getPlayButton().getAttributes().setVisible(false);
  68. annotation.getPreviousButton().getAttributes().setVisible(false);
  69. annotation.getNextButton().getAttributes().setVisible(false);
  70. annotation.getBeginButton().getAttributes().setVisible(false);
  71. annotation.getEndButton().getAttributes().setVisible(false);
  72. }
  73. if (!this.imageSources.isEmpty())
  74. {
  75. // Load the first image.
  76. this.doGoToImage(0);
  77. }
  78. }
  79. public java.util.List<? extends Object> getImageSources()
  80. {
  81. return java.util.Collections.unmodifiableList(this.imageSources);
  82. }
  83. public void setImageSources(Iterable<? extends Object> imageSources)
  84. {
  85. this.imageSources.clear();
  86. if (imageSources != null)
  87. {
  88. for (Object source : imageSources)
  89. {
  90. if (source != null)
  91. this.imageSources.add(source);
  92. }
  93. }
  94. }
  95. public String getState()
  96. {
  97. return this.state;
  98. }
  99. public int getIndex()
  100. {
  101. return this.index;
  102. }
  103. @SuppressWarnings( {"StringEquality"})
  104. public void goToImage(int index)
  105. {
  106. if (this.getAnnotation() == null)
  107. return;
  108. if (this.getState() == AVKey.PLAY)
  109. {
  110. this.stopSlideShow();
  111. }
  112. this.doGoToImage(index);
  113. }
  114. @SuppressWarnings( {"StringEquality"})
  115. public void startSlideShow()
  116. {
  117. if (this.getAnnotation() == null)
  118. return;
  119. if (this.hasNextIndex() && this.getState() == AVKey.STOP)
  120. {
  121. this.state = AVKey.PLAY;
  122. SlideShowAnnotation slideShowAnnotation = (SlideShowAnnotation) this.getAnnotation();
  123. slideShowAnnotation.setPlayButtonState(AVKey.PAUSE);
  124. this.startSlideShowUpdate();
  125. }
  126. }
  127. @SuppressWarnings( {"StringEquality"})
  128. public void stopSlideShow()
  129. {
  130. if (this.getAnnotation() == null)
  131. return;
  132. if (this.getState() == AVKey.PLAY)
  133. {
  134. this.state = AVKey.STOP;
  135. SlideShowAnnotation slideShowAnnotation = (SlideShowAnnotation) this.getAnnotation();
  136. slideShowAnnotation.setPlayButtonState(AVKey.PLAY);
  137. this.stopSlideShowUpdate();
  138. }
  139. }
  140. public void stopRetrievalTasks()
  141. {
  142. this.stopImageRetrieval();
  143. }
  144. public java.awt.Dimension getPreferredImageSize()
  145. {
  146. if (this.getAnnotation() == null)
  147. return null;
  148. SlideShowAnnotation slideShowAnnotation = (SlideShowAnnotation) this.getAnnotation();
  149. return slideShowAnnotation.getImageAnnotation().getAttributes().getSize();
  150. }
  151. public void setPreferredImageSize(java.awt.Dimension size)
  152. {
  153. if (this.getAnnotation() == null)
  154. return;
  155. SlideShowAnnotation slideShowAnnotation = (SlideShowAnnotation) this.getAnnotation();
  156. slideShowAnnotation.getImageAnnotation().getAttributes().setSize(size);
  157. }
  158. protected boolean hasPreviousIndex()
  159. {
  160. // The slide show loops, so there's always a previous index.
  161. return true;
  162. }
  163. protected boolean hasNextIndex()
  164. {
  165. // The slide show loops, so there's always a next index.
  166. return true;
  167. }
  168. protected int getPreviousIndex()
  169. {
  170. int maxIndex = this.imageSources.size() - 1;
  171. return (this.index > 0) ? (this.index - 1) : maxIndex;
  172. }
  173. protected int getNextIndex()
  174. {
  175. int maxIndex = this.imageSources.size() - 1;
  176. return (this.index < maxIndex) ? (this.index + 1) : 0;
  177. }
  178. protected void doGoToImage(int index)
  179. {
  180. int maxIndex = this.imageSources.size() - 1;
  181. if (index < 0 || index > maxIndex)
  182. return;
  183. if (index == this.index)
  184. return;
  185. this.retrieveAndSetImage(this.imageSources.get(index), index);
  186. }
  187. protected void doSetImage(PowerOfTwoPaddedImage image, int index)
  188. {
  189. int length = this.imageSources.size();
  190. Object imageSource = this.imageSources.get(index);
  191. String title = this.createTitle(imageSource);
  192. String positionText = this.createPositionText(index, length);
  193. this.index = index;
  194. SlideShowAnnotation slideShowAnnotation = (SlideShowAnnotation) this.getAnnotation();
  195. slideShowAnnotation.getTitleLabel().setText(title);
  196. slideShowAnnotation.getPositionLabel().setText(positionText);
  197. slideShowAnnotation.getImageAnnotation().setImageSource(image.getPowerOfTwoImage(),
  198. image.getOriginalWidth(), image.getOriginalHeight());
  199. // Update next and previous button states.
  200. slideShowAnnotation.getBeginButton().setEnabled(this.hasPreviousIndex());
  201. slideShowAnnotation.getPreviousButton().setEnabled(this.hasPreviousIndex());
  202. slideShowAnnotation.getNextButton().setEnabled(this.hasNextIndex());
  203. slideShowAnnotation.getEndButton().setEnabled(this.hasNextIndex());
  204. this.getWorldWindow().redraw();
  205. }
  206. //**************************************************************//
  207. //******************** Action Listener ***********************//
  208. //**************************************************************//
  209. @SuppressWarnings( {"StringEquality"})
  210. public void onActionPerformed(java.awt.event.ActionEvent e)
  211. {
  212. super.onActionPerformed(e);
  213. if (e.getActionCommand() == AVKey.PLAY)
  214. {
  215. this.playPressed(e);
  216. }
  217. else if (e.getActionCommand() == AVKey.PREVIOUS)
  218. {
  219. this.previousPressed(e);
  220. }
  221. else if (e.getActionCommand() == AVKey.NEXT)
  222. {
  223. this.nextPressed(e);
  224. }
  225. else if (e.getActionCommand() == AVKey.BEGIN)
  226. {
  227. this.beginPressed(e);
  228. }
  229. else if (e.getActionCommand() == AVKey.END)
  230. {
  231. this.endPressed(e);
  232. }
  233. else if (e.getActionCommand() == AVKey.RESIZE)
  234. {
  235. this.resizePressed(e);
  236. }
  237. }
  238. protected void playPressed(java.awt.event.ActionEvent e)
  239. {
  240. if (e == null)
  241. return;
  242. if (this.getAnnotation() == null)
  243. return;
  244. this.onPlayPressed(e);
  245. }
  246. protected void previousPressed(java.awt.event.ActionEvent e)
  247. {
  248. if (e == null)
  249. return;
  250. if (this.getAnnotation() == null)
  251. return;
  252. this.onPreviousPressed(e);
  253. }
  254. protected void nextPressed(java.awt.event.ActionEvent e)
  255. {
  256. if (e == null)
  257. return;
  258. if (this.getAnnotation() == null)
  259. return;
  260. this.onNextPressed(e);
  261. }
  262. protected void beginPressed(java.awt.event.ActionEvent e)
  263. {
  264. if (e == null)
  265. return;
  266. if (this.getAnnotation() == null)
  267. return;
  268. this.onBeginPressed(e);
  269. }
  270. protected void endPressed(java.awt.event.ActionEvent e)
  271. {
  272. if (e == null)
  273. return;
  274. if (this.getAnnotation() == null)
  275. return;
  276. this.onEndPressed(e);
  277. }
  278. protected void resizePressed(java.awt.event.ActionEvent e)
  279. {
  280. if (e == null)
  281. return;
  282. if (this.getAnnotation() == null)
  283. return;
  284. this.onResizePressed(e);
  285. }
  286. @SuppressWarnings( {"UnusedDeclaration", "StringEquality"})
  287. protected void onPlayPressed(java.awt.event.ActionEvent e)
  288. {
  289. String state = this.getState();
  290. if (state == null)
  291. return;
  292. if (state == AVKey.PLAY)
  293. {
  294. this.stopSlideShow();
  295. }
  296. else if (state == AVKey.STOP)
  297. {
  298. this.startSlideShow();
  299. }
  300. }
  301. @SuppressWarnings( {"UnusedDeclaration"})
  302. protected void onPreviousPressed(java.awt.event.ActionEvent e)
  303. {
  304. if (!this.hasPreviousIndex())
  305. return;
  306. int newIndex = this.getPreviousIndex();
  307. this.goToImage(newIndex);
  308. }
  309. @SuppressWarnings( {"UnusedDeclaration"})
  310. protected void onNextPressed(java.awt.event.ActionEvent e)
  311. {
  312. if (!this.hasNextIndex())
  313. return;
  314. int newIndex = this.getNextIndex();
  315. this.goToImage(newIndex);
  316. }
  317. @SuppressWarnings( {"UnusedDeclaration"})
  318. protected void onBeginPressed(java.awt.event.ActionEvent e)
  319. {
  320. this.goToImage(0);
  321. }
  322. @SuppressWarnings( {"UnusedDeclaration"})
  323. protected void onEndPressed(java.awt.event.ActionEvent e)
  324. {
  325. int maxIndex = this.imageSources.size() - 1;
  326. if (maxIndex < 0)
  327. return;
  328. this.goToImage(maxIndex);
  329. }
  330. @SuppressWarnings( {"UnusedDeclaration"})
  331. protected void onResizePressed(java.awt.event.ActionEvent e)
  332. {
  333. if (this.getAnnotation() == null)
  334. return;
  335. java.awt.Dimension preferredSize = this.getPreferredImageSize();
  336. if (preferredSize.equals(SMALL_IMAGE_PREFERRED_SIZE))
  337. {
  338. this.setPreferredImageSize(LARGE_IMAGE_PREFERRED_SIZE);
  339. SlideShowAnnotation slideShowAnnotation = (SlideShowAnnotation) this.getAnnotation();
  340. slideShowAnnotation.setSizeButtonState(SlideShowAnnotation.DECREASE);
  341. }
  342. else
  343. {
  344. this.setPreferredImageSize(SMALL_IMAGE_PREFERRED_SIZE);
  345. SlideShowAnnotation slideShowAnnotation = (SlideShowAnnotation) this.getAnnotation();
  346. slideShowAnnotation.setSizeButtonState(SlideShowAnnotation.INCREASE);
  347. }
  348. }
  349. //**************************************************************//
  350. //******************** Image Load Thread *********************//
  351. //**************************************************************//
  352. protected void retrieveAndSetImage(Object source, int index)
  353. {
  354. PowerOfTwoPaddedImage image = this.getImage(source);
  355. if (image != null)
  356. {
  357. this.doSetImage(image, index);
  358. return;
  359. }
  360. this.startImageRetrieval(source, index);
  361. }
  362. protected void doRetrieveAndSetImage(Object source, final int index)
  363. {
  364. javax.swing.SwingUtilities.invokeLater(new Runnable()
  365. {
  366. public void run()
  367. {
  368. if (updateTimer != null)
  369. {
  370. updateTimer.stop();
  371. }
  372. getAnnotation().setBusy(true);
  373. getWorldWindow().redraw();
  374. }
  375. });
  376. final PowerOfTwoPaddedImage image = this.readImage(source);
  377. this.putImage(source, image);
  378. javax.swing.SwingUtilities.invokeLater(new Runnable()
  379. {
  380. public void run()
  381. {
  382. doSetImage(image, index);
  383. getAnnotation().setBusy(false);
  384. getWorldWindow().redraw();
  385. if (updateTimer != null)
  386. {
  387. updateTimer.start();
  388. }
  389. }
  390. });
  391. }
  392. protected PowerOfTwoPaddedImage readImage(Object source)
  393. {
  394. try
  395. {
  396. if (source instanceof BufferedImage)
  397. {
  398. return PowerOfTwoPaddedImage.fromBufferedImage((BufferedImage) source);
  399. }
  400. else if (source instanceof String)
  401. {
  402. return PowerOfTwoPaddedImage.fromPath((String) source);
  403. }
  404. else if (source instanceof URL)
  405. {
  406. return PowerOfTwoPaddedImage.fromBufferedImage(ImageIO.read((URL) source));
  407. }
  408. else
  409. {
  410. String message = Logging.getMessage("generic.UnrecognizedSourceType", source);
  411. Logging.logger().severe(message);
  412. }
  413. }
  414. catch (IOException e)
  415. {
  416. String message = Logging.getMessage("generic.ExceptionAttemptingToReadFrom", source);
  417. Logging.logger().severe(message);
  418. }
  419. return null;
  420. }
  421. protected void startImageRetrieval(final Object source, final int index)
  422. {
  423. this.readThread = new Thread(new Runnable()
  424. {
  425. public void run()
  426. {
  427. doRetrieveAndSetImage(source, index);
  428. }
  429. });
  430. this.readThread.start();
  431. }
  432. protected void stopImageRetrieval()
  433. {
  434. if (this.readThread != null)
  435. {
  436. if (this.readThread.isAlive())
  437. {
  438. this.readThread.interrupt();
  439. }
  440. }
  441. this.readThread = null;
  442. }
  443. protected PowerOfTwoPaddedImage getImage(Object source)
  444. {
  445. return (PowerOfTwoPaddedImage) WorldWind.getMemoryCache(BUFFERED_IMAGE_CACHE_NAME).getObject(source);
  446. }
  447. protected boolean putImage(Object source, PowerOfTwoPaddedImage image)
  448. {
  449. long sizeInBytes = ImageUtil.computeSizeInBytes(image.getPowerOfTwoImage());
  450. MemoryCache cache = WorldWind.getMemoryCache(BUFFERED_IMAGE_CACHE_NAME);
  451. boolean addToCache = (sizeInBytes < cache.getCapacity());
  452. // If the image is too large for the cache, then do not add it to the cache.
  453. if (addToCache)
  454. {
  455. cache.add(source, image, sizeInBytes);
  456. }
  457. return addToCache;
  458. }
  459. //**************************************************************//
  460. //******************** Slideshow Update Timer *******************//
  461. //**************************************************************//
  462. protected boolean nextSlideShowImage()
  463. {
  464. if (this.getAnnotation() == null)
  465. return false;
  466. if (this.hasNextIndex())
  467. {
  468. int newIndex = this.getNextIndex();
  469. this.doGoToImage(newIndex);
  470. }
  471. return this.hasNextIndex();
  472. }
  473. protected void onSlideShowUpdate()
  474. {
  475. if (!this.nextSlideShowImage())
  476. {
  477. this.stopSlideShow();
  478. }
  479. }
  480. protected void startSlideShowUpdate()
  481. {
  482. this.updateTimer = new javax.swing.Timer((int) SLIDESHOW_UPDATE_DELAY_MILLIS,
  483. new java.awt.event.ActionListener()
  484. {
  485. public void actionPerformed(java.awt.event.ActionEvent actionEvent)
  486. {
  487. onSlideShowUpdate();
  488. }
  489. });
  490. // Coalesce timer events, so that an image load delay on the timer thread does not cause slide transition
  491. // events to bunch up.
  492. this.updateTimer.setCoalesce(true);
  493. this.updateTimer.start();
  494. }
  495. protected void stopSlideShowUpdate()
  496. {
  497. if (this.updateTimer != null)
  498. {
  499. this.updateTimer.stop();
  500. }
  501. this.updateTimer = null;
  502. }
  503. //**************************************************************//
  504. //******************** Utilities *****************************//
  505. //**************************************************************//
  506. protected String createTitle(Object imageSource)
  507. {
  508. String imageName = this.getImageName(imageSource);
  509. return (imageName != null) ? imageName : "";
  510. }
  511. protected String createPositionText(int position, int length)
  512. {
  513. if (length <= 1)
  514. return "";
  515. StringBuilder sb = new StringBuilder();
  516. sb.append(position + 1).append(" of ").append(length);
  517. return sb.toString();
  518. }
  519. protected String getImageName(Object imageSource)
  520. {
  521. if (imageSource == null)
  522. return null;
  523. String s = imageSource.toString();
  524. s = WWIO.stripTrailingSeparator(s);
  525. int index = s.lastIndexOf("/");
  526. if (index == -1)
  527. index = s.lastIndexOf("\\");
  528. if (index != -1 && index < s.length() - 1)
  529. {
  530. s = s.substring(index + 1, s.length());
  531. }
  532. return s;
  533. }
  534. }