/* * Copyright (C) 2014 Alec Dhuse * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package co.foldingmap.map.visualization; import co.foldingmap.GUISupport.Updateable; import co.foldingmap.ResourceHelper; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.RoundRectangle2D; import java.util.ArrayList; import javax.swing.ImageIcon; /** * * @author Alec */ public class TimeSpanControl extends Thread { protected ArrayList<Updateable> updateables; protected boolean started; protected Color markerFill, markerOutline; protected float x, y, height, width; protected float stopInterval, trackX, trackY; protected GeneralPath play; protected ImageIcon configImage, pauseImage, playImage; protected int position, waitTime; protected ResourceHelper resourceHelper; protected RoundRectangle2D playTrack, rectangle; protected RoundRectangle2D playButton, configButton; protected RoundRectangle2D positionMarker; protected VisualizationLayer layer; public TimeSpanControl(VisualizationLayer layer) { this.layer = layer; this.position = 0; this.markerFill = Color.LIGHT_GRAY; this.markerOutline = new Color(255, 255, 255, 200); this.resourceHelper = ResourceHelper.getInstance(); this.waitTime = layer.getDisplayInterval(); this.updateables = new ArrayList<Updateable>(); configImage = resourceHelper.getImage("gear.png"); pauseImage = resourceHelper.getImage("pause.png"); playImage = resourceHelper.getImage("play.png"); } /** * Adds an updateable to be called when a setting of this control is changed. * * @param updateable */ public void addUpdateable(Updateable updateable) { updateables.add(updateable); } /** * Returns if a given (x, y) coordinate is contained within the drawing of * this control. * * @param px * @param py * @return */ public boolean containsPoint(float px, float py) { return rectangle.contains(px, py); } /** * Draws the Time Scale for the MapPanel. * * @param g2 * @param height * @param width */ public void draw(Graphics2D g2, float panelHeight, float panelWidth) { BasicStroke stroke; float centerWidth, currentLineX, positionX; int numberOfStops, trackWidth; Line2D stopLines[]; try { numberOfStops = layer.getNumberOfSeries(); stopLines = new Line2D[numberOfStops]; stroke = new BasicStroke(1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); centerWidth = panelWidth / 2.0f; x = centerWidth - 200; y = panelHeight - 50; height = 40; width = 400; trackWidth = 300; stopInterval = (trackWidth / (numberOfStops - 1f)); //find the distance between stop lines. trackX = (centerWidth - 150); trackY = (y + 17); rectangle = new RoundRectangle2D.Float(x, y, width, height, 20, 20); playTrack = new RoundRectangle2D.Float(trackX, trackY, trackWidth, 5, 5, 5); playButton = new RoundRectangle2D.Float((x + 10), (y + 10), 20, 20, 8, 8); play = new GeneralPath(); configButton = new RoundRectangle2D.Float((x + width - 30), (y + 10), 20, 20, 8, 8); //create play image play.moveTo((x + 14), (y + 14)); play.lineTo((x + 14), (y + 28)); play.lineTo((x + 28), (y + 20)); play.lineTo((x + 14), (y + 14)); g2.setStroke(stroke); g2.setColor(new Color(68, 68, 68, 180)); g2.fill(rectangle); g2.setColor(Color.WHITE); g2.draw(playTrack); g2.draw(playButton); g2.draw(configButton); g2.drawImage(configImage.getImage(), (int) (x + width - 30), (int) (y + 10), null); if (started) { g2.drawImage(pauseImage.getImage(), (int) (x + 11), (int) (y + 11), null); } else { g2.fill(play); } //create stop lines //g2.setColor(new Color(255, 255, 255, 200)); for (int i = 1; i < (numberOfStops - 1); i++) { currentLineX = trackX + (i * stopInterval); stopLines[i] = new Line2D.Float(currentLineX, trackY, currentLineX, trackY + 5); //g2.draw(stopLines[i]); } //draw posistion marker positionX = (trackX + (position * stopInterval)) - 4f; positionMarker = new RoundRectangle2D.Float(positionX, trackY - 2, 9, 8, 2, 2); g2.setColor(markerFill); g2.fill(positionMarker); g2.setColor(markerOutline); g2.draw(positionMarker); } catch (Exception e) { System.err.println("Error in TimeSpanControl.draw(Graphics2D, float, float) - " + e); } } public int getPosition() { return position; } /** * Increments by one, and loops back to zero when the maximum is reached. */ public void incrementPosition() { if (position < (layer.getNumberOfSeries() - 1)) { position++; } else { position = 0; } } /** * Pass mouse clicks in to enable functionality. * * @param range */ public void mouseClicked(double clickX, double clickY) { double trackPos; int stopPos; if (playButton.contains(clickX, clickY)) { if (started) { started = false; } else { started = true; if (!this.isAlive()) this.start(); } } else if (configButton.contains(clickX, clickY)) { } else if (playTrack.contains(clickX, clickY)) { trackPos = (clickX - trackX); stopPos = (int) (trackPos / stopInterval); position = stopPos; } } @Override public void run() { try { while (started) { incrementPosition(); for (Updateable u: updateables) u.update(); this.sleep(waitTime); } this.interrupt(); } catch (Exception e) { System.err.println("Error in TimeSpanControl.run() - " + e); } } }