/* * 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.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipsetrader.core.feed.TimeSpan; import org.eclipsetrader.ui.internal.UIActivator; public class DateScaleCanvas { private Canvas horizontalScaleCanvas; private Image horizontalScaleImage; private Label label; private TimeSpan resolutionTimeSpan; private SimpleDateFormat monthYearFormatter = new SimpleDateFormat("MMM, yyyy"); //$NON-NLS-1$ private SimpleDateFormat monthFormatter = new SimpleDateFormat("MMM"); //$NON-NLS-1$ private SimpleDateFormat dayFormatter = new SimpleDateFormat("MMM, d"); //$NON-NLS-1$ private DateFormat dateFormat = DateFormat.getDateInstance(); private DateFormat dateTimeFormat = DateFormat.getDateTimeInstance(); Point location; DateValuesAxis datesAxis; Date[] visibleDates; public DateScaleCanvas(Composite parent) { GC gc = new GC(parent); FontMetrics fontMetrics = gc.getFontMetrics(); gc.dispose(); horizontalScaleCanvas = new Canvas(parent, SWT.DOUBLE_BUFFERED | SWT.NO_FOCUS | SWT.NO_BACKGROUND); horizontalScaleCanvas.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); horizontalScaleCanvas.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); ((GridData) horizontalScaleCanvas.getLayoutData()).heightHint = Dialog.convertVerticalDLUsToPixels(fontMetrics, 14); horizontalScaleCanvas.addControlListener(new ControlAdapter() { @Override public void controlResized(ControlEvent e) { if (horizontalScaleImage != null) { horizontalScaleImage.dispose(); horizontalScaleImage = null; } redraw(); } }); horizontalScaleCanvas.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { if (horizontalScaleImage != null) { horizontalScaleImage.dispose(); horizontalScaleImage = null; } } }); horizontalScaleCanvas.addPaintListener(new PaintListener() { @Override public void paintControl(PaintEvent e) { onPaint(e); } }); label = new Label(horizontalScaleCanvas, SWT.NONE); label.setBackground(horizontalScaleCanvas.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); label.setBounds(-200, 0, 0, 0); } public void setLocation(Point location) { this.location = location; } public void setDatesAxis(DateValuesAxis datesAxis) { this.datesAxis = datesAxis; } public Control getControl() { return horizontalScaleCanvas; } public Canvas getCanvas() { return horizontalScaleCanvas; } public void setVisibleDates(Date[] visibleDates) { this.visibleDates = visibleDates; } public void redraw() { horizontalScaleCanvas.setData(BaseChartViewer.K_NEEDS_REDRAW, Boolean.TRUE); horizontalScaleCanvas.redraw(); } private void onPaint(PaintEvent event) { Rectangle clientArea = horizontalScaleCanvas.getClientArea(); boolean needsRedraw = Boolean.TRUE.equals(horizontalScaleCanvas.getData(BaseChartViewer.K_NEEDS_REDRAW)); if (horizontalScaleImage != null && !horizontalScaleImage.isDisposed()) { if (horizontalScaleImage.getBounds().width != clientArea.width || horizontalScaleImage.getBounds().height != clientArea.height) { horizontalScaleImage.dispose(); } } if (horizontalScaleImage == null || horizontalScaleImage.isDisposed()) { horizontalScaleImage = new Image(horizontalScaleCanvas.getDisplay(), clientArea.width, clientArea.height); needsRedraw = true; } if (needsRedraw) { Graphics graphics = new Graphics(horizontalScaleImage, location, datesAxis, new DoubleValuesAxis()); try { graphics.fillRectangle(clientArea); Calendar oldDate = null; Calendar currentDate = Calendar.getInstance(); for (int i = 0; i < visibleDates.length; i++) { Date date = visibleDates[i]; boolean tick = false; // Draw a longer tick boolean highlight = false; // Highlight the tick String text = ""; //$NON-NLS-1$ currentDate.setTime(date); if (oldDate != null) { if (resolutionTimeSpan == null || resolutionTimeSpan.getUnits() == TimeSpan.Units.Days) { if (currentDate.get(Calendar.YEAR) != oldDate.get(Calendar.YEAR)) { tick = true; highlight = true; text = monthYearFormatter.format(currentDate.getTime()); } else if (currentDate.get(Calendar.MONTH) != oldDate.get(Calendar.MONTH)) { tick = true; highlight = false; text = monthFormatter.format(currentDate.getTime()); } } else { if (currentDate.get(Calendar.MONTH) != oldDate.get(Calendar.MONTH)) { tick = true; highlight = true; text = monthFormatter.format(currentDate.getTime()); } else if (currentDate.get(Calendar.DAY_OF_MONTH) != oldDate.get(Calendar.DAY_OF_MONTH)) { tick = true; highlight = false; text = dayFormatter.format(currentDate.getTime()); } } oldDate.setTime(date); } else { oldDate = Calendar.getInstance(); oldDate.setTime(date); } int x = graphics.mapToHorizontalAxis(date); graphics.setForegroundColor(highlight ? new RGB(255, 0, 0) : new RGB(0, 0, 0)); graphics.drawLine(x, 0, x, tick ? 6 : 3); if (tick) { graphics.drawString(text, x - 1, 7); } } } catch (Error e) { Status status = new Status(IStatus.ERROR, UIActivator.PLUGIN_ID, Messages.DateScaleCanvas_HorizontalScaleRenderingError); UIActivator.log(status); } finally { horizontalScaleCanvas.setData(BaseChartViewer.K_NEEDS_REDRAW, Boolean.FALSE); graphics.dispose(); } } Util.paintImage(event, horizontalScaleImage); } public void hideToolTip() { label.setLocation(-200, 0); } public void showToolTip(int x, int y, Date value) { if (value != null) { if (resolutionTimeSpan == null || resolutionTimeSpan.getUnits() == TimeSpan.Units.Days) { label.setText(dateFormat.format(value)); } else { label.setText(dateTimeFormat.format(value)); } label.pack(); label.setLocation(x - label.getSize().x / 2, 0); } } public TimeSpan getResolutionTimeSpan() { return resolutionTimeSpan; } public void setResolutionTimeSpan(TimeSpan resolutionTimeSpan) { this.resolutionTimeSpan = resolutionTimeSpan; } }