// This file is part of Penn TotalRecall <http://memory.psych.upenn.edu/TotalRecall>. // // TotalRecall 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, version 3 only. // // TotalRecall 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 TotalRecall. If not, see <http://www.gnu.org/licenses/>. package components.waveform; import info.GUIConstants; import info.MyColors; import java.awt.AlphaComposite; import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JComponent; import javax.swing.SwingUtilities; import javax.swing.Timer; import behaviors.singleact.ReplayLast200MillisAction; /** * Application glass pane, used for drawing mouse feedback. * * @author Yuvi Masory */ public class MyGlassPane extends JComponent { private static MyGlassPane instance; private final AlphaComposite composite; private volatile boolean highlightMode; private volatile Point highlightSource; private volatile Point highlightDest; private volatile Rectangle highlightRect; private Timer timer; private volatile boolean flashMode; private int flashRectangleXPos; private int flashRectangleWidth; private final int flashWidth = (int)(GUIConstants.zoomlessPixelsPerSecond * (ReplayLast200MillisAction.duration / (double)1000)); private MyGlassPane() { composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25F); flashMode = false; highlightMode = false; highlightSource = new Point(); highlightDest = new Point(); highlightRect = new Rectangle(); } @Override protected void paintComponent(Graphics g) { if(highlightMode) { Graphics2D g2d = (Graphics2D)g; g2d.setComposite(composite); g2d.setColor(MyColors.mouseHighlightColor); g2d.fillRect((int)highlightRect.getX(), (int)highlightRect.getY(), (int)highlightRect.getWidth(), (int)highlightRect.getHeight()); } else if(flashMode) { Graphics2D g2d = (Graphics2D)g; g2d.setComposite(composite); g2d.setColor(MyColors.replay200MillisFlashColor); int yPos = (int)SwingUtilities.convertPoint(WaveformDisplay.getInstance(), -1, 0, this).getY(); g2d.fillRect(flashRectangleXPos, yPos, flashRectangleWidth, WaveformDisplay.height()); } else { setVisible(false); } } public void setHighlightMode(boolean flag) { highlightMode = flag; setVisible(flag); } public void setHighlightSource(Point sourcePoint, Component sourceComp) { highlightSource = SwingUtilities.convertPoint(sourceComp, sourcePoint, this); } public void setHighlightDest(Point destPoint, Component sourceComp) { highlightDest = SwingUtilities.convertPoint(sourceComp, destPoint, this); udpateHighlightRect(); } private void udpateHighlightRect() { int xSource = (int) (highlightSource.getX() < highlightDest.getX() ? highlightSource.getX() : highlightDest.getX()); int ySource = (int) SwingUtilities.convertPoint(WaveformDisplay.getInstance(), 0, 0, this).getY(); int width = (int) Math.abs(highlightSource.getX() - highlightDest.getX()); int height = WaveformDisplay.height(); Rectangle naiveBounds = new Rectangle(xSource, ySource, width, height); Rectangle waveformBounds = SwingUtilities.convertRectangle(WaveformDisplay.getInstance(), WaveformDisplay.getInstance().getVisibleRect(), this); highlightRect = naiveBounds.intersection(waveformBounds); } public int[] getHighlightBounds() { return new int[] {(int) highlightSource.getX(), (int) highlightDest.getX()}; } public boolean isHighlightMode() { return highlightMode; } public void flashRectangle() { if((timer != null && timer.isRunning()) == false) { this.flashRectangleXPos = (int)SwingUtilities.convertPoint(WaveformDisplay.getInstance(), WaveformDisplay.getProgressBarXPos() - flashWidth, -1, this).getX(); this.flashRectangleWidth = flashWidth; flashMode = true; setVisible(true); repaint(); timer = new Timer(ReplayLast200MillisAction.duration, new StopFlashListener()); timer.setRepeats(false); timer.start(); } } private final class StopFlashListener implements ActionListener { public void actionPerformed(ActionEvent e) { flashMode = false; repaint(); } } public static MyGlassPane getInstance() { if(instance == null) { instance = new MyGlassPane(); } return instance; } }