/*
* Copyright (c) 2004-2011 Marco Maccaferri and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marco Maccaferri - initial API and implementation
*/
package org.eclipsetrader.ui.charts;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
public class CrosshairDecorator implements MouseListener, MouseMoveListener, MouseTrackListener, DisposeListener, PaintListener {
public static final int MODE_OFF = 0;
public static final int MODE_MOUSE_DOWN = 1;
public static final int MODE_MOUSE_HOVER = 2;
private boolean active = true;
private int mode = MODE_OFF;
private boolean showSummaryTooltip;
private boolean mouseDown;
private boolean skipPaint;
private Point location;
private ChartCanvas focusCanvas;
private List<ChartCanvas> decoratedCanvas = new ArrayList<ChartCanvas>();
private DecoratorToolTip tooltip;
private StringBuilder summary = new StringBuilder();
private IChartObjectVisitor summaryLabelVisitor = new IChartObjectVisitor() {
@Override
public boolean visit(IChartObject object) {
String s = object.getToolTip(location.x, SWT.DEFAULT);
if (s != null) {
if (summary.length() != 0) {
summary.append("\r\n"); //$NON-NLS-1$
}
summary.append(s);
}
return true;
}
};
public CrosshairDecorator() {
}
public void decorateCanvas(ChartCanvas canvas) {
canvas.getCanvas().addMouseListener(this);
canvas.getCanvas().addMouseMoveListener(this);
canvas.getCanvas().addMouseTrackListener(this);
canvas.getCanvas().addDisposeListener(this);
canvas.getCanvas().addPaintListener(this);
decoratedCanvas.add(canvas);
}
public void createSummaryLabel(Composite parent) {
tooltip = new DecoratorToolTip(parent);
tooltip.setRespectDisplayBounds(true);
tooltip.setRespectMonitorBounds(true);
}
public void dispose() {
for (ChartCanvas canvas : decoratedCanvas) {
canvas.getCanvas().removeMouseListener(this);
canvas.getCanvas().removeMouseMoveListener(this);
canvas.getCanvas().removeMouseTrackListener(this);
canvas.getCanvas().removeDisposeListener(this);
canvas.getCanvas().removePaintListener(this);
}
decoratedCanvas.clear();
}
public void activate() {
if (!active) {
active = true;
}
}
public void deactivate() {
if (active) {
active = false;
}
}
public boolean isActive() {
return active;
}
public boolean isVisible() {
return location != null;
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
*/
@Override
public void widgetDisposed(DisposeEvent e) {
for (ChartCanvas canvas : decoratedCanvas) {
if (canvas.getCanvas() == e.widget) {
decoratedCanvas.remove(canvas);
break;
}
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void mouseDoubleClick(MouseEvent e) {
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void mouseDown(MouseEvent e) {
if (e.button != 1) {
return;
}
if (mode == MODE_MOUSE_DOWN && !mouseDown && active) {
location = new Point(e.x, e.y);
focusCanvas = (ChartCanvas) e.widget.getData();
drawLines(location);
updateLabel(location);
mouseDown = true;
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void mouseUp(MouseEvent e) {
if (e.button != 1) {
return;
}
if (mode == MODE_MOUSE_DOWN && mouseDown) {
skipPaint = true;
restoreBackground(location);
skipPaint = false;
location = null;
mouseDown = false;
if (tooltip != null) {
tooltip.hide();
}
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void mouseEnter(MouseEvent e) {
if (mode == MODE_MOUSE_HOVER || mouseDown) {
focusCanvas = (ChartCanvas) e.widget.getData();
location = new Point(e.x, e.y);
drawLines(location);
updateLabel(location);
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void mouseExit(MouseEvent e) {
if (location != null) {
skipPaint = true;
restoreBackground(location);
skipPaint = false;
location = null;
if (tooltip != null) {
tooltip.hide();
}
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void mouseHover(MouseEvent e) {
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
*/
@Override
public void mouseMove(MouseEvent e) {
if (mode == MODE_MOUSE_HOVER || mouseDown) {
skipPaint = true;
restoreBackground(location);
skipPaint = false;
focusCanvas = (ChartCanvas) e.widget.getData();
location = new Point(e.x, e.y);
drawLines(location);
updateLabel(location);
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
*/
@Override
public void paintControl(PaintEvent e) {
if (!skipPaint && active) {
drawLines(location);
}
}
private void drawLines(Point location) {
if (focusCanvas == null || location == null) {
return;
}
Rectangle bounds = focusCanvas.getCanvas().getBounds();
GC gc = new GC(focusCanvas.getCanvas());
gc.drawLine(location.x, 0, location.x, bounds.height);
gc.drawLine(0, location.y, bounds.width, location.y);
gc.dispose();
for (ChartCanvas canvas : decoratedCanvas) {
if (canvas.getCanvas() != focusCanvas.getCanvas()) {
bounds = canvas.getCanvas().getBounds();
gc = new GC(canvas.getCanvas());
gc.drawLine(location.x, 0, location.x, bounds.height);
gc.dispose();
}
}
}
private void restoreBackground(Point location) {
if (focusCanvas == null || location == null) {
return;
}
Rectangle bounds = focusCanvas.getCanvas().getBounds();
focusCanvas.getCanvas().redraw(location.x, 0, 1, bounds.height, false);
focusCanvas.getCanvas().update();
focusCanvas.getCanvas().redraw(0, location.y, bounds.width, 1, false);
focusCanvas.getCanvas().update();
for (ChartCanvas canvas : decoratedCanvas) {
if (canvas.getCanvas() != focusCanvas.getCanvas()) {
bounds = canvas.getCanvas().getBounds();
canvas.getCanvas().redraw(location.x, 0, 1, bounds.height, false);
canvas.getCanvas().update();
}
}
}
private void updateLabel(Point location) {
if (tooltip != null && location != null) {
summary = new StringBuilder();
for (ChartCanvas canvas : decoratedCanvas) {
canvas.accept(summaryLabelVisitor);
}
tooltip.setText(summary.toString());
if (showSummaryTooltip) {
if (!"".equals(tooltip.getText())) { //$NON-NLS-1$
Point p = new Point(location.x, location.y);
p = focusCanvas.getCanvas().toDisplay(p);
tooltip.show(p);
}
else {
tooltip.hide();
}
}
}
}
public int getMode() {
return mode;
}
public void setMode(int mode) {
this.mode = mode;
}
public boolean isShowSummaryTooltip() {
return showSummaryTooltip;
}
public void setShowSummaryTooltip(boolean showSummaryTooltip) {
this.showSummaryTooltip = showSummaryTooltip;
if (!showSummaryTooltip && tooltip != null) {
tooltip.hide();
}
}
}