/* ZoomSignalPlot.java created 2007-10-15 * */ package org.signalml.app.view.signal; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.font.TextLayout; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import javax.swing.JComponent; import javax.swing.border.LineBorder; import org.signalml.app.util.IconUtils; import org.signalml.domain.signal.samplesource.MultichannelSampleSource; import org.signalml.util.Util; /** ZoomSignalPlot * * * @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. */ public class ZoomSignalPlot extends JComponent { private static final long serialVersionUID = 1L; private SignalPlot plot; private Point focusPoint; private int channel; private float factor = 2F; private double[] samples = null; private GeneralPath generalPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD,50000); private final static Image zoomImage = IconUtils.loadClassPathImage("org/signalml/app/icon/zoom.png"); public ZoomSignalPlot() { setBorder(new LineBorder(Color.LIGHT_GRAY,3,false)); setCursor(IconUtils.getEmptyCursor()); } @Override protected void paintComponent(Graphics gOrig) { if (plot == null || focusPoint == null) { return; } Graphics2D g = (Graphics2D) gOrig; Dimension size = getSize(); Insets insets = getInsets(); g.setColor(Color.WHITE); g.fillRect(0,0,size.width,size.height); size.width -= (insets.left + insets.right); size.height -= (insets.top + insets.bottom); g.setColor(Color.BLACK); MultichannelSampleSource sampleSource = plot.getSignalOutput(); Point2D.Float signalFocus = plot.toSignalSpace(focusPoint); int pixelPerChannel = plot.getPixelPerChannel(); int invisibleChannels = plot.getInvisibleChannelsBeforeChannel(channel); int channelCenter = (channel - invisibleChannels)*pixelPerChannel + pixelPerChannel/2; // double length = (((size.width) / plot.getPixelPerSecond()) / factor); double minTime = signalFocus.x - length/2; double maxTime = minTime + length; float samplingFrequency = plot.getSamplingFrequency(); int firstSample = (int) Math.max(0, Math.floor(minTime * samplingFrequency)); int lastSample = (int) Math.min(plot.getMaxSampleCount()-1, Math.ceil(maxTime * samplingFrequency)); int sampleCnt = lastSample - firstSample; if (samples == null || samples.length < sampleCnt) { samples = new double[sampleCnt]; } if (channel >= sampleSource.getChannelCount()) return; try { sampleSource.getSamples(channel, samples, firstSample, sampleCnt, 0); } catch (RuntimeException ex) { setVisible(false); throw ex; } int i; double x, y; double pixelPerValue = plot.getPixelPerValue(channel) * factor; double timeZoomFactor = plot.getTimeZoomFactor() * factor; int centerOffset = Math.round((focusPoint.y - channelCenter) * factor); int leftOffset; if (minTime < 0) { leftOffset = insets.left + size.width - (int)((sampleCnt-1) * timeZoomFactor); } else { leftOffset = insets.left; } x = leftOffset; y = size.height/2 - samples[0] * pixelPerValue - centerOffset; int ix, iy, lastix, lastiy; ix = (int) StrictMath.floor(x+0.5); iy = (int) StrictMath.floor(y+0.5); generalPath.reset(); generalPath.moveTo(x, y); lastix = ix; lastiy = iy; for (i=1; i<sampleCnt; i++) { y = size.height/2 - samples[i] * pixelPerValue - centerOffset; x = leftOffset + timeZoomFactor * i; ix = (int) StrictMath.floor(x+0.5); iy = (int) StrictMath.floor(y+0.5); if (lastix != ix || lastiy != iy) { generalPath.lineTo(ix, iy); } lastix = ix; lastiy = iy; } g.draw(generalPath); g.drawImage(zoomImage,insets.left+1,insets.top+1,null); String label = Float.toString(factor) + "x " + sampleSource.getLabel(channel); TextLayout textLayout = new TextLayout(label,g.getFont(),g.getFontRenderContext()); Point labelPoint = new Point(insets.left+1+zoomImage.getWidth(null)+3, insets.top+1+zoomImage.getHeight(null)/2); Rectangle labelRect = textLayout.getPixelBounds( null, labelPoint.x, labelPoint.y ); labelPoint.translate(0, labelRect.height/2); labelRect.translate(0, labelRect.height/2); g.setColor(Color.WHITE); g.fill(labelRect); g.setColor(Color.BLACK); textLayout.draw( g, labelPoint.x, labelPoint.y ); } @Override public boolean isDoubleBuffered() { return true; } @Override public boolean isOpaque() { return true; } @Override public Dimension getPreferredSize() { Dimension size = super.getPreferredSize(); if (size != null) { return size; } return getMinimumSize(); } @Override public Dimension getMinimumSize() { return new Dimension(100,100); } @Override public Dimension getMaximumSize() { return getPreferredSize(); } public Point getFocusPoint() { return focusPoint; } public void setFocusPoint(Point focusPoint) { if (!Util.equalsWithNulls(this.focusPoint, focusPoint)) { this.focusPoint = focusPoint; repaint(); } } public int getChannel() { return channel; } public void setChannel(int channel) { if (this.channel != channel) { this.channel = channel; repaint(); } } public SignalPlot getPlot() { return plot; } public void setPlot(SignalPlot plot) { if (this.plot != plot) { this.plot = plot; repaint(); } } public void setParameters(SignalPlot plot, Point focusPoint, int channel) { this.plot = plot; this.focusPoint = focusPoint; this.channel = channel; repaint(); } public void setParameters(Point focusPoint, int channel) { this.focusPoint = focusPoint; this.channel = channel; repaint(); } public float getFactor() { return factor; } public void setFactor(float factor) { if (this.factor != factor) { this.factor = factor; repaint(); } } }