package com.isti.traceview.gui.controls;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
//import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.util.Date;
import java.util.Observable;
import java.util.Observer;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.MouseInputListener;
import org.apache.log4j.Logger;
import com.isti.traceview.TraceView;
import com.isti.traceview.common.TimeInterval;
import com.isti.traceview.data.DataModule;
import com.isti.traceview.gui.GraphPanel;
import com.isti.traceview.gui.GraphPanel.GraphPanelObservable;
/**
* Scroll bar to control traces in Graph Panel.
*
* @author Max Kokoulin
*/
public class Slider extends JPanel implements Observer {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(Slider.class);
private static final Dimension size = new Dimension(200, 30);
//private static Insets inset = new Insets(0, 0, 0, 0);
private Font labelFont = null;
private GraphPanel graphPanel = null;
private SliderPanel slider = null;
private TimeInterval range = null;
private int mousePressX = Integer.MIN_VALUE;
private int sliderMoved = 0;
public Slider(GraphPanel graphPanel) {
super();
this.graphPanel = graphPanel;
this.range = null;
BoxLayout thisLayout = new BoxLayout(this, javax.swing.BoxLayout.X_AXIS);
setLayout(thisLayout);
graphPanel.addObserver(this);
TraceView.getDataModule().addObserver(this);
slider = new SliderPanel();
add(slider);
setSize(size);
setPreferredSize(size);
setMinimumSize(new Dimension(200, 30));
setMaximumSize(new Dimension(10000, size.width));
labelFont = new Font(getFont().getName(), getFont().getStyle(), getFont().getSize() - 1);
this.validate();
}
/**
* Gets time range of scroll bar, this time range represented whole length of bar
*/
public TimeInterval getRange() {
return range;
}
/**
* Sets time range of scroll bar, this time range represented whole length of bar
*/
public void setRange(TimeInterval range) {
this.range = range;
}
/**
* Gets position of slider, in pixels
*/
private int getSliderPosition() {
return new Long(slider.getWidth() * (graphPanel.getTimeRange().getStart() - range.getStart()) / range.getDuration()).intValue();
}
/**
* Gets width of slider, in pixels
*/
private int getSliderWidth() {
return new Long(slider.getWidth() * (graphPanel.getTimeRange().getEnd() - range.getStart()) / range.getDuration()).intValue()
- getSliderPosition();
}
/**
* Gets date corresponding position on scroll bar
* @param x the scroll bar position
* @return the corresponding date
*/
private Date getDate(int x) {
return new Date(range.getStart() + range.getDuration() * x / slider.getWidth());
}
public void update(Observable o, Object arg) {
logger.debug(this + ": update request from " + o);
if (o instanceof DataModule) {
if (arg instanceof TimeInterval) {
setRange((TimeInterval) arg);
repaint();
}
} else if (o instanceof GraphPanelObservable) {
if (arg instanceof TimeInterval) {
repaint();
}
}
}
private class SliderPanel extends JPanel implements MouseInputListener {
private static final long serialVersionUID = 1L;
public SliderPanel() {
super();
this.setBorder(new LineBorder(Color.BLACK, 2, true));
this.setBackground(Color.WHITE);
this.setMaximumSize(new Dimension(10000, 18));
addMouseListener(this);
addMouseMotionListener(this);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (graphPanel.getTimeRange() == null || range == null) {
g.drawLine(0, 0, getWidth(), getHeight());
g.drawLine(0, getHeight(), getWidth(), 0);
} else {
logger.debug("SliderPanel repaint: position " + getSliderPosition() + ", width " + getSliderWidth() + ", shift " + sliderMoved);
int startx = getSliderPosition() + sliderMoved;
int width = getSliderWidth();
g.fillRoundRect(startx, 0, width, getHeight(), 3, 3);
if (mousePressX != Integer.MIN_VALUE) {
g.setFont(labelFont);
FontMetrics fontMetrics = g.getFontMetrics();
g.setXORMode(Color.WHITE);
g.drawString(TimeInterval.formatDate(getDate(startx), TimeInterval.DateFormatType.DATE_FORMAT_MIDDLE), 5,
fontMetrics.getHeight() - 2);
String end = TimeInterval.formatDate(getDate(startx + width), TimeInterval.DateFormatType.DATE_FORMAT_MIDDLE);
g.drawString(end, getWidth() - fontMetrics.stringWidth(end) - 5, fontMetrics.getHeight() - 2);
}
}
}
/**
* Methods from MouseInputListener interface to handle mouse events.
*/
public void mouseMoved(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
if (mousePressX == Integer.MIN_VALUE) {
sliderMoved = 0;
} else {
sliderMoved = e.getX() - mousePressX;
}
repaint();
}
public void mouseClicked(MouseEvent e) {
int x = e.getX();
if (x < getSliderPosition()) {
TimeInterval current = graphPanel.getTimeRange();
graphPanel.setTimeRange(new TimeInterval(current.getStart() - current.getDuration(), current.getEnd() - current.getDuration()));
} else if (x > (getSliderPosition() + getSliderWidth())) {
TimeInterval current = graphPanel.getTimeRange();
graphPanel.setTimeRange(new TimeInterval(current.getStart() + current.getDuration(), current.getEnd() + current.getDuration()));
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
int x = e.getX();
if (x > getSliderPosition() && x < (getSliderPosition() + getSliderWidth())) {
mousePressX = x;
sliderMoved = 0;
repaint();
}
}
public void mouseReleased(MouseEvent e) {
mousePressX = Integer.MIN_VALUE;
long start = getDate(getSliderPosition() + sliderMoved).getTime();
graphPanel.setTimeRange(new TimeInterval(start, start + graphPanel.getTimeRange().getDuration()));
sliderMoved = 0;
}
}
}