]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/colour/DateColourer.java
Version 19, May 2018
[GpsPrune.git] / tim / prune / gui / colour / DateColourer.java
1 package tim.prune.gui.colour;
2
3 import java.awt.Color;
4 import java.text.DateFormat;
5 import java.util.Calendar;
6 import java.util.HashMap;
7 import java.util.TimeZone;
8
9 import tim.prune.config.Config;
10 import tim.prune.data.DataPoint;
11 import tim.prune.data.Timestamp;
12 import tim.prune.data.Track;
13 import tim.prune.data.TrackInfo;
14
15 /**
16  * Point colourer giving a different colour to each date.
17  * Uses the currently selected timezone, so the results
18  * may be different when selecting a different timezone
19  */
20 public class DateColourer extends DiscretePointColourer
21 {
22         // Doesn't really matter what format is used here, as long as dates are different
23         private static final DateFormat DEFAULT_DATE_FORMAT = DateFormat.getDateInstance();
24         // Selected timezone for deciding which date a timestamp falls on
25         private TimeZone _selectedTimezone = null;
26
27         /**
28          * Constructor
29          * @param inStartColour start colour of scale
30          * @param inEndColour end colour of scale
31          * @param inWrapLength number of unique colours before wrap
32          */
33         public DateColourer(Color inStartColour, Color inEndColour, int inWrapLength)
34         {
35                 super(inStartColour, inEndColour, inWrapLength);
36         }
37
38         /**
39          * Calculate the colours for each of the points in the given track
40          * @param inTrackInfo track info object
41          */
42         @Override
43         public synchronized void calculateColours(TrackInfo inTrackInfo)
44         {
45                 // Note, this method needs to be synchronized because otherwise the
46                 // Calendar objects in the different threads get confused and the
47                 // wrong colours are generated.
48
49                 // TODO: Move this timezone-selection into a helper for use by others?
50                 // Select the current timezone
51                 final String zoneId = Config.getConfigString(Config.KEY_TIMEZONE_ID);
52                 if (zoneId == null || zoneId.equals("")) {
53                         _selectedTimezone = TimeZone.getDefault();
54                 }
55                 else {
56                         _selectedTimezone = TimeZone.getTimeZone(zoneId);
57                 }
58                 // initialise the array to the right size
59                 Track track = inTrackInfo == null ? null : inTrackInfo.getTrack();
60                 final int numPoints = track == null ? 0 : track.getNumPoints();
61                 init(numPoints);
62                 // Make a hashmap of the already-used dates
63                 HashMap<String, Integer> usedDates = new HashMap<String, Integer>(20);
64                 // Also store the previous one, because they're probably consecutive
65                 String prevDate = null;
66                 int prevIndex = -1;
67
68                 // loop over track points
69                 int dayIndex = -1;
70                 for (int i=0; i<numPoints; i++)
71                 {
72                         DataPoint p = track.getPoint(i);
73                         if (p != null && !p.isWaypoint())
74                         {
75                                 dayIndex = 0; // default index 0 will be used if no date found
76                                 String date = getDate(p.getTimestamp());
77                                 if (date != null)
78                                 {
79                                         // Check if it's the previous one
80                                         if (prevDate != null && date.equals(prevDate)) {
81                                                 dayIndex = prevIndex;
82                                         }
83                                         else
84                                         {
85                                                 // Look up in the hashmap to see if it's been used before
86                                                 Integer foundIndex = usedDates.get(date);
87                                                 if (foundIndex == null)
88                                                 {
89                                                         // not been used before, so add it
90                                                         dayIndex = usedDates.size() + 1;
91                                                         usedDates.put(date, dayIndex);
92                                                 }
93                                                 else
94                                                 {
95                                                         // found it
96                                                         dayIndex = foundIndex;
97                                                 }
98                                                 // Remember what we've got for the next point
99                                                 prevDate = date;
100                                                 prevIndex = dayIndex;
101                                         }
102                                 }
103                                 // if date is null (no timestamp or invalid) then dayIndex remains 0
104                                 setColour(i, dayIndex);
105                         }
106                 }
107
108                 // generate the colours needed
109                 generateDiscreteColours(usedDates.size() + 1);
110         }
111
112
113         /**
114          * Find which date (in the currently selected timezone) the given timestamp falls on
115          * @param inTimestamp timestamp
116          * @return String containing description of date, or null
117          */
118         private String getDate(Timestamp inTimestamp)
119         {
120                 if (inTimestamp == null || !inTimestamp.isValid()) {
121                         return null;
122                 }
123                 Calendar cal = inTimestamp.getCalendar(null);
124                 // use selected time zone, not system one
125                 DEFAULT_DATE_FORMAT.setTimeZone(_selectedTimezone);
126                 return DEFAULT_DATE_FORMAT.format(cal.getTime());
127         }
128 }