/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.gui.javafx.crs;
import com.sun.javafx.tk.FontMetrics;
import java.util.*;
import org.geotoolkit.temporal.object.TemporalConstants;
/**
* A single temporal subdivision used by DateRenderer.
*
* @author Johann Sorel (Geomatys)
*/
public interface TimeSubdivision {
/**
* @return unit text
*/
public String getUnitText();
/**
* We expect subdivisions to be regular.
* (can be unexact like are months and years)
*
* @return number of milliseconds to match one unit.
* example : 1 minute would be 60000.
*/
public double getUnitLength();
/**
* Intermediate division will not be displayed in the lower bar.
* @return true if division is intermediate.
*/
public boolean isIntermediate();
/**
* @param fm Font metrics to use for length evaluation
* @return maximum size of a text element
*/
public double getTextLength(FontMetrics fm);
/**
* @param milliseconds time in milliseconds
* @return Text for this time unit.
*/
public String getText(long milliseconds);
/**
*
* @param begin start time inclusive
* @param end end time inclusive
* @return steps between the two values
*/
public long[] getSteps(long begin, long end);
public static class Year implements TimeSubdivision {
@Override
public String getUnitText() {
return "";
}
@Override
public double getUnitLength() {
return TemporalConstants.YEAR_MS;
}
@Override
public boolean isIntermediate() {
return false;
}
@Override
public double getTextLength(FontMetrics fm) {
return fm.computeStringWidth("99999");
}
@Override
public String getText(long milliseconds) {
int value = (int) (milliseconds/TemporalConstants.YEAR_MS);
return String.valueOf(1970+value);
}
@Override
public long[] getSteps(long begin, long end) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(begin);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 1);
final List<Long> steps = new ArrayList<>();
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.YEAR, 1);
while(calendar.getTimeInMillis() <= end){
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.YEAR, 1);
}
final long[] array = new long[steps.size()];
for(int i=0,n=steps.size(); i<n; i++){
array[i] = steps.get(i);
}
return array;
}
}
public static class Month implements TimeSubdivision {
@Override
public String getUnitText() {
return "";
}
@Override
public double getUnitLength() {
return TemporalConstants.MONTH_MS;
}
@Override
public boolean isIntermediate() {
return false;
}
@Override
public double getTextLength(FontMetrics fm) {
return fm.computeStringWidth("AAAAAA"); //should not be longer
}
@Override
public String getText(long milliseconds) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(milliseconds);
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
return calendar.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault());
}
@Override
public long[] getSteps(long begin, long end) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(begin);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 1);
final List<Long> steps = new ArrayList<>();
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.MONTH, 1);
while(calendar.getTimeInMillis() <= end){
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.MONTH, 1);
}
final long[] array = new long[steps.size()];
for(int i=0,n=steps.size(); i<n; i++){
array[i] = steps.get(i);
}
return array;
}
}
public static class Day implements TimeSubdivision {
@Override
public String getUnitText() {
return "d";
}
@Override
public double getUnitLength() {
return TemporalConstants.DAY_MS;
}
@Override
public boolean isIntermediate() {
return false;
}
@Override
public double getTextLength(FontMetrics fm) {
return fm.computeStringWidth("AA"); //31 day max
}
@Override
public String getText(long milliseconds) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(milliseconds);
return String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));
}
@Override
public long[] getSteps(long begin, long end) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(begin);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 1);
final List<Long> steps = new ArrayList<>();
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.DAY_OF_MONTH, 1);
while(calendar.getTimeInMillis() <= end){
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
final long[] array = new long[steps.size()];
for(int i=0,n=steps.size(); i<n; i++){
array[i] = steps.get(i);
}
return array;
}
}
public static class Hour implements TimeSubdivision {
@Override
public String getUnitText() {
return "h";
}
@Override
public double getUnitLength() {
return TemporalConstants.HOUR_MS;
}
@Override
public boolean isIntermediate() {
return false;
}
@Override
public double getTextLength(FontMetrics fm) {
return fm.computeStringWidth("AA"); //24 max
}
@Override
public String getText(long milliseconds) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(milliseconds);
return String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
}
@Override
public long[] getSteps(long begin, long end) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(begin);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 1);
final List<Long> steps = new ArrayList<>();
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.HOUR_OF_DAY, 1);
while(calendar.getTimeInMillis() <= end){
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.HOUR_OF_DAY, 1);
}
final long[] array = new long[steps.size()];
for(int i=0,n=steps.size(); i<n; i++){
array[i] = steps.get(i);
}
return array;
}
}
public static class Quarter implements TimeSubdivision {
@Override
public String getUnitText() {
return "m";
}
@Override
public double getUnitLength() {
return TemporalConstants.MINUTE_MS * 15;
}
@Override
public boolean isIntermediate() {
return true;
}
@Override
public double getTextLength(FontMetrics fm) {
return fm.computeStringWidth("AA"); //60 max
}
@Override
public String getText(long milliseconds) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(milliseconds);
return String.valueOf(calendar.get(Calendar.MINUTE));
}
@Override
public long[] getSteps(long begin, long end) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(begin);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 1);
final List<Long> steps = new ArrayList<>();
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.MINUTE, 15);
while(calendar.getTimeInMillis() <= end){
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.MINUTE, 15);
}
final long[] array = new long[steps.size()];
for(int i=0,n=steps.size(); i<n; i++){
array[i] = steps.get(i);
}
return array;
}
}
public static class Minute implements TimeSubdivision {
@Override
public String getUnitText() {
return "m";
}
@Override
public double getUnitLength() {
return TemporalConstants.MINUTE_MS;
}
@Override
public boolean isIntermediate() {
return true;
}
@Override
public double getTextLength(FontMetrics fm) {
return fm.computeStringWidth("AA"); //60 max
}
@Override
public String getText(long milliseconds) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(milliseconds);
return String.valueOf(calendar.get(Calendar.MINUTE));
}
@Override
public long[] getSteps(long begin, long end) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
calendar.setTimeInMillis(begin);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 1);
final List<Long> steps = new ArrayList<>();
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.MINUTE, 1);
while(calendar.getTimeInMillis() <= end){
steps.add(calendar.getTimeInMillis());
calendar.add(Calendar.MINUTE, 1);
}
final long[] array = new long[steps.size()];
for(int i=0,n=steps.size(); i<n; i++){
array[i] = steps.get(i);
}
return array;
}
}
}