1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.jrobin.graph;
26
27 import java.awt.*;
28 import java.text.SimpleDateFormat;
29 import java.util.Calendar;
30 import java.util.Date;
31 import java.util.Locale;
32
33 class TimeAxis implements RrdGraphConstants {
34 private static final TimeAxisSetting[] tickSettings = {
35 new TimeAxisSetting(0, SECOND, 30, MINUTE, 5, MINUTE, 5, 0, "HH:mm"),
36 new TimeAxisSetting(2, MINUTE, 1, MINUTE, 5, MINUTE, 5, 0, "HH:mm"),
37 new TimeAxisSetting(5, MINUTE, 2, MINUTE, 10, MINUTE, 10, 0, "HH:mm"),
38 new TimeAxisSetting(10, MINUTE, 5, MINUTE, 20, MINUTE, 20, 0, "HH:mm"),
39 new TimeAxisSetting(30, MINUTE, 10, HOUR, 1, HOUR, 1, 0, "HH:mm"),
40 new TimeAxisSetting(60, MINUTE, 30, HOUR, 2, HOUR, 2, 0, "HH:mm"),
41 new TimeAxisSetting(180, HOUR, 1, HOUR, 6, HOUR, 6, 0, "HH:mm"),
42 new TimeAxisSetting(600, HOUR, 6, DAY, 1, DAY, 1, 24 * 3600, "EEE"),
43 new TimeAxisSetting(1800, HOUR, 12, DAY, 1, DAY, 2, 24 * 3600, "EEE"),
44 new TimeAxisSetting(3600, DAY, 1, WEEK, 1, WEEK, 1, 7 * 24 * 3600, "'Week 'w"),
45 new TimeAxisSetting(3 * 3600, WEEK, 1, MONTH, 1, WEEK, 2, 7 * 24 * 3600, "'Week 'w"),
46 new TimeAxisSetting(6 * 3600, MONTH, 1, MONTH, 1, MONTH, 1, 30 * 24 * 3600, "MMM"),
47 new TimeAxisSetting(48 * 3600, MONTH, 1, MONTH, 3, MONTH, 3, 30 * 24 * 3600, "MMM"),
48 new TimeAxisSetting(10 * 24 * 3600, YEAR, 1, YEAR, 1, YEAR, 1, 365 * 24 * 3600, "yy"),
49 new TimeAxisSetting(-1, MONTH, 0, MONTH, 0, MONTH, 0, 0, "")
50 };
51
52 private TimeAxisSetting tickSetting;
53 private RrdGraph rrdGraph;
54 private double secPerPix;
55 private Calendar calendar;
56
57 TimeAxis(RrdGraph rrdGraph) {
58 this.rrdGraph = rrdGraph;
59 if (rrdGraph.im.xsize > 0) {
60 this.secPerPix = (rrdGraph.im.end - rrdGraph.im.start) / rrdGraph.im.xsize;
61 }
62 this.calendar = Calendar.getInstance(Locale.getDefault());
63 this.calendar.setFirstDayOfWeek(rrdGraph.gdef.firstDayOfWeek);
64 }
65
66 void draw() {
67 chooseTickSettings();
68 if (tickSetting == null) {
69 return;
70 }
71 drawMinor();
72 drawMajor();
73 drawLabels();
74 }
75
76 private void drawMinor() {
77 if (!rrdGraph.gdef.noMinorGrid) {
78 adjustStartingTime(tickSetting.minorUnit, tickSetting.minorUnitCount);
79 Paint color = rrdGraph.gdef.colors[COLOR_GRID];
80 int y0 = rrdGraph.im.yorigin, y1 = y0 - rrdGraph.im.ysize;
81 for (int status = getTimeShift(); status <= 0; status = getTimeShift()) {
82 if (status == 0) {
83 long time = calendar.getTime().getTime() / 1000L;
84 int x = rrdGraph.mapper.xtr(time);
85 rrdGraph.worker.drawLine(x, y0 - 1, x, y0 + 1, color, TICK_STROKE);
86 rrdGraph.worker.drawLine(x, y0, x, y1, color, GRID_STROKE);
87 }
88 findNextTime(tickSetting.minorUnit, tickSetting.minorUnitCount);
89 }
90 }
91 }
92
93 private void drawMajor() {
94 adjustStartingTime(tickSetting.majorUnit, tickSetting.majorUnitCount);
95 Paint color = rrdGraph.gdef.colors[COLOR_MGRID];
96 int y0 = rrdGraph.im.yorigin, y1 = y0 - rrdGraph.im.ysize;
97 for (int status = getTimeShift(); status <= 0; status = getTimeShift()) {
98 if (status == 0) {
99 long time = calendar.getTime().getTime() / 1000L;
100 int x = rrdGraph.mapper.xtr(time);
101 rrdGraph.worker.drawLine(x, y0 - 2, x, y0 + 2, color, TICK_STROKE);
102 rrdGraph.worker.drawLine(x, y0, x, y1, color, GRID_STROKE);
103 }
104 findNextTime(tickSetting.majorUnit, tickSetting.majorUnitCount);
105 }
106 }
107
108 private void drawLabels() {
109
110 String labelFormat = tickSetting.format.replaceAll("([^%]|^)%([^%t])", "$1%t$2");
111 Font font = rrdGraph.gdef.smallFont;
112 Paint color = rrdGraph.gdef.colors[COLOR_FONT];
113 adjustStartingTime(tickSetting.labelUnit, tickSetting.labelUnitCount);
114 int y = rrdGraph.im.yorigin + (int) rrdGraph.worker.getFontHeight(font) + 2;
115 for (int status = getTimeShift(); status <= 0; status = getTimeShift()) {
116 String label = formatLabel(labelFormat, calendar.getTime());
117 long time = calendar.getTime().getTime() / 1000L;
118 int x1 = rrdGraph.mapper.xtr(time);
119 int x2 = rrdGraph.mapper.xtr(time + tickSetting.labelSpan);
120 int labelWidth = (int) rrdGraph.worker.getStringWidth(label, font);
121 int x = x1 + (x2 - x1 - labelWidth) / 2;
122 if (x >= rrdGraph.im.xorigin && x + labelWidth <= rrdGraph.im.xorigin + rrdGraph.im.xsize) {
123 rrdGraph.worker.drawString(label, x, y, font, color);
124 }
125 findNextTime(tickSetting.labelUnit, tickSetting.labelUnitCount);
126 }
127 }
128
129 private static String formatLabel(String format, Date date) {
130 if (format.contains("%")) {
131
132 return String.format(format, date);
133 }
134 else {
135
136 return new SimpleDateFormat(format).format(date);
137 }
138 }
139
140 private void findNextTime(int timeUnit, int timeUnitCount) {
141 switch (timeUnit) {
142 case SECOND:
143 calendar.add(Calendar.SECOND, timeUnitCount);
144 break;
145 case MINUTE:
146 calendar.add(Calendar.MINUTE, timeUnitCount);
147 break;
148 case HOUR:
149 calendar.add(Calendar.HOUR_OF_DAY, timeUnitCount);
150 break;
151 case DAY:
152 calendar.add(Calendar.DAY_OF_MONTH, timeUnitCount);
153 break;
154 case WEEK:
155 calendar.add(Calendar.DAY_OF_MONTH, 7 * timeUnitCount);
156 break;
157 case MONTH:
158 calendar.add(Calendar.MONTH, timeUnitCount);
159 break;
160 case YEAR:
161 calendar.add(Calendar.YEAR, timeUnitCount);
162 break;
163 }
164 }
165
166 private int getTimeShift() {
167 long time = calendar.getTime().getTime() / 1000L;
168 return (time < rrdGraph.im.start) ? -1 : (time > rrdGraph.im.end) ? +1 : 0;
169 }
170
171 private void adjustStartingTime(int timeUnit, int timeUnitCount) {
172 calendar.setTime(new Date(rrdGraph.im.start * 1000L));
173 switch (timeUnit) {
174 case SECOND:
175 calendar.add(Calendar.SECOND, -(calendar.get(Calendar.SECOND) % timeUnitCount));
176 break;
177 case MINUTE:
178 calendar.set(Calendar.SECOND, 0);
179 calendar.add(Calendar.MINUTE, -(calendar.get(Calendar.MINUTE) % timeUnitCount));
180 break;
181 case HOUR:
182 calendar.set(Calendar.SECOND, 0);
183 calendar.set(Calendar.MINUTE, 0);
184 calendar.add(Calendar.HOUR_OF_DAY, -(calendar.get(Calendar.HOUR_OF_DAY) % timeUnitCount));
185 break;
186 case DAY:
187 calendar.set(Calendar.SECOND, 0);
188 calendar.set(Calendar.MINUTE, 0);
189 calendar.set(Calendar.HOUR_OF_DAY, 0);
190 break;
191 case WEEK:
192 calendar.set(Calendar.SECOND, 0);
193 calendar.set(Calendar.MINUTE, 0);
194 calendar.set(Calendar.HOUR_OF_DAY, 0);
195 int diffDays = calendar.get(Calendar.DAY_OF_WEEK) - calendar.getFirstDayOfWeek();
196 if (diffDays < 0) {
197 diffDays += 7;
198 }
199 calendar.add(Calendar.DAY_OF_MONTH, -diffDays);
200 break;
201 case MONTH:
202 calendar.set(Calendar.SECOND, 0);
203 calendar.set(Calendar.MINUTE, 0);
204 calendar.set(Calendar.HOUR_OF_DAY, 0);
205 calendar.set(Calendar.DAY_OF_MONTH, 1);
206 calendar.add(Calendar.MONTH, -(calendar.get(Calendar.MONTH) % timeUnitCount));
207 break;
208 case YEAR:
209 calendar.set(Calendar.SECOND, 0);
210 calendar.set(Calendar.MINUTE, 0);
211 calendar.set(Calendar.HOUR_OF_DAY, 0);
212 calendar.set(Calendar.DAY_OF_MONTH, 1);
213 calendar.set(Calendar.MONTH, 0);
214 calendar.add(Calendar.YEAR, -(calendar.get(Calendar.YEAR) % timeUnitCount));
215 break;
216 }
217 }
218
219
220 private void chooseTickSettings() {
221 if (rrdGraph.gdef.timeAxisSetting != null) {
222 tickSetting = new TimeAxisSetting(rrdGraph.gdef.timeAxisSetting);
223 }
224 else {
225 for (int i = 0; tickSettings[i].secPerPix >= 0 && secPerPix > tickSettings[i].secPerPix; i++) {
226 tickSetting = tickSettings[i];
227 }
228 }
229 }
230
231 }