package com.isti.traceview.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.event.MouseInputListener;
import org.apache.log4j.Logger;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.data.RangeType;
import org.jfree.ui.RectangleEdge;
import com.isti.traceview.TraceViewException;
import com.isti.traceview.common.IEvent;
import com.isti.traceview.common.TimeInterval;
import com.isti.traceview.data.EventWrapper;
import com.isti.traceview.data.PlotData;
import com.isti.traceview.data.PlotDataPoint;
import com.isti.traceview.data.PlotDataProvider;
import com.isti.traceview.data.Segment;
import com.isti.traceview.processing.RemoveGainException;
/**
* Graphics panel to plot several traces in the same time and values coordinate axis on a single
* panel. Has auxiliary panel on the left side and big graph panel to plot data on the right side.
*
* @author Max Kokoulin
*/
public class ChannelView extends JPanel implements Comparable<Object>, Observer {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(ChannelView.class); // @jve:decl-index=0:
public static boolean tooltipVisible = false;
public static final int defaultInfoPanelWidth = 80;
protected static int currentSelectionNumber = 0;
private List<String> channelNames = new ArrayList<String>();
private List<PlotDataProvider> plotDataProviders = null; // @jve:decl-index=0:
List<PlotData> graphs = null;
int height = 0;
int maxValueAllChannels = Integer.MIN_VALUE;
int minValueAllChannels = Integer.MAX_VALUE;
double meanValue = Double.POSITIVE_INFINITY;
private InfoPanel infoPanel = null;
private GraphAreaPanel graphAreaPanel = null;
private GraphPanel graphPanel = null;
private int mousePressX;
private int mousePressY;
private NumberAxis axis = null; // @jve:decl-index=0:
private int lastClickedY = Integer.MIN_VALUE; // to
private int lastClickedX = Integer.MIN_VALUE;
private List<MarkPosition> markPositions = null;
private int selectionNumber = 0;
//private boolean isDrawSelectionCheckBox = true;
/**
* Mouse adapter for GraphAreaPanel - internal panel containing graphs
*/
private IMouseAdapter mouseAdapter = null;
public ChannelView(List<PlotDataProvider> channels, int infoPanelWidth, boolean isDrawSelectionCheckBox, Color graphAreaBgColor, Color infoAreaBgColor) {
super();
String names = "";
for (PlotDataProvider channel: channels) {
names = names + channel.toString() + ";";
channelNames.add(channel.toString());
}
logger.debug("ChannelView created for list: " + names);
initialize(infoPanelWidth, isDrawSelectionCheckBox, graphAreaBgColor, infoAreaBgColor);
setPlotDataProviders(channels);
}
public ChannelView(PlotDataProvider channel, int infoPanelWidth, boolean isDrawSelectionCheckBox, Color graphAreaBgColor, Color infoAreaBgColor) {
super();
logger.debug("ChannelView created for " + channel.toString());
initialize(infoPanelWidth, isDrawSelectionCheckBox, graphAreaBgColor, infoAreaBgColor);
List<PlotDataProvider> lst = new ArrayList<PlotDataProvider>();
lst.add(channel);
setPlotDataProviders(lst);
}
public ChannelView(List<PlotDataProvider> channels) {
this(channels, defaultInfoPanelWidth, true, null, null);
}
public ChannelView(PlotDataProvider channel) {
this(channel, defaultInfoPanelWidth, true, null, null);
}
public ChannelView() {
this(new ArrayList<PlotDataProvider>(), defaultInfoPanelWidth, true, null, null);
}
private void initialize(int infoPanelWidth, boolean isDrawSelectionCheckBox, Color graphAreaBgColor, Color infoAreaBgColor) {
ToolTipManager.sharedInstance().unregisterComponent(this);
axis = new NumberAxis();
axis.setRangeType(RangeType.FULL);
this.setLayout(new BorderLayout());
// setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
this.add(getInfoPanel(infoPanelWidth, isDrawSelectionCheckBox, infoAreaBgColor), BorderLayout.WEST);
this.add(getGraphAreaPanel(graphAreaBgColor), BorderLayout.CENTER);
markPositions = new ArrayList<MarkPosition>();
}
/**
* Unchecks the NonPrintableCheckbox in the ChannelView.
*/
public void clearCheckBox(){
this.infoPanel.selected.setSelected(false);
}
/**
* Sets mouse adapter defines mouse action inside this ChannelView
*
* @param ma the new mouse adapter
*/
public void setMouseAdapter(IMouseAdapter ma) {
mouseAdapter = ma;
}
/**
* Gets current mouse adapter defines mouse action inside this ChannelView
*/
public IMouseAdapter getMouseAdapter() {
return mouseAdapter;
}
/**
* @return value coordinate of last clicked point on this ChannelView (in pixels inside graph
* area panel)
*/
public int getLastClickedY() {
return lastClickedY;
}
/**
* @return time coordinate of last clicked point on this ChannelView (in pixels inside graph
* area panel)
*/
public int getLastClickedX() {
return lastClickedX;
}
/**
* @return width of area graph itself occupy, without left auxiliary panel
*/
public int getGraphAreaWidth() {
return graphAreaPanel.width;
}
/**
* @param x
* time coordinate of point (in pixels inside graph area panel)
* @return Set of events in this point
*/
public Set<IEvent> getEvents(int x) {
Set<EventWrapper> eventWrappers = graphAreaPanel.getEvents(x);
if (eventWrappers == null)
return null;
Set<IEvent> ret = new HashSet<IEvent>();
for (EventWrapper eventWrapper: eventWrappers) {
ret.add(eventWrapper.getEvent());
}
return ret;
}
/**
* @return Necessary count of data point in graph to draw inside this panel
*/
public int getPointCount() {
return graphAreaPanel.getWidth();
}
public void update(Observable observable, Object arg) {
logger.debug(this + ": update request from " + observable);
if (arg instanceof TimeInterval) {
//TimeInterval ti = (TimeInterval) arg;
//logger.info(this + " updating for range " + ti + " due to request from observer: '" + observable.getClass().getName() + "'");
graphAreaPanel.repaint();
}
}
/**
* Sets graph panel contains this ChannelView
*
* @param gp The new graph panel
*/
public void setGraphPanel(GraphPanel gp) {
this.graphPanel = gp;
}
/**
* Gets graph panel contains this ChannelView
*/
public GraphPanel getGraphPanel() {
return graphPanel;
}
/**
* @return time coordinate of last pressed point on this ChannelView (in pixels inside graph
* area panel)
*/
public int getMousePressX() {
return mousePressX;
}
/**
* @return value coordinate of last pressed point on this ChannelView (in pixels inside graph
* area panel)
*/
public int getMousePressY() {
return mousePressY;
}
/**
* Adds marker to screen. Marker image loaded from markPosition.gif file placed in the jar.
* Parameters are coordinates of image's center.
*
* @param time
* time position (in internal Java time representation)
* @param value
* value position
*/
public void addMarkPosition(long time, double value) {
markPositions.add(new MarkPosition(time, value));
}
/**
* Clears all markers
*/
public void clearMarkPositions() {
markPositions.clear();
}
/**
* Getter of the property <tt>channelNames</tt>
*
* @return the list of channelNames drawn in this ChannelView
*/
public List<String> getChannelNames() {
return channelNames;
}
/**
* Getter of the property <tt>plotDataProviders</tt>
*
* @return the list of PlotDataProviders drawn in this ChannelView.
*/
public List<PlotDataProvider> getPlotDataProviders() {
return plotDataProviders;
}
/**
* @return pixelized graph data drawn in this ChannelView.
*/
public List<PlotData> getPlotData() {
return graphs;
}
/**
* Setter of the property <tt>plotDataProviders</tt>
*
* @param channels
* List of plotDataProviders to draw inside this ChannelView.
*/
public void setPlotDataProviders(List<PlotDataProvider> channels) {
if (plotDataProviders != null) {
for (PlotDataProvider channel: plotDataProviders) {
channel.deleteObserver(this);
}
}
plotDataProviders = channels;
for (PlotDataProvider channel: plotDataProviders) {
channel.addObserver(this);
logger.debug("Observer for " + channel.toString() + " added");
if (channel.getMaxValue() > maxValueAllChannels) {
maxValueAllChannels = channel.getMaxValue();
}
if (channel.getMinValue() < minValueAllChannels) {
minValueAllChannels = channel.getMinValue();
}
}
lastClickedY = Integer.MIN_VALUE;
}
/**
* Return time interval of loaded data
*/
public TimeInterval getLoadedTimeRange() {
TimeInterval ret = null;
for (PlotDataProvider channel: plotDataProviders) {
if (ret == null) {
ret = channel.getTimeRange();
} else {
ret = TimeInterval.getAggregate(ret, channel.getTimeRange());
}
}
return ret;
}
/**
* Prepares pixelized data for PlotDataProviders to draw. Should be called before paint.
*/
public synchronized String updateData() {
int width = graphAreaPanel.getWidth();// - graphAreaPanel.getInsets().left -
// graphAreaPanel.getInsets().right;
logger.debug("Updating data " + this + "Width = " + width);
graphs = new ArrayList<PlotData>();
List<String> errorChannels = new ArrayList<String>();
for (PlotDataProvider channel: plotDataProviders) {
// lg.debug("processing channel: " + channel);
PlotData data = null;
try {
data = channel.getPlotData(graphPanel.getTimeRange(), width, graphPanel.getFilter(), graphPanel.getRemoveGain(), graphPanel.getColorMode());
} catch (TraceViewException e) {
channel.setRotation(null);
try {
errorChannels.add(channel.getNetworkName()+"/"+channel.getStation()+"/"+channel.getLocationName()+"/"+channel.getChannelName() + " - " + e.getMessage());
data = channel.getPlotData(graphPanel.getTimeRange(), width, graphPanel.getFilter(), graphPanel.getRemoveGain(), graphPanel.getColorMode());
} catch (TraceViewException | RemoveGainException e1) {
// do nothing
logger.error("TraceViewException:", e1);
}
} catch (RemoveGainException e) {
try {
errorChannels.add(channel.getNetworkName()+"/"+channel.getStation()+"/"+channel.getLocationName()+"/"+channel.getChannelName() + " - " + e.getMessage());
data = channel.getPlotData(graphPanel.getTimeRange(), width, graphPanel.getFilter(), null, graphPanel.getColorMode());
} catch (TraceViewException | RemoveGainException e1) {
// do nothing
logger.error("TraceViewException:", e1);
}
}
graphs.add(data);
meanValue = data.getMeanValue();
}
Collections.sort(graphs);
if(errorChannels.size() > 0)
return errorChannels.get(0);
else
return "";
}
/**
* Customized method to paint events.
*/
public void paintCustomEvent(Graphics g, EventWrapper eventWrapper, int x, int ymax, int ymin) {
}
/**
* This method initializes infoPanel
*
* @return javax.swing.JPanel
*/
private InfoPanel getInfoPanel(int infoPanelWidth, boolean isDrawSelectionCheckBox, Color infoAreaBgColor) {
if (infoPanel == null) {
infoPanel = new InfoPanel(this, infoPanelWidth, isDrawSelectionCheckBox, infoAreaBgColor);
}
return infoPanel;
}
/**
* This method initializes graphAreaPanel
*
* @return javax.swing.JPanel
*/
private GraphAreaPanel getGraphAreaPanel(Color graphAreaBgColor) {
if (graphAreaPanel == null) {
graphAreaPanel = new GraphAreaPanel(this, graphAreaBgColor);
}
return graphAreaPanel;
}
/**
* Gets string representation of ChannelView in the debug purposes
*/
public String toString() {
String ret = "";
for (PlotDataProvider channel: plotDataProviders) {
ret = ret + channel.getStation().getName() + "/" + channel.getChannelName() + " ";
}
return "ChannelView: " + ret;
}
/**
* @return flag if this ChannelView selected(by checkbox on info panel)
*/
public boolean isSelected() {
return infoPanel.isSelected();
}
/**
* Adds MouseListener to internal graph panel
*/
public void addMouseListener(MouseListener l) {
graphAreaPanel.addMouseListener(l);
}
/**
* Adds MouseMotionListener to internal graph panel
*/
public void addMouseMotionListener(MouseMotionListener l) {
graphAreaPanel.addMouseMotionListener(l);
}
/**
* Sets cursor for internal graph panel
*/
public void setCursor(Cursor cursor) {
graphAreaPanel.setCursor(cursor);
}
/**
* When user selects several ChannelViews on the {@link GraphPanel}, each ChannelView stores
* his sequential number in this selection. If GraphPanel will be set to Selection mode,
* ChannelView will be shown in the order of their selectionNumbers
*
* @return sequential number during selection
*/
public int getSelectionNumber() {
return selectionNumber;
}
/**
* This method should be called after selection mode changing in GraphPanel
*/
public void selectionPerformed() {
}
/**
* Comparator by selection number
*/
public int compareTo(Object o) {
if (o instanceof ChannelView) {
ChannelView c = (ChannelView) o;
return new Integer(getSelectionNumber()).compareTo(new Integer(c.getSelectionNumber()));
} else {
return 1;
}
}
/**
* Left panel for auxiliary information: selection checkbox, axis painting etc
*/
class InfoPanel extends JPanel implements ItemListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private NonPrintableCheckBox selected = null;
private ChannelView channelView = null;
public InfoPanel(ChannelView cv, int infoPanelWidth, boolean isDrawSelectionCheckBox, Color infoAreaBgColor) {
super();
if(infoAreaBgColor!=null){
setBackground(infoAreaBgColor);
}
this.channelView = cv;
setPreferredSize(new Dimension(infoPanelWidth, 0));
setBorder(BorderFactory.createEtchedBorder());
setLayout(new FlowLayout(FlowLayout.LEFT, 2, 2));
if(isDrawSelectionCheckBox){
add(getSelected());
}
}
public boolean isSelected() {
return selected.isSelected();
}
/**
* This method initializes selected
*
* @return Customized checkbox for ChannelView selection which drawn on screen and don't
* drawn during rendering for print
*/
private NonPrintableCheckBox getSelected() {
if (selected == null) {
selected = new NonPrintableCheckBox();
selected.addItemListener(this);
}
return selected;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
axis.draw((Graphics2D) g, getWidth() - 5, new Rectangle(0, 0, getWidth(), getHeight()), new Rectangle(0, 0, getWidth(), getHeight()),
RectangleEdge.LEFT, null);
}
private class NonPrintableCheckBox extends JCheckBox {
/**
*
*/
private static final long serialVersionUID = 1L;
public void paint(Graphics g) {
// if(!isPaintingForPrint()){ //works only in jre 1.6
super.paint(g);
// }
}
}
/** Listens to the check box. */
public void itemStateChanged(ItemEvent e) {
if (!(graphPanel.getSelectState() || graphPanel.getOverlayState())) {
if (e.getStateChange() == ItemEvent.DESELECTED) {
selectionNumber = 0;
graphPanel.getSelectedChannelShowSet().remove(channelView);
} else if (e.getStateChange() == ItemEvent.SELECTED) {
graphPanel.getSelectedChannelShowSet().add(channelView);
currentSelectionNumber++;
selectionNumber = currentSelectionNumber;
}
}
selectionPerformed();
}
}
/**
* Big right panel for graphs drawing
*/
class GraphAreaPanel extends JPanel implements MouseInputListener {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Panel height in pixel
*/
int height;
/**
* Panel width in pixel
*/
int width;
/**
* Apmlitude of contained graph - precomputed value to increase speed of paintComponent()
* calculations
*/
int amp;
ChannelView cv = null;
private int button = MouseEvent.NOBUTTON;
private int fontHeight = 0;
public GraphAreaPanel(ChannelView cv, Color graphAreaBgColor) {
super();
this.cv = cv;
if(graphAreaBgColor != null){
setBackground(graphAreaBgColor);
}
setLayout(new GridBagLayout());
setBorder(BorderFactory.createEtchedBorder());
addMouseListener(this);
addMouseMotionListener(this);
setToolTipText("YYY");
}
public void paint(Graphics g) {
logger.debug("Repainting " + this);
super.paint(g);
// maxValue = Integer.MIN_VALUE;
// minValue = Integer.MAX_VALUE;
height = this.getHeight();
width = this.getWidth();
IScaleModeState scaleMode = graphPanel.getScaleMode();
IMeanState meanState = graphPanel.getMeanState();
IOffsetState offsetState = graphPanel.getOffsetState();
scaleMode.init(graphs, (graphPanel.getOverlayState() == true) || (graphPanel.getSelectState() == true) ? graphPanel
.getCurrentChannelShowSet() : graphPanel.getChannelShowSet(), graphPanel.getTimeRange(), meanState, height);
//lg.debug("scaleMode Initialized:" + scaleMode.getStateName() + scaleMode.getMaxValue() + scaleMode.getMinValue());
if (scaleMode.getMinValue() != Double.POSITIVE_INFINITY && scaleMode.getMaxValue() != Double.NEGATIVE_INFINITY) {
axis.setRange(scaleMode.getMinValue(), scaleMode.getMaxValue());
}
//Offset step is 1/20 of graph height
offsetState.setShift((scaleMode.getMaxValue() - scaleMode.getMinValue()) / 20);
logger.debug("Set ChannelView " + this + " boundaries: " + scaleMode.getMaxValue() + "-" + scaleMode.getMinValue());
// Graph's number, used to separate graphs then overlay mode is activated
int graphNum = 0;
Color segmentColor = null;
if (graphPanel.initialPaint) {
System.out.print("...");
}
for (PlotData data: graphs) {
int i = 0;
// strokes for previous pixel
List<Stroke> yprev = new ArrayList<Stroke>();
for (PlotDataPoint[] points: data.getPixels()) {
int j = 0;
for (PlotDataPoint point: points) {
//add previous stroke to list if list has unsuffisient length
if(yprev.size()==j || yprev.get(j)==null){
yprev.add(j, new Stroke());
}
Stroke current = new Stroke();
if (point.getSegmentNumber() >= 0) {
segmentColor = graphPanel.getColorMode().getSegmentColor(graphNum + point.getSegmentNumber(), graphNum + point.getRawDataProviderNumber(), graphNum + point.getContinueAreaNumber(), data.getTraceColor());
if (point.getSegmentNumber() == 0 && data.getLabelColor() == null) {
data.setLabelColor(segmentColor);
}
g.setColor(segmentColor);
// reinit previous stroke if color differs
if ((yprev.get(j).color!=null) && (yprev.get(j).color != segmentColor)){
yprev.set(j, new Stroke());
}
current.color = segmentColor;
current.top = scaleMode.getY(meanState.getValue(offsetState.getValue(point.getTop(), point.getSegmentNumber()), data.getMeanValue()));
current.bottom = scaleMode.getY(meanState.getValue(offsetState.getValue(point.getBottom(), point.getSegmentNumber()), data.getMeanValue()));
//lg.debug("Drawing pixel " + j + ": " + point.getTop() + "-" + point.getBottom() + ", " + current);
g.drawLine(i, current.top, i, current.bottom);
if (i > 0) {
// fill vertical gaps
if (current.bottom < yprev.get(j).top) {
//lg.debug("Fill gap at top: " + yprev.get(j).top + "-" + current.bottom);
g.drawLine(i - 1, yprev.get(j).top, i, current.bottom);
}
if (current.top > yprev.get(j).bottom) {
//lg.debug("Fill gap at bottom: " + yprev.get(j).bottom + "-" + current.top);
g.drawLine(i - 1, yprev.get(j).bottom, i, current.top);
}
}
yprev.set(j, current);
} else {
//we have gap, set previous values to it's default
yprev.set(j, new Stroke());
}
// drawing events
//long currentTime = getTime(i);
for (EventWrapper eventWrapper: point.getEvents()) {
logger.debug("drawing event front");
g.setColor(eventWrapper.getEvent().getColor());
if (eventWrapper.getEvent().getType().equals("ARRIVAL") && graphPanel.getPhaseState()) {
// drawing phases
if (graphPanel.getSelectedEarthquakes().contains(eventWrapper.getEvent().getParameterValue("EARTHQUAKE"))
&& graphPanel.getSelectedPhases().contains(eventWrapper.getEvent().getParameterValue("PHASE"))) {
g.drawLine(i, getHeight(), i, 0);
g.drawString((String) eventWrapper.getEvent().getParameterValue("PHASE"), i + 2, getHeight() - 5);
}
} else if (eventWrapper.getEvent().getType().equals("PICK") && graphPanel.getPickState()) {
// drawing picks
g.drawLine(i, getHeight(), i, 0);
Polygon p = new Polygon();
p.addPoint(i, 0);
p.addPoint(i + 4, 4);
p.addPoint(i, 8);
g.fillPolygon(p);
} else {
paintCustomEvent(g, eventWrapper, i, current.top, current.bottom);
g.setColor(segmentColor);
}
}
j++;
}
while(j<yprev.size()){
yprev.set(j, new Stroke());
j++;
}
i++;
}
graphNum++;
}
if (plotDataProviders != null) {
logger.debug("drawing channel labels");
g.setFont(GraphPanel.getAxisFont());
fontHeight = g.getFontMetrics().getHeight();
int i = 1;
for (PlotData data: graphs) {
g.setColor(data.getLabelColor());
g.drawString(data.getLabel() + (plotDataProviders.get(i-1).isRotated() ? " (ROT "+plotDataProviders.get(i-1).getRotation().getRotationAngleText()+")" : ""),
(plotDataProviders.get(i-1).isRotated() ? getWidth() - 150 : getWidth() - 120), i++ * fontHeight);
}
// drawing Y axis labels
g.setColor(Color.BLACK);
if (scaleMode.getMaxValue() != Double.POSITIVE_INFINITY && scaleMode.getMaxValue() != Double.NEGATIVE_INFINITY
&& !Double.isInfinite(scaleMode.getMinValue())) {
g.drawString(new Double(scaleMode.getMaxValue()).toString(), 10, fontHeight);
}
if (scaleMode.getMinValue() != Double.POSITIVE_INFINITY && scaleMode.getMinValue() != Double.NEGATIVE_INFINITY
&& !Double.isInfinite(scaleMode.getMinValue())) {
g.drawString(new Double(scaleMode.getMinValue()).toString(), 10, getHeight() - 10);
}
// drawing marks
for (MarkPosition mp: markPositions) {
Image image = graphPanel.getMarkPositionImage();
g.drawImage(image, graphPanel.getXposition(mp.getTime()) - image.getHeight(this) / 2, graphPanel.getScaleMode().getY(
mp.getValue())
- image.getHeight(this) / 2, this);
}
}
logger.debug("Repainting end " + this);
}
/**
* Computes trace time value
*
* @param x
* screen panel coordinate
* @return time value in internal Java format
*/
public long getTime(int x) {
TimeInterval ti = graphPanel.getTimeRange();
return new Double(ti.getStart() + x * new Double(ti.getDuration())/ getWidth()).longValue();
}
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
graphPanel.cvMouseMoved = true;
if ((button != MouseEvent.NOBUTTON) && (e.isControlDown() || e.isShiftDown())) {
mouseDragged(e);
} else {
if (mouseAdapter != null) {
mouseAdapter.mouseMoved(x, y, cv);
}
graphPanel.dispatchEvent(SwingUtilities.convertMouseEvent(this, e, graphPanel));
}
}
public void mouseDragged(MouseEvent e) {
if (mouseAdapter != null) {
mouseAdapter.mouseDragged(e.getX(), e.getY(), cv);
}
graphPanel.dispatchEvent(SwingUtilities.convertMouseEvent(this, e, graphPanel));
}
public void mouseClicked(MouseEvent e) {
int clickedX = e.getX();
int clickedY = e.getY();
if (e.getButton() == MouseEvent.BUTTON1) {
if (mouseAdapter != null) {
mouseAdapter.mouseClickedButton1(clickedX, clickedY, cv);
}
lastClickedY = clickedY;
lastClickedX = clickedX;
} else if (e.getButton() == MouseEvent.BUTTON3) {
if (mouseAdapter != null) {
mouseAdapter.mouseClickedButton3(clickedX, clickedY, cv);
}
}
graphPanel.dispatchEvent(SwingUtilities.convertMouseEvent(this, e, graphPanel));
}
public void mouseEntered(MouseEvent e) {
graphPanel.cvMouseEntered(e);
}
public void mouseExited(MouseEvent e) {
graphPanel.cvMouseExited(e);
}
public void mousePressed(MouseEvent e) {
mousePressX = e.getX();
mousePressY = e.getY();
graphPanel.getScaleMode().init(
graphs,
(graphPanel.getOverlayState() == true) || (graphPanel.getSelectState() == true) ? graphPanel.getCurrentChannelShowSet()
: graphPanel.getChannelShowSet(), graphPanel.getTimeRange(), graphPanel.getMeanState(), getHeight());
// one-button mouse Mac OSX behaviour emulation
if (e.getButton() == MouseEvent.BUTTON1) {
if (e.isShiftDown()) {
button = MouseEvent.BUTTON2;
} else if (e.isControlDown()) {
button = MouseEvent.BUTTON3;
} else {
button = MouseEvent.BUTTON1;
}
} else {
button = e.getButton();
}
graphPanel.dispatchEvent(SwingUtilities.convertMouseEvent(this, e, graphPanel));
}
public void mouseReleased(MouseEvent e) {
if (button != MouseEvent.NOBUTTON && ((mousePressX != e.getX()) || (mousePressY != e.getY()))) {
if (button == MouseEvent.BUTTON3 || (button == MouseEvent.BUTTON1 && e.isControlDown() == true)) {
if (mouseAdapter != null) {
mouseAdapter.mouseReleasedButton3(e.getX(), e.getY(), cv);
}
} else if (e.getButton() == MouseEvent.BUTTON1) {
if (mouseAdapter != null) {
mouseAdapter.mouseReleasedButton1(e.getX(), e.getY(), cv);
}
}
}
button = MouseEvent.NOBUTTON;
graphPanel.dispatchEvent(SwingUtilities.convertMouseEvent(this, e, graphPanel));
}
// Hack to correct repaint in all-screen mode
private boolean toolTipTextWasChanged = false;
public String getToolTipText(MouseEvent event) {
int x = event.getX();
int y = event.getY();
int channelNumber = 0;
// lg.debug("getToolTipText: X=" + x + "; Y=" + y);
if (fontHeight != 0) {
channelNumber = y / fontHeight;
}
if ((channelNumber < plotDataProviders.size()) && (x > getWidth() - 120) && (x < getWidth() - 20)) {
PlotDataProvider channel = plotDataProviders.get(channelNumber);
toolTipTextWasChanged = true;
// lg.debug("getToolTipText: label");
return getChannelLabelText(channel);
} else if(graphPanel.getShowBlockHeader()){
toolTipTextWasChanged = true;
PlotDataProvider channel = plotDataProviders.get(0);
return getBlockHeaderText(channel, x);
} else {
// lg.debug("getToolTipText: empty");
if (toolTipTextWasChanged) {
toolTipTextWasChanged = false;
graphPanel.forceRepaint();
//graphPanel.repaint(); // repetitive call to repaint()
}
return null;
}
}
protected String getChannelLabelText(PlotDataProvider channel) {
String respname = "No response";
try {
if (channel.getResponse() != null) {
respname = channel.getResponse().getFileName();
}
} catch (TraceViewException e) {
// do nothing
}
return "<html>" + channel.getName() + "<br><i>Start time: </i> "
+ TimeInterval.formatDate(channel.getTimeRange().getStartTime(), TimeInterval.DateFormatType.DATE_FORMAT_MIDDLE)
+ "<br><i>Duration: </i> " + channel.getTimeRange().convert() + "<br><i>Sample rate: </i>" + channel.getSampleRate() + " ms <br>"
+ respname + "</html>";
}
protected String getBlockHeaderText(PlotDataProvider channel, int x) {
long time = getTime(x);
List<Segment> segments = channel.getRawData(new TimeInterval(time, time));
if(segments.size()>0){
return segments.get(0).getBlockHeaderText(time);
} else {
return "<html>There is no data in this place</html>";
}
}
public JToolTip createToolTip(){
return new CVToolTip();
}
class CVToolTip extends JToolTip{
/**
*
*/
private static final long serialVersionUID = 1L;
public CVToolTip(){
logger.debug("CVToolTip: create");
tooltipVisible = true;
}
@SuppressWarnings("deprecation")
public void show(){
logger.debug("CVToolTip: show");
super.show();
}
@SuppressWarnings("deprecation")
public void hide(){
logger.debug("CVToolTip: hide");
super.hide();
}
public void repaint(){
super.repaint();
graphPanel.repaint();
}
protected void finalize()throws Throwable {
logger.debug("CVToolTip: false");
tooltipVisible = false;
super.finalize();
}
}
private Set<EventWrapper> getEvents(int x) {
// lg.debug("getEvents: x= " + x);
if (graphs != null) {
for (PlotData data: graphs) {
if (data.getPointCount() > x) {
Set<EventWrapper> ret = new HashSet<EventWrapper>();
for (PlotDataPoint dp: data.getPixels().get(x)) {
if (dp.getEvents().size() != 0) {
ret.addAll(dp.getEvents());
}
}
if (ret.size() > 0) {
return ret;
} else {
return null;
}
} else {
return null;
}
}
}
return null;
}
}
}// @jve:decl-index=0:visual-constraint="10,10"
/*
class CustomToolTipManager extends ToolTipManager {
public CustomToolTipManager(){}
public void mouseMoved(MouseEvent event){
super.mouseMoved(event);
if(event.getSource() instanceof ChannelView){
ChannelView cv = (ChannelView)event.getSource();
cv.getGraphPanel().forceRepaint = true;
}
}
}
*/
class Stroke {
int top = Integer.MIN_VALUE;
int bottom = Integer.MAX_VALUE;
Color color = null;
public String toString(){
return "Stroke: " + top + "-" + bottom + ", color " + color;
}
}
/**
* Class to represent marker on graph area.
*/
class MarkPosition {
private long time = Long.MIN_VALUE;
private double value = Double.NEGATIVE_INFINITY;
public MarkPosition(long time, double value) {
this.time = time;
this.value = value;
}
public long getTime() {
return time;
}
public double getValue() {
return value;
}
}