All Downloads are FREE. Search and download functionalities are using the official Maven repository.

timeBench.action.layout.timescale.BasicTimeScale Maven / Gradle / Ivy

Go to download

TimeBench, a flexible, easy-to-use, and reusable software library written in Java that provides foundational data structures and algorithms for time- oriented data in Visual Analytics.

The newest version!
package timeBench.action.layout.timescale;

import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;

import org.apache.log4j.Logger;

/**
 * 

* The central class in the TimeVis API. It essentially implements the mapping * between pixels and dates by using a start date and the number of milliseconds * that should be displayed within one pixel. *

*

* BasicTimeScale uses {@link TimeUnitProvider#getBest(double, int)} to * determine the best fitting {@link TimeUnit} for the given milliseconds that * should be represented by one unit. {@link BasicTimeScale} can 'fit' the * pixel-to-date mapping (if desired; see * {@link BasicTimeScale#adjustDateToUnit(int, long)}) along the determined * {@link TimeUnit} to absorb rounding errors between dates that lie in one * {@link TimeUnit} and therefore have to be displayed exactly. This adjustement * is based on the desired pixels per millisecond and the minimum number of * pixels to be displayed within one {@link TimeUnit}. *

* * @author peterw * */ public class BasicTimeScale implements TimeScale { protected final Logger log = Logger.getLogger(getClass()); private ChangeEvent ce = new ChangeEvent(this); private EventListenerList listenerList = new EventListenerList(); protected long startDate; protected long millisPerPixel; protected TimeUnit timeUnit; protected TimeUnitProvider timeUnitProvider; protected int minimumPixelPerUnit = 28; /** * Create a default {@link BasicTimeScale} with a default * {@link TimeUnitProvider}, the current date as the start date and one * hour representing one pixel. */ public BasicTimeScale() { this(TimeUnitProvider.createDefaultTimeUnitProvider()); } /** * Creates a {@link BasicTimeScale} with the current date as the start date * and one hour representing one pixel. * * @param timeUnitProvider * a {@link TimeUnitProvider} which will be use to determine the * best fitting {@link TimeUnit} */ public BasicTimeScale(TimeUnitProvider timeUnitProvider) { this(new Date().getTime(), GregorianTimeUnit.getMaxLength(Calendar.HOUR, 1), timeUnitProvider); } /** * Create a {@link BasicTimeScale} with the start date, the * milliseconds per pixel and {@link TimeUnitProvider} of the given {@link TimeScale}. * * @param scale * the base {@link BasicTimeScale} */ public BasicTimeScale(TimeScale scale) { this(scale.getStartDate(), scale.getMillisPerPixel(), scale.getTimeUnitProvider()); } /** * Creates a {@link BasicTimeScale} with a default {@link TimeUnitProvider}. * * @param startDate * a start date in milliseconds. The first pixel of this * {@link BasicTimeScale} will match to this date * @param millisPerPixel * the number of millisecond each pixel represents */ public BasicTimeScale(long startDate, long millisPerPixel) { this(startDate, millisPerPixel, TimeUnitProvider.createDefaultTimeUnitProvider()); } /** * Creates a {@link BasicTimeScale} with a given start date in milliseconds, * the number of milliseconds that should be represented by one pixel and a * {@link TimeUnitProvider} which will be used to determine the best fitting * {@link TimeUnit}. * * @param startDate * a start date in milliseconds. The first pixel of this * {@link BasicTimeScale} will match to this date * @param millisPerPixel * the number of millisecond each pixel represents * @param timeUnitProvider * a {@link TimeUnitProvider} which will be use to determine the * best fitting {@link TimeUnit} */ public BasicTimeScale(long startDate, long millisPerPixel, TimeUnitProvider timeUnitProvider) { this.timeUnitProvider = timeUnitProvider; this.startDate = startDate; this.millisPerPixel = millisPerPixel; timeUnit = timeUnitProvider.getBest(millisPerPixel, minimumPixelPerUnit); } /** * Returns the number of milliseconds one pixel represents. * * @return the number of milliseconds one pixel represents */ public long getMillisPerPixel() { return millisPerPixel; } /** * Set the number of milliseconds one pixel represents. * * @param millisPerPixel * the number of milliseconds one pixel represents */ public void setMillisPerPixel(long millisPerPixel) { this.millisPerPixel = millisPerPixel; adjustTimeScale(); } /** * Returns the current {@link TimeUnitProvider}. * * @return the current {@link TimeUnitProvider} */ public TimeUnitProvider getTimeUnitProvider() { return timeUnitProvider; } /** * Set the current {@link TimeUnitProvider} * * @param timeUnitProvider * a {@link TimeUnitProvider} */ public void setTimeUnitProvider(TimeUnitProvider timeUnitProvider) { this.timeUnitProvider = timeUnitProvider; adjustTimeScale(); } /** * Returns the minimum number of pixels, that should be used to represent * one {@link TimeUnit}. * * @return the minimum number of pixels, that should be used to represent * one {@link TimeUnit} * @see TimeUnitProvider#getBest(double, int) */ public int getMinimumPixelPerUnit() { return minimumPixelPerUnit; } /** * Set the minimum number of pixels, that should be used to represent one * {@link TimeUnit}. * * @return the minimum number of pixels, that should be used to represent * one {@link TimeUnit} * @see TimeUnitProvider#getBest(double, int) */ public void setMinimumPixelPerUnit(int minimumPixelPerUnit) { this.minimumPixelPerUnit = minimumPixelPerUnit; adjustTimeScale(); } /** * Returns the currently used {@link TimeUnit} * * @return the currently used {@link TimeUnit} */ public TimeUnit getTimeUnit() { return timeUnit; } /** * Returns the start date of this {@link BasicTimeScale}, which is * represented by the first pixel. * * @return the start date */ public long getStartDate() { return startDate; } /** * Set the start date of this {@link BasicTimeScale}, which is represented * by the first pixel. * * @param startDate * the start date */ public void setStartDate(long startDate) { this.startDate = startDate; fireStateChanged(); } /** * Returns the start date adjusted to the current {@link TimeUnit} * * @see BasicTimeScale#adjustDateToUnit(int, long) * @return the adjusted start date */ public long getStartDateAdjusted() { return adjustDateToUnit(0, getStartDate()); } /** * Returns a date represented by the given pixel, adjusted to the current * {@link TimeUnit} * * @param pixel * a pixel * @return an date represented by this pixel, adjusted to the current * {@link TimeUnit} * @see BasicTimeScale#adjustDateToUnit(int, long) */ public long getDateAtPixel(int pixel) { return getDateAtPixel(pixel, true); } /** *

* Returns a date represented by the given pixel. *

*

* This method uses {@link BasicTimeScale#getRawDate(int)} to retrieve that * date and {@link BasicTimeScale#adjustDateToUnit(int, long)} to adjust * this date, if given. *

* * @param pixel * a pixel * @param adjustToUnit * return a date adjusted to the current {@link TimeUnit} * @return a (adjusted) date represented by the given pixel */ public long getDateAtPixel(int pixel, boolean adjustToUnit) { long rawDate = getRawDate(pixel); if (adjustToUnit) { rawDate = adjustDateToUnit(pixel, rawDate); } return rawDate; } /** *

* Returns a date represented by the given pixel. *

*

* The date is determined by multiplying given pixel with the milliseconds * per pixel and adding the start date. *

* * @param pixel * @return a date represented by the given pixel */ protected long getRawDate(int pixel) { return startDate + (long) (pixel * getMillisPerPixel()); } /** * Returns the pixel representing the given date. * * @param date * a date * @return the pixel representing the given date */ public int getPixelForDate(long date) { long startDifference = date - startDate; int x = (int) (startDifference / getMillisPerPixel()); return x; } /** *

* Adjusts a given date at a particular pixel to the current * {@link TimeUnit}. *

*

* One pixel represents not a single date, but an interval defined by the * number of milliseconds per pixel. The given pixel and date must match for * this method to return correct results. *

*

* Given, parameter pixel represents a range of dates, where one of these * date 'fit' into the current {@link TimeUnit} and parameter date is one * date represented by this pixel, but not 'fitting' into the * {@link TimeUnit}. Adjusting this date to the current {@link TimeUnit} * just means to convert the given date to the fitting date. Note that the * pixel-date mapping remains correct as one pixel maps to both dates, the * given and the returned. *

*

* If none of the dates represented by the given pixel 'fits' into the * current {@link TimeUnit}, the adjusted date will be interpolated based * on the next 'fitting' date and the number of milliseconds per pixel. *

* * @param pixel * the pixel representing rawDate * @param rawDate * a date represented by pixel * @return a date adjusted to the {@link TimeUnit} and represented by the * given pixel */ public long adjustDateToUnit(int pixel, long rawDate) { if (timeUnit.previous(rawDate) == rawDate) { return rawDate; } long nextUnit = timeUnit.next(rawDate); int unitX = (int) getPixelForDate(nextUnit); rawDate = nextUnit - (unitX - pixel) * millisPerPixel; return rawDate; } /** * Zoom this {@link BasicTimeScale}. * * @param factor * the zoom factor */ public void zoom(double factor) { millisPerPixel *= factor; adjustTimeScale(); } /** * Pan this {@link BasicTimeScale}. * * @param pixels * the number of pixels to pan */ public void pan(int pixels) { startDate = (long) (startDate - getMillisPerPixel() * pixels); fireStateChanged(); } /** * Adjusts the {@link TimeUnit} and fires a {@link ChangeEvent} when * properties like millisPerSecond, startDate, etc. have changed. */ protected void adjustTimeScale() { timeUnit = timeUnitProvider.getBest(millisPerPixel, minimumPixelPerUnit); fireStateChanged(); } protected void fireStateChanged() { for (ChangeListener l : listenerList.getListeners(ChangeListener.class)) { l.stateChanged(ce); } } public void addChangeListener(ChangeListener cl) { listenerList.add(ChangeListener.class, cl); } public void removeChangeListener(ChangeListener cl) { listenerList.remove(ChangeListener.class, cl); } public String toString() { DateFormat df = DateFormat.getDateTimeInstance(); StringBuilder sb = new StringBuilder(); sb.append(df.format(startDate)); sb.append(", Unit: ").append(timeUnit); return sb.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy