Source code: graph/DateDrawer.java
1 /* Copyright 1998 - 2003: Jim Cochrane - see file forum.txt */
2
3 package graph;
4
5 import java.awt.*;
6 import java.util.*;
7 import support.*;
8
9 /**
10 * Abstraction for drawing date data
11 */
12 public class DateDrawer extends TemporalDrawer {
13
14 // mkd is the associated market drawer and is_ind specifies whether
15 // this DateDrawer is associated with indicator data.
16 DateDrawer(BasicDrawer d) {
17 super(d);
18 }
19
20 // The data to be drawn
21 public Object data() { return _market_drawer.dates(); }
22
23 // 1 coordinate for each point - no x coordinate
24 public int drawing_stride() { return 1; }
25
26 public int[] x_values() {
27 return _market_drawer.x_values();
28 }
29
30 protected final static int Max_months = 360, Max_years = 30;
31
32 protected final static int Many_months = 28;
33
34 protected int Year_x_offset;
35
36 protected int Month_y, Year_y;
37
38 protected int Month_x_offset;
39
40 // length of the month name
41 protected int month_ln;
42
43 /**
44 * Draw a vertical line for each month in `data' and years and month
45 * names at the appropriate places.
46 */
47 protected void draw_tuples(Graphics g, Rectangle b) {
48 int mi, yi, i;
49 int lastyear, lastmonth, year, month;
50 Rectangle bounds = b;
51 IntPair months[] = new IntPair[Max_months],
52 years[] = new IntPair[Max_years];
53 int[] _x_values = x_values();
54 String[] data = (String[]) data();
55 if (data == null) return;
56
57 if (is_indicator()) {
58 Month_y = label_y_value(bounds);
59 Year_y = Month_y;
60 }
61 Month_x_offset = 10;
62 month_ln = 3;
63 // Determine the first month and year in `data'.
64 year = Integer.valueOf(data[0].substring(0,4)).intValue();
65 month = Integer.valueOf(data[0].substring(4,6)).intValue();
66 // If the first date in `data' is not "yyyymm01", it is not the
67 // first day of the month; thus the `month' needs to be incremented
68 // to the next month in `data', since the first month is not complete.
69 if (! data[0].substring(6,8).equals ("01")) {
70 if (month == 12) {
71 month = 1;
72 ++year;
73 } else {
74 ++month;
75 }
76 }
77 lastyear =
78 Integer.valueOf(data[data.length-1].substring(0,4)).intValue();
79 lastmonth =
80 Integer.valueOf(data[data.length-1].substring(4,6)).intValue();
81 mi = 0; yi = 0;
82 while (! (year == lastyear && month == lastmonth)) {
83 int date_index;
84 date_index = Utilities.index_at_date(
85 first_date_at(year, month), data, 1, 0, data.length - 1);
86 if (date_index < 0) {
87 month = lastmonth;
88 break;
89 }
90 months[mi] = new IntPair(month, date_index);
91 if (month == 1) {
92 years[yi] = new IntPair(year, months[mi].right());
93 ++yi;
94 }
95 if (month == 12) {
96 month = 1;
97 ++year;
98 } else {
99 ++month;
100 }
101 ++mi;
102 }
103 // assert: year == lastyear && month == lastmonth
104 months[mi] = new IntPair(month,
105 Utilities.index_at_date(first_date_at(year, month), data, 1, 0,
106 data.length - 1));
107 if (month == 1) {
108 years[yi] = new IntPair(year, months[mi].right());
109 ++yi;
110 }
111 ++mi;
112
113 if (months.length > 1 && _x_values.length > 1 &&
114 months[0] != null && months[1] != null &&
115 months[0].right() >= 0 && months[1].right() >= 0) {
116 // Set the month name length and the month x offset according
117 // to the distance between the x-value for the first month and
118 // the x-value for the second month.
119 if (_x_values[months[1].right()] -
120 _x_values[months[0].right()] < 25) {
121 month_ln = 1;
122 }
123 Month_x_offset = label_x_value(_x_values[months[0].right()],
124 _x_values[months[1].right()]);
125 Year_x_offset = Month_x_offset;
126 }
127 // Draw months and years.
128 boolean do_months = true;
129 if (mi > 1 && months[0].right() == months[1].right()) {
130 do_months = false;
131 }
132 if (do_months) {
133 i = 0;
134 while (i < mi) {
135 if (months[i].right() < 0) {
136 months[i].set_right(0);
137 }
138 draw_month(g, bounds, months[i], _x_values);
139 ++i;
140 }
141 }
142
143 i = 0;
144 while (i < yi) {
145 boolean short_years = do_months && mi >= Many_months;
146 if (is_indicator() && years[i].right() < _x_values.length) {
147 draw_year(g, bounds, years[i], ! do_months, true, _x_values,
148 short_years);
149 } else if (! do_months && years[i].right() < _x_values.length) {
150 draw_year(g, bounds, years[i], true, false, _x_values,
151 short_years);
152 }
153 ++i;
154 }
155 }
156
157 // Date of first day of `year'/`month' - for example:
158 // "20001101" for year = 2000 and month = 11
159 protected String first_date_at (int year, int month) {
160 String result;
161 String monthstr;
162
163 if (month < 10) {
164 monthstr = "0" + String.valueOf(month);
165 } else {
166 monthstr = String.valueOf(month);
167 }
168 result = String.valueOf(year) + monthstr + "01";
169
170 return result;
171 }
172
173 // Precondition:
174 // p.left() specifies the month
175 // p.right() specifies the index
176 protected void draw_month(Graphics g, Rectangle bounds, IntPair p,
177 int[] _x_values) {
178 int x, month_x, month;
179 final int Line_offset = -2;
180 double width_factor;
181
182 width_factor = width_factor_value(bounds, data_length());
183 x = _x_values[p.right()];
184 month_x = x + Month_x_offset;
185 month = p.left();
186 // Don't draw the line if it's close to the left border.
187 if (x > Too_far_left) {
188 g.setColor(conf.reference_line_color());
189 g.drawLine(x + Line_offset, bounds.y,
190 x + Line_offset, bounds.y + bounds.height);
191 }
192 if (is_indicator() && month != 1) {
193 g.setColor(conf.text_color());
194 g.drawString(Utilities.month_at(month).substring(0, month_ln),
195 month_x, Month_y);
196 }
197 }
198
199 // Precondition:
200 // p.left() specifies the year
201 // p.right() specifies the index
202 protected void draw_year(Graphics g, Rectangle bounds, IntPair p,
203 boolean line, boolean year, int[] _x_values, boolean two_digit) {
204 int year_x, x;
205 final int Line_offset = -3;
206 double width_factor;
207
208 width_factor = width_factor_value(bounds, data_length());
209 x = _x_values[p.right()];
210 year_x = x + Year_x_offset;
211 if (line && x > Too_far_left) {
212 g.setColor(conf.reference_line_color());
213 g.drawLine(x + Line_offset, bounds.y,
214 x + Line_offset, bounds.y + bounds.height);
215 }
216 if (year && is_indicator()) {
217 int y = p.left();
218 if (two_digit) y %= 100;
219 String ys = String.valueOf(y);
220 if (y < 10) ys = "0" + ys;
221
222 g.setColor(conf.text_color());
223 g.drawString(ys, year_x, Year_y);
224 }
225 }
226 }