Normand Briere
2018-07-11 1e74123cfed4374b403574b6cd16bd8d4e73bf45
Refactoring.
12 files modified
2314 ■■■■ changed files
timeflow/app/TimeflowApp.java 12 ●●●●● patch | view | raw | blame | history
timeflow/app/ui/LinkTabPane.java 414 ●●●● patch | view | raw | blame | history
timeflow/data/time/RoughTime.java 3 ●●●● patch | view | raw | blame | history
timeflow/data/time/TimeUnit.java 472 ●●●● patch | view | raw | blame | history
timeflow/format/file/HtmlFormat.java 264 ●●●● patch | view | raw | blame | history
timeflow/views/AbstractVisualizationView.java 8 ●●●● patch | view | raw | blame | history
timeflow/views/ListView.java 499 ●●●● patch | view | raw | blame | history
timeflow/views/TimelineView.java 94 ●●●● patch | view | raw | blame | history
timeflow/vis/Mouseover.java 176 ●●●● patch | view | raw | blame | history
timeflow/vis/VisualAct.java 1 ●●●● patch | view | raw | blame | history
timeflow/vis/timeline/AxisRenderer.java 151 ●●●● patch | view | raw | blame | history
timeflow/vis/timeline/AxisTicMarks.java 220 ●●●● patch | view | raw | blame | history
timeflow/app/TimeflowApp.java
....@@ -35,7 +35,8 @@
3535 public JMenu filterMenu;
3636 JMenuItem save = new JMenuItem("Save");
3737 FilterControlPanel filterControlPanel;
38
- LinkTabPane leftPanel;
38
+ //LinkTabPane
39
+ JTabbedPane leftPanel;
3940 TFListener filterMenuMaker = new TFListener()
4041 {
4142 @Override
....@@ -90,14 +91,15 @@
9091
9192 // left tab area, with vertical gray divider.
9293 JPanel leftHolder = new JPanel();
93
- container.add(leftHolder, BorderLayout.WEST);
94
+ container.add(leftHolder, BorderLayout.EAST); // WEST);
9495
9596 leftHolder.setLayout(new BorderLayout());
9697 JPanel pad = new Pad(3, 3);
9798 pad.setBackground(Color.gray);
9899 leftHolder.add(pad, BorderLayout.EAST);
99100
100
- leftPanel = new LinkTabPane();//JTabbedPane();
101
+ leftPanel = new //LinkTabPane();
102
+ JTabbedPane();
101103 leftHolder.add(leftPanel, BorderLayout.CENTER);
102104
103105 JPanel configPanel = new JPanel();
....@@ -112,9 +114,9 @@
112114 configPanel.add(legend, BorderLayout.CENTER);
113115 legend.add(new SizeLegendPanel(model), BorderLayout.NORTH);
114116 legend.add(new ColorLegendPanel(model), BorderLayout.CENTER);
115
- leftPanel.addTab(configPanel, "Display", true);
117
+ leftPanel.add(configPanel, "Display"); //, true);
116118
117
- leftPanel.addTab(filterControlPanel, "Filter", true);
119
+ leftPanel.add(filterControlPanel, "Filter"); //, true);
118120
119121 // center tab area
120122
timeflow/app/ui/LinkTabPane.java
....@@ -8,201 +8,225 @@
88 import java.util.*;
99
1010 // custom JTabbedPane-like thing.
11
-public class LinkTabPane extends JPanel {
12
-
13
- ArrayList<String> tabNames=new ArrayList<String>();
14
- HashMap<String, JComponent> tabMap=new HashMap<String, JComponent>();
15
- String currentName;
16
- CardLayout cards=new CardLayout();
17
- JPanel center=new JPanel();
18
- LinkTop top=new LinkTop();
19
-
20
- public LinkTabPane()
21
- {
22
- setBackground(Color.white);
23
- setLayout(new BorderLayout());
24
- add(top, BorderLayout.NORTH);
25
- add(center, BorderLayout.CENTER);
26
- center.setLayout(cards);
27
- top.addMouseListener(new MouseAdapter() {
28
- @Override
29
- public void mousePressed(MouseEvent e) {
30
- String s=top.getName(e.getX());
31
- if (s!=null)
32
- {
33
- String old=currentName;
34
- setCurrentName(s);
35
- firePropertyChange("tab", old, s);
36
- }
37
- }});
38
- }
39
-
40
- public String getTitleAt(int i)
41
- {
42
- return tabNames.get(i);
43
- }
44
-
45
- public void setSelectedIndex(int i)
46
- {
47
- setCurrentName(getTitleAt(i));
48
- }
49
-
50
- public void addTab(JComponent component, String name, boolean left)
51
- {
52
- tabNames.add(name);
53
- tabMap.put(name, component);
54
- center.add(component, name);
55
- top.addName(name, left);
56
- repaint();
57
- if (currentName==null)
58
- currentName=name;
59
- }
60
-
61
- public String getCurrentName()
62
- {
63
- return currentName;
64
- }
65
-
66
- public void setCurrentName(final String currentName)
67
- {
68
- this.currentName=currentName;
69
- top.repaint();
70
- SwingUtilities.invokeLater(new Runnable() {public void run() {cards.show(center, currentName);}});
11
+public class LinkTabPane extends JPanel
12
+{
7113
72
- }
73
-
74
- class LinkTop extends JPanel
75
- {
76
- int left, right;
77
- ArrayList<HotLink> leftHots=new ArrayList<HotLink>();
78
- ArrayList<HotLink> rightHots=new ArrayList<HotLink>();
79
- Font font=new Font("Verdana", Font.PLAIN, 14);
80
- FontMetrics fm=getFontMetrics(font);
81
-
82
- LinkTop()
83
- {
84
- setLayout(new FlowLayout(FlowLayout.LEFT));
85
- setBackground(new Color(220,220,220));
86
- }
87
-
88
- public void paintComponent(Graphics g1)
89
- {
90
- int w=getSize().width, h=getSize().height;
91
- Graphics2D g=(Graphics2D)g1;
92
- g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
93
- g.setColor(getBackground());
94
- g.fillRect(0,0,w,h);
95
- g.setColor(Color.gray);
96
- for (int i=0; i<2; i++)
97
- {
98
- g.drawLine(0,i,w,i);
99
- g.drawLine(0,h-1-i,w,h-1-i);
100
- }
101
-
102
- for (HotLink hot: leftHots)
103
- {
104
- draw(g, hot, h, 0);
105
- }
106
-
107
- for (HotLink hot: rightHots)
108
- {
109
- draw(g, hot, h, w);
110
- }
111
-
112
- for (int i=0; i<leftHots.size(); i++)
113
- {
114
-
115
- if (i<leftHots.size()-1)
116
- {
117
- HotLink hot=leftHots.get(i);
118
- for (int j=0; j<1; j++)
119
- g.drawLine(hot.x+hot.width-1-j, 7, hot.x+hot.width-1-j, h-7);
120
- }
121
- }
122
-
123
- for (int i=0; i<rightHots.size(); i++)
124
- {
125
-
126
- if (i<rightHots.size()-1)
127
- {
128
- HotLink hot=rightHots.get(i);
129
- for (int j=0; j<1; j++)
130
- g.drawLine(hot.x+w-1-j, 7, hot.x+w-1-j, h-7);
131
- }
132
- }
133
- }
134
-
135
- void draw(Graphics g, HotLink hot, int h, int dx)
136
- {
137
- int x=hot.x+dx;
138
- if (hot.s.equals(currentName))
139
- {
140
- g.setColor(Color.lightGray);
141
- g.fillRect(x,2,hot.width,h-4);
142
- g.setColor(Color.gray);
143
- g.drawLine(x-1, 0, x-1, h);
144
- g.drawLine(x+hot.width-1, 0, x+hot.width-1, h);
145
- }
146
- g.setColor(Color.darkGray);
147
- g.setFont(font);
148
- int sw=fm.stringWidth(hot.s);
149
- g.drawString(hot.s, x+(hot.width-sw)/2, h-10);
150
-
151
- }
152
-
153
- String getName(int x)
154
- {
155
- for (HotLink h: leftHots)
156
- {
157
- if (h.x<=x && h.x+h.width>x)
158
- return h.s;
159
- }
160
- for (HotLink h: rightHots)
161
- {
162
- int w=getSize().width;
163
- if (h.x+w<=x && h.x+h.width+w>x)
164
- return h.s;
165
- }
14
+ ArrayList<String> tabNames = new ArrayList<String>();
15
+ HashMap<String, JComponent> tabMap = new HashMap<String, JComponent>();
16
+ String currentName;
17
+ CardLayout cards = new CardLayout();
18
+ JPanel center = new JPanel();
19
+ LinkTop top = new LinkTop();
16620
167
- if (leftHots.size()>0)
168
- return leftHots.get(leftHots.size()-1).s;
169
- if (rightHots.size()>0)
170
- return rightHots.get(0).s;
171
- return null;
172
- }
173
-
174
- void addName(String name, boolean leftward)
175
- {
176
- if (leftward)
177
- {
178
- int x=right;
179
- int w=fm.stringWidth(name)+24;
180
- leftHots.add(new HotLink(name, x, 0, w, 30));
181
- right+=w;
182
- }
183
- else
184
- {
185
- int x=left;
186
- int w=fm.stringWidth(name)+24;
187
- rightHots.add(new HotLink(name, x-w, 0, w, 30));
188
- left-=w;
189
- }
190
- }
191
-
192
- class HotLink extends Rectangle
193
- {
194
- String s;
195
- HotLink(String s, int x, int y, int w, int h)
196
- {
197
- super(x,y,w,h);
198
- this.s=s;
199
- }
200
- }
201
-
202
- public Dimension getPreferredSize()
203
- {
204
- return new Dimension(30,30);
205
- }
206
- }
207
-
21
+ public LinkTabPane()
22
+ {
23
+ setBackground(Color.white);
24
+ setLayout(new BorderLayout());
25
+ add(top, BorderLayout.NORTH);
26
+ add(center, BorderLayout.CENTER);
27
+ center.setLayout(cards);
28
+ top.addMouseListener(new MouseAdapter()
29
+ {
30
+
31
+ @Override
32
+ public void mousePressed(MouseEvent e)
33
+ {
34
+ String s = top.getName(e.getX());
35
+ if (s != null)
36
+ {
37
+ String old = currentName;
38
+ setCurrentName(s);
39
+ firePropertyChange("tab", old, s);
40
+ }
41
+ }
42
+ });
43
+ }
44
+
45
+ public String getTitleAt(int i)
46
+ {
47
+ return tabNames.get(i);
48
+ }
49
+
50
+ public void setSelectedIndex(int i)
51
+ {
52
+ setCurrentName(getTitleAt(i));
53
+ }
54
+
55
+ public void addTab(JComponent component, String name, boolean left)
56
+ {
57
+ tabNames.add(name);
58
+ tabMap.put(name, component);
59
+ center.add(component, name);
60
+ top.addName(name, left);
61
+ repaint();
62
+ if (currentName == null)
63
+ {
64
+ currentName = name;
65
+ }
66
+ }
67
+
68
+ public String getCurrentName()
69
+ {
70
+ return currentName;
71
+ }
72
+
73
+ public void setCurrentName(final String currentName)
74
+ {
75
+ this.currentName = currentName;
76
+ top.repaint();
77
+ SwingUtilities.invokeLater(new Runnable()
78
+ {
79
+ public void run()
80
+ {
81
+ cards.show(center, currentName);
82
+ }
83
+ });
84
+
85
+ }
86
+
87
+ class LinkTop extends JPanel
88
+ {
89
+ int left, right;
90
+ ArrayList<HotLink> leftHots = new ArrayList<HotLink>();
91
+ ArrayList<HotLink> rightHots = new ArrayList<HotLink>();
92
+ Font font = new Font("Verdana", Font.PLAIN, 14);
93
+ FontMetrics fm = getFontMetrics(font);
94
+
95
+ LinkTop()
96
+ {
97
+ setLayout(new FlowLayout(FlowLayout.LEFT));
98
+ setBackground(new Color(220, 220, 220));
99
+ }
100
+
101
+ public void paintComponent(Graphics g1)
102
+ {
103
+ int w = getSize().width, h = getSize().height;
104
+ Graphics2D g = (Graphics2D) g1;
105
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
106
+ g.setColor(getBackground());
107
+ g.fillRect(0, 0, w, h);
108
+ g.setColor(Color.gray);
109
+ for (int i = 0; i < 2; i++)
110
+ {
111
+ g.drawLine(0, i, w, i);
112
+ g.drawLine(0, h - 1 - i, w, h - 1 - i);
113
+ }
114
+
115
+ for (HotLink hot : leftHots)
116
+ {
117
+ draw(g, hot, h, 0);
118
+ }
119
+
120
+ for (HotLink hot : rightHots)
121
+ {
122
+ draw(g, hot, h, w);
123
+ }
124
+
125
+ for (int i = 0; i < leftHots.size(); i++)
126
+ {
127
+
128
+ if (i < leftHots.size() - 1)
129
+ {
130
+ HotLink hot = leftHots.get(i);
131
+ for (int j = 0; j < 1; j++)
132
+ {
133
+ g.drawLine(hot.x + hot.width - 1 - j, 7, hot.x + hot.width - 1 - j, h - 7);
134
+ }
135
+ }
136
+ }
137
+
138
+ for (int i = 0; i < rightHots.size(); i++)
139
+ {
140
+
141
+ if (i < rightHots.size() - 1)
142
+ {
143
+ HotLink hot = rightHots.get(i);
144
+ for (int j = 0; j < 1; j++)
145
+ {
146
+ g.drawLine(hot.x + w - 1 - j, 7, hot.x + w - 1 - j, h - 7);
147
+ }
148
+ }
149
+ }
150
+ }
151
+
152
+ void draw(Graphics g, HotLink hot, int h, int dx)
153
+ {
154
+ int x = hot.x + dx;
155
+ if (hot.s.equals(currentName))
156
+ {
157
+ g.setColor(Color.lightGray);
158
+ g.fillRect(x, 2, hot.width, h - 4);
159
+ g.setColor(Color.gray);
160
+ g.drawLine(x - 1, 0, x - 1, h);
161
+ g.drawLine(x + hot.width - 1, 0, x + hot.width - 1, h);
162
+ }
163
+ g.setColor(Color.darkGray);
164
+ g.setFont(font);
165
+ int sw = fm.stringWidth(hot.s);
166
+ g.drawString(hot.s, x + (hot.width - sw) / 2, h - 10);
167
+
168
+ }
169
+
170
+ String getName(int x)
171
+ {
172
+ for (HotLink h : leftHots)
173
+ {
174
+ if (h.x <= x && h.x + h.width > x)
175
+ {
176
+ return h.s;
177
+ }
178
+ }
179
+ for (HotLink h : rightHots)
180
+ {
181
+ int w = getSize().width;
182
+ if (h.x + w <= x && h.x + h.width + w > x)
183
+ {
184
+ return h.s;
185
+ }
186
+ }
187
+
188
+ if (leftHots.size() > 0)
189
+ {
190
+ return leftHots.get(leftHots.size() - 1).s;
191
+ }
192
+ if (rightHots.size() > 0)
193
+ {
194
+ return rightHots.get(0).s;
195
+ }
196
+ return null;
197
+ }
198
+
199
+ void addName(String name, boolean leftward)
200
+ {
201
+ if (leftward)
202
+ {
203
+ int x = right;
204
+ int w = fm.stringWidth(name) + 24;
205
+ leftHots.add(new HotLink(name, x, 0, w, 30));
206
+ right += w;
207
+ } else
208
+ {
209
+ int x = left;
210
+ int w = fm.stringWidth(name) + 24;
211
+ rightHots.add(new HotLink(name, x - w, 0, w, 30));
212
+ left -= w;
213
+ }
214
+ }
215
+
216
+ class HotLink extends Rectangle
217
+ {
218
+ String s;
219
+
220
+ HotLink(String s, int x, int y, int w, int h)
221
+ {
222
+ super(x, y, w, h);
223
+ this.s = s;
224
+ }
225
+ }
226
+
227
+ public Dimension getPreferredSize()
228
+ {
229
+ return new Dimension(30, 30);
230
+ }
231
+ }
208232 }
timeflow/data/time/RoughTime.java
....@@ -100,7 +100,8 @@
100100
101101 public String format()
102102 {
103
- return units.formatFull(time);
103
+ //return units.formatFull(time);
104
+ return TimeUnit.SECOND.formatFull(time);
104105 }
105106
106107 public static int compare(RoughTime t1, RoughTime t2)
timeflow/data/time/TimeUnit.java
....@@ -3,241 +3,255 @@
33 import java.util.*;
44 import java.text.*;
55
6
-public class TimeUnit {
6
+public class TimeUnit
7
+{
78
8
- public static final TimeUnit YEAR=new TimeUnit("Years", Calendar.YEAR, 365*24*60*60*1000L, "yyyy", "yyyy");
9
- public static final TimeUnit MONTH=new TimeUnit("Months", Calendar.MONTH, 30*24*60*60*1000L, "MMM", "MMM yyyy");
10
- public static final TimeUnit WEEK=new TimeUnit("Weeks", Calendar.WEEK_OF_YEAR, 7*24*60*60*1000L, "d", "MMM d yyyy");
11
- public static final TimeUnit DAY=new TimeUnit("Days", Calendar.DAY_OF_MONTH, 24*60*60*1000L, "d", "MMM d yyyy");
12
- public static final TimeUnit DAY_OF_WEEK=new TimeUnit("Days", Calendar.DAY_OF_WEEK, 24*60*60*1000L, "d", "MMM d yyyy");
13
- public static final TimeUnit HOUR=new TimeUnit("Hours", Calendar.HOUR_OF_DAY, 60*60*1000L, "kk:mm", "MMM d yyyy kk:mm");
14
- public static final TimeUnit MINUTE=new TimeUnit("Minutes", Calendar.MINUTE, 60*1000L, ":mm", "MMM d yyyy kk:mm");
15
- public static final TimeUnit SECOND=new TimeUnit("Seconds", Calendar.SECOND, 1000L, ":ss", "MMM d yyyy kk:mm:ss");
16
- public static final TimeUnit DECADE=multipleYears(10);
17
- public static final TimeUnit CENTURY=multipleYears(100);
18
-
19
- private static final double DAY_SIZE=24*60*60*1000L;
20
-
21
- private int quantity;
22
- private long roughSize;
23
- private SimpleDateFormat format, fullFormat;
24
- private String name;
25
- private int calendarCode;
26
-
27
- private TimeUnit()
28
- {
29
- }
30
-
31
- private TimeUnit(String name, int calendarCode, long roughSize, String formatPattern, String fullFormatPattern)
32
- {
33
- this.name=name;
34
- this.calendarCode=calendarCode;
35
- this.roughSize=roughSize;
36
- format=new SimpleDateFormat(formatPattern);
37
- fullFormat=new SimpleDateFormat(fullFormatPattern);
38
- quantity=1;
39
- }
40
-
41
- public String toString()
42
- {
43
- return "[TimeUnit: "+name+"]";
44
- }
9
+ public static final TimeUnit YEAR = new TimeUnit("Years", Calendar.YEAR, 365 * 24 * 60 * 60 * 1000L, "yyyy", "yyyy");
10
+ public static final TimeUnit MONTH = new TimeUnit("Months", Calendar.MONTH, 30 * 24 * 60 * 60 * 1000L, "MMM", "MMM yyyy");
11
+ public static final TimeUnit WEEK = new TimeUnit("Weeks", Calendar.WEEK_OF_YEAR, 7 * 24 * 60 * 60 * 1000L, "d", "MMM d yyyy");
12
+ public static final TimeUnit DAY = new TimeUnit("Days", Calendar.DAY_OF_MONTH, 24 * 60 * 60 * 1000L, "d", "MMM d yyyy");
13
+ public static final TimeUnit DAY_OF_WEEK = new TimeUnit("Days", Calendar.DAY_OF_WEEK, 24 * 60 * 60 * 1000L, "d", "MMM d yyyy");
14
+ public static final TimeUnit HOUR = new TimeUnit("Hours", Calendar.HOUR_OF_DAY, 60 * 60 * 1000L, "kk:mm", "MMM d yyyy kk:mm");
15
+ public static final TimeUnit MINUTE = new TimeUnit("Minutes", Calendar.MINUTE, 60 * 1000L, ":mm", "MMM d yyyy kk:mm");
16
+ public static final TimeUnit SECOND = new TimeUnit("Seconds", Calendar.SECOND, 1000L, ":ss", "MMM d yyyy kk:mm:ss");
17
+ public static final TimeUnit DECADE = multipleYears(10);
18
+ public static final TimeUnit CENTURY = multipleYears(100);
19
+ private static final double DAY_SIZE = 24 * 60 * 60 * 1000L;
20
+ private int quantity;
21
+ private long roughSize;
22
+ private SimpleDateFormat format, fullFormat;
23
+ private String name;
24
+ private int calendarCode;
4525
46
- public static TimeUnit multipleYears(int numYears)
47
- {
48
- TimeUnit t=new TimeUnit();
49
- t.name=numYears+" Years";
50
- t.calendarCode=Calendar.YEAR;
51
- t.roughSize=YEAR.roughSize*numYears;
52
- t.format=YEAR.format;
53
- t.fullFormat=YEAR.fullFormat;
54
- t.quantity=numYears;
55
- return t;
56
- }
57
-
58
- public static TimeUnit multipleWeeks(int num)
59
- {
60
- TimeUnit t=new TimeUnit();
61
- t.name=num+" Weeks";
62
- t.calendarCode=Calendar.WEEK_OF_YEAR;
63
- t.roughSize=WEEK.roughSize*num;
64
- t.format=WEEK.format;
65
- t.fullFormat=WEEK.fullFormat;
66
- t.quantity=num;
67
- return t;
68
- }
69
-
70
- public TimeUnit times(int quantity)
71
- {
72
- TimeUnit t=new TimeUnit();
73
- t.name=quantity+" "+this.name;
74
- t.calendarCode=this.calendarCode;
75
- t.roughSize=this.roughSize*quantity;
76
- t.format=this.format;
77
- t.fullFormat=this.fullFormat;
78
- t.quantity=quantity;
79
- return t;
80
-
81
- }
26
+ private TimeUnit()
27
+ {
28
+ }
8229
83
-
84
- public int numUnitsIn(TimeUnit u)
85
- {
86
- return (int)Math.round(u.getRoughSize()/(double)getRoughSize());
87
- }
88
-
89
- public boolean isDayOrLess()
90
- {
91
- return roughSize <= 24*60*60*1000L;
92
- }
93
-
94
- public RoughTime roundDown(long timestamp)
95
- {
96
- return round(timestamp, false);
97
- }
98
-
99
- public RoughTime roundUp(long timestamp)
100
- {
101
- return round(timestamp, true);
102
- }
103
-
104
- private static final int[] calendarUnits={Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH, Calendar.MONTH, Calendar.YEAR};
105
- public RoughTime round(long timestamp, boolean up)
106
- {
107
- Calendar c=TimeUtils.cal(timestamp);
108
-
109
- if (calendarCode==Calendar.WEEK_OF_YEAR )
110
- {
111
- c.set(Calendar.DAY_OF_WEEK, c.getMinimum(Calendar.DAY_OF_WEEK));
112
- }
113
- else
114
- {
115
-
116
- // set to minimum all fields of finer granularity.
117
- int roundingCode=calendarCode;
118
- if (calendarCode==Calendar.WEEK_OF_YEAR || calendarCode==Calendar.DAY_OF_WEEK)
119
- roundingCode=Calendar.DAY_OF_MONTH;
120
- for (int i=0; i<calendarUnits.length; i++)
121
- {
122
- if (calendarUnits[i]==roundingCode)
123
- break;
124
- if (i==calendarUnits.length-1)
125
- throw new IllegalArgumentException("Unsupported Calendar Unit: "+calendarCode);
126
- c.set(calendarUnits[i], c.getMinimum(calendarUnits[i]));
127
- }
128
- if (quantity>1)
129
- {
130
- c.set(calendarCode, quantity*(c.get(calendarCode)/quantity));
131
- }
132
- }
133
-
134
- // if rounding up, then add a unit at current granularity.
135
- if (up)
136
- c.add(calendarCode, quantity);
137
-
138
- return new RoughTime(c.getTimeInMillis(), this);
139
- }
140
-
141
- public int get(long timestamp)
142
- {
143
- Calendar c= TimeUtils.cal(timestamp);
144
- int n=c.get(calendarCode);
145
- return quantity==1 ? n : n%quantity;
146
- }
147
-
148
- public void addTo(RoughTime r)
149
- {
150
- addTo(r,1);
151
- }
152
-
153
- public void addTo(RoughTime r, int times)
154
- {
155
- Calendar c=TimeUtils.cal(r.getTime());
156
- c.add(calendarCode, quantity*times);
157
- r.setTime(c.getTimeInMillis());
158
- }
159
-
160
- // Finding the difference between two dates, in a given unit of time,
161
- // is much subtler than you'd think! And annoyingly, the Calendar class does not do
162
- // this for you, even though it actually "knows" how to do so since it
163
- // can add fields.
164
- //
165
- // The most vexing problem is dealing with daylight savings time,
166
- // which means that one day a year has 23 hours and one day has 25 hours.
167
- // We also have to handle the fact that months and years aren't constant lengths.
168
- //
169
- // Rather than write all this ourselves, in this code we
170
- // use the Calendar class to do the heavy lifting.
171
- public long difference(long x, long y)
172
- {
173
- // If this is not one of the hard cases,
174
- // just divide the timespan by the length of time unit.
175
- // Note that we're not worrying about hours and daylight savings time.
176
- if (calendarCode!=Calendar.YEAR && calendarCode!=Calendar.MONTH &&
177
- calendarCode!=Calendar.DAY_OF_MONTH && calendarCode!=Calendar.DAY_OF_WEEK &&
178
- calendarCode!=Calendar.WEEK_OF_YEAR)
179
- {
180
- return (x-y)/roughSize;
181
- }
182
-
183
- Calendar c1=TimeUtils.cal(x), c2=TimeUtils.cal(y);
184
- int diff=0;
185
- switch (calendarCode)
186
- {
187
- case Calendar.YEAR:
188
- return (c1.get(Calendar.YEAR)-c2.get(Calendar.YEAR))/quantity;
189
-
190
- case Calendar.MONTH:
191
- diff= 12*(c1.get(Calendar.YEAR)-c2.get(Calendar.YEAR))+
192
- c1.get(Calendar.MONTH)-c2.get(Calendar.MONTH);
193
- return diff/quantity;
194
-
195
- case Calendar.DAY_OF_MONTH:
196
- case Calendar.DAY_OF_WEEK:
197
- case Calendar.DAY_OF_YEAR:
198
- case Calendar.WEEK_OF_MONTH:
199
- case Calendar.WEEK_OF_YEAR:
200
- // This is ugly, but believe me, it beats the alternative methods :-)
201
- // We use the Calendar class's knowledge of daylight savings time.
202
- // and also the fact that if we calculate this naively, then we aren't going
203
- // to be off by more than one in either direction.
204
- int naive=(int)Math.round((x-y)/(double)roughSize);
205
- c2.add(calendarCode, naive*quantity);
206
- if (c1.get(calendarCode)==c2.get(calendarCode))
207
- return naive/quantity;
208
- c2.add(calendarCode, quantity);
209
- if (c1.get(calendarCode)==c2.get(calendarCode))
210
- return naive/quantity+1;
211
- return naive/quantity-1;
212
- }
213
- throw new IllegalArgumentException("Unexpected calendar code: "+calendarCode);
214
- }
30
+ private TimeUnit(String name, int calendarCode, long roughSize, String formatPattern, String fullFormatPattern)
31
+ {
32
+ this.name = name;
33
+ this.calendarCode = calendarCode;
34
+ this.roughSize = roughSize;
35
+ format = new SimpleDateFormat(formatPattern);
36
+ fullFormat = new SimpleDateFormat(fullFormatPattern);
37
+ quantity = 1;
38
+ }
21539
216
- public long approxNumInRange(long start, long end)
217
- {
218
- return 1+(end-start)/roughSize;
219
- }
220
-
221
- public long getRoughSize() {
222
- return roughSize;
223
- }
40
+ public String toString()
41
+ {
42
+ return "[TimeUnit: " + name + "]";
43
+ }
22444
225
- public String format(Date date)
226
- {
227
- return format.format(date);
228
- }
45
+ public static TimeUnit multipleYears(int numYears)
46
+ {
47
+ TimeUnit t = new TimeUnit();
48
+ t.name = numYears + " Years";
49
+ t.calendarCode = Calendar.YEAR;
50
+ t.roughSize = YEAR.roughSize * numYears;
51
+ t.format = YEAR.format;
52
+ t.fullFormat = YEAR.fullFormat;
53
+ t.quantity = numYears;
54
+ return t;
55
+ }
22956
230
- public String formatFull(Date date)
231
- {
232
- return fullFormat.format(date);
233
- }
57
+ public static TimeUnit multipleWeeks(int num)
58
+ {
59
+ TimeUnit t = new TimeUnit();
60
+ t.name = num + " Weeks";
61
+ t.calendarCode = Calendar.WEEK_OF_YEAR;
62
+ t.roughSize = WEEK.roughSize * num;
63
+ t.format = WEEK.format;
64
+ t.fullFormat = WEEK.fullFormat;
65
+ t.quantity = num;
66
+ return t;
67
+ }
23468
235
- public String formatFull(long timestamp)
236
- {
237
- return fullFormat.format(new Date(timestamp));
238
- }
69
+ public TimeUnit times(int quantity)
70
+ {
71
+ TimeUnit t = new TimeUnit();
72
+ t.name = quantity + " " + this.name;
73
+ t.calendarCode = this.calendarCode;
74
+ t.roughSize = this.roughSize * quantity;
75
+ t.format = this.format;
76
+ t.fullFormat = this.fullFormat;
77
+ t.quantity = quantity;
78
+ return t;
23979
240
- public String getName() {
241
- return name;
242
- }
80
+ }
81
+
82
+ public int numUnitsIn(TimeUnit u)
83
+ {
84
+ return (int) Math.round(u.getRoughSize() / (double) getRoughSize());
85
+ }
86
+
87
+ public boolean isDayOrLess()
88
+ {
89
+ return roughSize <= 24 * 60 * 60 * 1000L;
90
+ }
91
+
92
+ public RoughTime roundDown(long timestamp)
93
+ {
94
+ return round(timestamp, false);
95
+ }
96
+
97
+ public RoughTime roundUp(long timestamp)
98
+ {
99
+ return round(timestamp, true);
100
+ }
101
+ private static final int[] calendarUnits =
102
+ {
103
+ Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH, Calendar.MONTH, Calendar.YEAR
104
+ };
105
+
106
+ public RoughTime round(long timestamp, boolean up)
107
+ {
108
+ Calendar c = TimeUtils.cal(timestamp);
109
+
110
+ if (calendarCode == Calendar.WEEK_OF_YEAR)
111
+ {
112
+ c.set(Calendar.DAY_OF_WEEK, c.getMinimum(Calendar.DAY_OF_WEEK));
113
+ } else
114
+ {
115
+
116
+ // set to minimum all fields of finer granularity.
117
+ int roundingCode = calendarCode;
118
+ if (calendarCode == Calendar.WEEK_OF_YEAR || calendarCode == Calendar.DAY_OF_WEEK)
119
+ {
120
+ roundingCode = Calendar.DAY_OF_MONTH;
121
+ }
122
+ for (int i = 0; i < calendarUnits.length; i++)
123
+ {
124
+ if (calendarUnits[i] == roundingCode)
125
+ {
126
+ break;
127
+ }
128
+ if (i == calendarUnits.length - 1)
129
+ {
130
+ throw new IllegalArgumentException("Unsupported Calendar Unit: " + calendarCode);
131
+ }
132
+ c.set(calendarUnits[i], c.getMinimum(calendarUnits[i]));
133
+ }
134
+ if (quantity > 1)
135
+ {
136
+ c.set(calendarCode, quantity * (c.get(calendarCode) / quantity));
137
+ }
138
+ }
139
+
140
+ // if rounding up, then add a unit at current granularity.
141
+ if (up)
142
+ {
143
+ c.add(calendarCode, quantity);
144
+ }
145
+
146
+ return new RoughTime(c.getTimeInMillis(), this);
147
+ }
148
+
149
+ public int get(long timestamp)
150
+ {
151
+ Calendar c = TimeUtils.cal(timestamp);
152
+ int n = c.get(calendarCode);
153
+ return quantity == 1 ? n : n % quantity;
154
+ }
155
+
156
+ public void addTo(RoughTime r)
157
+ {
158
+ addTo(r, 1);
159
+ }
160
+
161
+ public void addTo(RoughTime r, int times)
162
+ {
163
+ Calendar c = TimeUtils.cal(r.getTime());
164
+ c.add(calendarCode, quantity * times);
165
+ r.setTime(c.getTimeInMillis());
166
+ }
167
+
168
+ // Finding the difference between two dates, in a given unit of time,
169
+ // is much subtler than you'd think! And annoyingly, the Calendar class does not do
170
+ // this for you, even though it actually "knows" how to do so since it
171
+ // can add fields.
172
+ //
173
+ // The most vexing problem is dealing with daylight savings time,
174
+ // which means that one day a year has 23 hours and one day has 25 hours.
175
+ // We also have to handle the fact that months and years aren't constant lengths.
176
+ //
177
+ // Rather than write all this ourselves, in this code we
178
+ // use the Calendar class to do the heavy lifting.
179
+ public long difference(long x, long y)
180
+ {
181
+ // If this is not one of the hard cases,
182
+ // just divide the timespan by the length of time unit.
183
+ // Note that we're not worrying about hours and daylight savings time.
184
+ if (calendarCode != Calendar.YEAR && calendarCode != Calendar.MONTH
185
+ && calendarCode != Calendar.DAY_OF_MONTH && calendarCode != Calendar.DAY_OF_WEEK
186
+ && calendarCode != Calendar.WEEK_OF_YEAR)
187
+ {
188
+ return (x - y) / roughSize;
189
+ }
190
+
191
+ Calendar c1 = TimeUtils.cal(x), c2 = TimeUtils.cal(y);
192
+ int diff = 0;
193
+ switch (calendarCode)
194
+ {
195
+ case Calendar.YEAR:
196
+ return (c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR)) / quantity;
197
+
198
+ case Calendar.MONTH:
199
+ diff = 12 * (c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR))
200
+ + c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
201
+ return diff / quantity;
202
+
203
+ case Calendar.DAY_OF_MONTH:
204
+ case Calendar.DAY_OF_WEEK:
205
+ case Calendar.DAY_OF_YEAR:
206
+ case Calendar.WEEK_OF_MONTH:
207
+ case Calendar.WEEK_OF_YEAR:
208
+ // This is ugly, but believe me, it beats the alternative methods :-)
209
+ // We use the Calendar class's knowledge of daylight savings time.
210
+ // and also the fact that if we calculate this naively, then we aren't going
211
+ // to be off by more than one in either direction.
212
+ int naive = (int) Math.round((x - y) / (double) roughSize);
213
+ c2.add(calendarCode, naive * quantity);
214
+ if (c1.get(calendarCode) == c2.get(calendarCode))
215
+ {
216
+ return naive / quantity;
217
+ }
218
+ c2.add(calendarCode, quantity);
219
+ if (c1.get(calendarCode) == c2.get(calendarCode))
220
+ {
221
+ return naive / quantity + 1;
222
+ }
223
+ return naive / quantity - 1;
224
+ }
225
+ throw new IllegalArgumentException("Unexpected calendar code: " + calendarCode);
226
+ }
227
+
228
+ public long approxNumInRange(long start, long end)
229
+ {
230
+ return 1 + (end - start) / roughSize;
231
+ }
232
+
233
+ public long getRoughSize()
234
+ {
235
+ return roughSize;
236
+ }
237
+
238
+ public String format(Date date)
239
+ {
240
+ return format.format(date);
241
+ }
242
+
243
+ public String formatFull(Date date)
244
+ {
245
+ return fullFormat.format(date);
246
+ }
247
+
248
+ public String formatFull(long timestamp)
249
+ {
250
+ return fullFormat.format(new Date(timestamp));
251
+ }
252
+
253
+ public String getName()
254
+ {
255
+ return name;
256
+ }
243257 }
timeflow/format/file/HtmlFormat.java
....@@ -9,135 +9,145 @@
99
1010 public class HtmlFormat implements Export
1111 {
12
- TFModel model;
13
- java.util.List<Field> fields;
14
- Field title;
15
-
16
- public HtmlFormat() {}
17
-
18
- public HtmlFormat(TFModel model)
19
- {
20
- setModel(model);
21
- }
22
-
23
- public void setModel(TFModel model)
24
- {
25
- this.model=model;
26
- fields=model.getDB().getFields();
27
- title=model.getDB().getField(VirtualField.LABEL);
28
- }
29
-
30
- @Override
31
- public void export(TFModel model, BufferedWriter out) throws Exception {
32
- setModel(model);
33
- out.write(makeHeader());
34
- for (Act a: model.getDB())
35
- out.write(makeItem(a));
36
- out.write(makeFooter());
37
- out.flush();
38
- }
39
-
40
- public void append(ActList acts, int start, int end, StringBuffer b)
41
- {
42
- for (int i=start; i<end; i++)
43
- {
44
- Act a=acts.get(i);
45
- b.append(makeItem(a,i));
46
- }
47
- }
48
-
49
- private String makeItem(Act act)
50
- {
51
- return makeItem(act, -1);
52
- }
53
-
54
- public String makeItem(Act act, int id)
55
- {
56
- StringBuffer page=new StringBuffer();
57
-
58
-
59
- page.append("<tr><td valign=top align=left width=200><b>");
60
- if (title!=null)
61
- {
62
- Field f=model.getColorField();
63
- Color c=Color.black;
64
- if (f!=null)
65
- {
66
- if (f.getType()==String.class)
67
- c=model.getDisplay().makeColor(act.getString(f));
68
- else
69
- {
70
- String[] tags=act.getTextList(f);
71
- if (tags.length==0)
72
- c=Color.gray;
73
- else
74
- c=model.getDisplay().makeColor(tags[0]);
75
- }
76
- }
77
-
78
- page.append("<font size=+1 color="+htmlColor(c)+">"+act.getString(title)+"</font><br>");
79
- }
80
-
81
- Field startField=model.getDB().getField(VirtualField.START);
82
-
83
- if (startField!=null)
84
- {
85
- page.append("<font color=#999999>"+model.getDisplay().format(
86
- act.getTime(startField))+"</font>");
87
- }
88
- page.append("</b><br>");
89
- if (id>=0)
90
- page.append("<a href=\"e"+id+"\">EDIT</a>");
91
- page.append("<br></td><td valign=top>");
92
- for (Field f: fields)
93
- {
94
- page.append("<b><font color=#003399>"+f.getName()+"</font></b>&nbsp;&nbsp;");
95
- Object val=act.get(f);
96
- if (val instanceof URL)
97
- {
98
- page.append("<a href=\""+val+"\">"+val+"</a>");
99
- }
100
- else
101
- page.append(model.getDisplay().toString(val));
102
- page.append("<br>");
12
+ TFModel model;
13
+ java.util.List<Field> fields;
14
+ Field title;
10315
104
- }
105
- page.append("<br></td></tr>");
16
+ public HtmlFormat()
17
+ {
18
+ }
10619
107
- return page.toString();
108
- }
109
-
110
- public String makeHeader()
111
- {
112
- StringBuffer page=new StringBuffer();
113
- page.append("<html><body><blockquote>");
114
- page.append("<br>File: "+model.getDbFile()+"<br>");
115
- page.append("Source: "+model.getDB().getSource()+"<br><br>");
116
- page.append("<br><br>");
117
- page.append("<table border=0>");
20
+ public HtmlFormat(TFModel model)
21
+ {
22
+ setModel(model);
23
+ }
11824
119
- return page.toString();
120
- }
121
-
122
- public String makeFooter()
123
- {
124
- return "</table></blockquote></body></html>";
125
- }
126
-
127
-
128
- static String htmlColor(Color c)
129
- {
130
- return '#'+hex2(c.getRed())+hex2(c.getGreen())+hex2(c.getBlue());
131
- }
132
-
133
- private static final String hexDigits="0123456789ABCDEF";
134
- private static String hex2(int n)
135
- {
136
- return hexDigits.charAt((n/16)%16)+""+hexDigits.charAt(n%16);
137
- }
138
- @Override
139
- public String getName() {
140
- return "HTML List";
141
- }
25
+ public void setModel(TFModel model)
26
+ {
27
+ this.model = model;
28
+ fields = model.getDB().getFields();
29
+ title = model.getDB().getField(VirtualField.LABEL);
30
+ }
14231
32
+ @Override
33
+ public void export(TFModel model, BufferedWriter out) throws Exception
34
+ {
35
+ setModel(model);
36
+ out.write(makeHeader());
37
+ for (Act a : model.getDB())
38
+ {
39
+ out.write(makeItem(a));
40
+ }
41
+ out.write(makeFooter());
42
+ out.flush();
43
+ }
44
+
45
+ public void append(ActList acts, int start, int end, StringBuffer b)
46
+ {
47
+ for (int i = start; i < end; i++)
48
+ {
49
+ Act a = acts.get(i);
50
+ b.append(makeItem(a, i));
51
+ }
52
+ }
53
+
54
+ private String makeItem(Act act)
55
+ {
56
+ return makeItem(act, -1);
57
+ }
58
+
59
+ public String makeItem(Act act, int id)
60
+ {
61
+ StringBuffer page = new StringBuffer();
62
+
63
+ page.append("<tr><td valign=top align=left width=200><b>");
64
+ if (title != null)
65
+ {
66
+ Field f = model.getColorField();
67
+ Color c = Color.black;
68
+ if (f != null)
69
+ {
70
+ if (f.getType() == String.class)
71
+ {
72
+ c = model.getDisplay().makeColor(act.getString(f));
73
+ } else
74
+ {
75
+ String[] tags = act.getTextList(f);
76
+ if (tags.length == 0)
77
+ {
78
+ c = Color.gray;
79
+ } else
80
+ {
81
+ c = model.getDisplay().makeColor(tags[0]);
82
+ }
83
+ }
84
+ }
85
+
86
+ page.append("<font size=+1 color=" + htmlColor(c) + ">" + act.getString(title) + "</font><br>");
87
+ }
88
+
89
+ Field startField = model.getDB().getField(VirtualField.START);
90
+
91
+ if (startField != null)
92
+ {
93
+ page.append("<font color=#999999>" + model.getDisplay().format(act.getTime(startField)) + "</font>");
94
+ }
95
+ page.append("</b><br>");
96
+ if (id >= 0)
97
+ {
98
+ page.append("<a href=\"e" + id + "\">EDIT</a>");
99
+ }
100
+ page.append("<br></td><td valign=top>");
101
+ for (Field f : fields)
102
+ {
103
+ page.append("<b><font color=#003399>" + f.getName() + "</font></b>&nbsp;&nbsp;");
104
+ Object val = act.get(f);
105
+ if (val instanceof URL)
106
+ {
107
+ page.append("<a href=\"" + val + "\">" + val + "</a>");
108
+ } else
109
+ {
110
+ page.append(model.getDisplay().toString(val));
111
+ }
112
+ page.append("<br>");
113
+
114
+ }
115
+ page.append("<br></td></tr>");
116
+
117
+ return page.toString();
118
+ }
119
+
120
+ public String makeHeader()
121
+ {
122
+ StringBuffer page = new StringBuffer();
123
+ page.append("<html><body><blockquote>");
124
+ page.append("<br>File: " + model.getDbFile() + "<br>");
125
+ page.append("Source: " + model.getDB().getSource() + "<br><br>");
126
+ page.append("<br><br>");
127
+ page.append("<table border=0>");
128
+
129
+ return page.toString();
130
+ }
131
+
132
+ public String makeFooter()
133
+ {
134
+ return "</table></blockquote></body></html>";
135
+ }
136
+
137
+ static String htmlColor(Color c)
138
+ {
139
+ return '#' + hex2(c.getRed()) + hex2(c.getGreen()) + hex2(c.getBlue());
140
+ }
141
+ private static final String hexDigits = "0123456789ABCDEF";
142
+
143
+ private static String hex2(int n)
144
+ {
145
+ return hexDigits.charAt((n / 16) % 16) + "" + hexDigits.charAt(n % 16);
146
+ }
147
+
148
+ @Override
149
+ public String getName()
150
+ {
151
+ return "HTML List";
152
+ }
143153 }
timeflow/views/AbstractVisualizationView.java
....@@ -31,6 +31,10 @@
3131 {
3232 this.model = model;
3333
34
+ final JPopupMenu popup = new JPopupMenu();
35
+ final JMenuItem edit = new JMenuItem("Edit");
36
+ final JMenuItem delete = new JMenuItem("Delete");
37
+
3438 // deal with mouseovers.
3539 addMouseMotionListener(new MouseMotionListener()
3640 {
....@@ -50,9 +54,6 @@
5054 }
5155 });
5256
53
-
54
- final JPopupMenu popup = new JPopupMenu();
55
- final JMenuItem edit = new JMenuItem("Edit");
5657 edit.addActionListener(new ActionListener()
5758 {
5859
....@@ -64,7 +65,6 @@
6465 });
6566 popup.add(edit);
6667
67
- final JMenuItem delete = new JMenuItem("Delete");
6868 popup.add(delete);
6969 delete.addActionListener(new ActionListener()
7070 {
timeflow/views/ListView.java
....@@ -20,247 +20,266 @@
2020 import java.net.URL;
2121 import java.util.*;
2222
23
-public class ListView extends AbstractView {
23
+public class ListView extends AbstractView
24
+{
25
+ private JEditorPane listDisplay;
26
+ private JComboBox sortMenu = new JComboBox();
27
+ private ActComparator sort;//=ActComparator.byTime();
28
+ private int maxPerPage = 50;
29
+ private int pageStart = 0;
30
+ private int lastSize = 0;
31
+ private ActList acts;
32
+ private Field sortField;
33
+ private JLabel pageLabel = new JLabel("Page", JLabel.LEFT);
34
+ private JComboBox pageMenu = new JComboBox();
35
+ private boolean changing = false;
36
+ private JPanel controls;
2437
25
- private JEditorPane listDisplay;
26
- private JComboBox sortMenu=new JComboBox();
27
- private ActComparator sort;//=ActComparator.byTime();
28
- private int maxPerPage=50;
29
- private int pageStart=0;
30
- private int lastSize=0;
31
- private ActList acts;
32
- private Field sortField;
33
-
34
- private JLabel pageLabel=new JLabel("Page", JLabel.LEFT);
35
- private JComboBox pageMenu=new JComboBox();
36
- private boolean changing=false;
37
-
38
- private JPanel controls;
39
-
40
- public ListView(TFModel model)
41
- {
42
- super(model);
43
-
44
- listDisplay=HtmlDisplay.create();
45
- listDisplay.addHyperlinkListener(new LinkIt());
46
- JScrollPane scrollPane = new JScrollPane(listDisplay);
47
- setLayout(new BorderLayout());
48
- add(scrollPane, BorderLayout.CENTER);
49
-
50
-
51
- controls=new JPanel();
52
- controls.setLayout(null);
53
- controls.setBackground(Color.white);
54
-
55
- int x=10, y=10;
56
- int ch=25, pad=5, cw=160;
57
- JLabel sortLabel=new JLabel("Sort Order", JLabel.LEFT);
58
- controls.add(sortLabel);
59
- sortLabel.setBounds(x,y,cw,ch);
60
- y+=ch+pad;
61
-
62
- controls.add(sortMenu);
63
- sortMenu.setBounds(x,y,cw,ch);
64
- y+=ch+3*pad;
65
-
66
- controls.add(pageLabel);
67
- pageLabel.setBounds(x,y,cw,ch);
68
- y+=ch+pad;
69
- controls.add(pageMenu);
70
- pageMenu.setBounds(x,y,cw,ch);
71
-
72
- showPageMenu(false);
73
- pageMenu.addActionListener(pageListener);
74
- sortMenu.addActionListener(sortListener);
75
- }
76
-
77
- protected JComponent _getControls()
78
- {
79
- return controls;
80
- }
81
-
82
- ActionListener sortListener=new ActionListener() {
83
- @Override
84
- public void actionPerformed(ActionEvent e) {
85
- if (changing || sortMenu.getItemCount()<=0) // this means the action was fired after all items removed.
86
- return;
87
- sortField=getModel().getDB().getField((String)sortMenu.getSelectedItem());
88
- sort=sortField==null ? null : ActComparator.by(sortField);
89
- setToFirstPage();
90
- makeList();
91
- }};
92
-
93
- ActionListener pageListener=new ActionListener() {
94
- @Override
95
- public void actionPerformed(ActionEvent e) {
96
- if (changing)
97
- return;
98
- pageStart=maxPerPage*pageMenu.getSelectedIndex();
99
- System.out.println(e.getActionCommand());
100
- makeList();
101
- }};
102
-
103
- @Override
104
- protected void onscreen(boolean majorChange)
105
- {
106
- _note(null);
107
- }
108
-
109
- public void _note(TFEvent e) {
110
- changing=true;
111
- if (e==null || e.affectsSchema() || e.affectsRowSet())
112
- {
113
- sortMenu.removeActionListener(sortListener);
114
- sortMenu.removeAllItems();
115
- pageStart=0;
116
- java.util.List<Field> fields=getModel().getDB().getFields();
117
- Field firstField=null;
118
- if (fields.size()>0)
119
- firstField=fields.get(0);
120
- for (Field f: fields)
121
- {
122
- sortMenu.addItem(f.getName());
123
- }
124
- sortField=getModel().getDB().getField(VirtualField.START);
125
- if (sortField!=null)
126
- sortMenu.setSelectedItem(sortField.getName());
127
- else
128
- sortField=firstField;
129
- sortMenu.addActionListener(sortListener);
130
- sort=null;
131
- }
132
- if (e!=null && e.affectsData())
133
- {
134
- setToFirstPage();
135
- }
136
- changing=false;
137
- makeList();
138
- }
139
-
140
- private void setToFirstPage()
141
- {
142
- pageStart=0;
143
- if (pageMenu.isVisible())
144
- {
145
- pageMenu.removeActionListener(pageListener);
146
- pageMenu.setSelectedIndex(0);
147
- pageMenu.addActionListener(pageListener);
148
- }
149
- }
150
-
151
- void showPageMenu(boolean visible)
152
- {
153
- pageLabel.setVisible(visible);
154
- pageMenu.setVisible(visible);
155
- if (visible)
156
- {
157
- pageMenu.removeActionListener(pageListener);
158
- pageMenu.setSelectedIndex(pageStart/maxPerPage);
159
- pageMenu.addActionListener(pageListener);
160
- }
161
- }
162
-
163
-
164
- void makeList()
165
- {
166
- HtmlFormat html=new HtmlFormat();
167
- html.setModel(getModel());
168
- StringBuffer page=new StringBuffer();
169
-
170
- page.append(html.makeHeader());
171
-
172
-
173
- ActList as=getModel().getActs();
174
- if (as==null || as.size()==0 && getModel().getDB().size()==0)
175
- {
176
- page.append("<tr><td><h1><font color=#003399>Empty Database</font></h1></td></tr>");
177
- showPageMenu(false);
178
- }
179
- else
180
- {
181
-
182
- if (sort==null)
183
- {
184
- Field timeField=getModel().getDB().getField(VirtualField.START);
185
- if (timeField!=null)
186
- sort=ActComparator.by(timeField);
187
- }
38
+ public ListView(TFModel model)
39
+ {
40
+ super(model);
18841
189
- acts=as.copy();
190
- if (sort!=null)
191
- Collections.sort(acts, sort);
192
-
193
- boolean pages=acts.size()>maxPerPage;
194
- int last=Math.min(acts.size(), pageStart+maxPerPage);
195
- if (pages)
196
- {
197
- int n=acts.size();
198
- if (lastSize!=n)
199
- {
200
- pageMenu.removeActionListener(pageListener);
201
- pageMenu.removeAllItems();
202
- for (int i=0; i*maxPerPage<n;i++)
203
- {
204
- pageMenu.addItem("Items "+((i*maxPerPage)+1)+" to "+
205
- Math.min(n, (i+1)*maxPerPage));
206
- }
207
- pageMenu.addActionListener(pageListener);
208
- lastSize=n;
209
- }
210
- }
211
- showPageMenu(pages);
212
-
213
- page.append("<tr><td><h1><font color=#003399>"+(pages? (pageStart+1)+"-"+(last) +" of ": "")+acts.size()+" Events</font></h1>");
214
- page.append("<br><br></td></tr>");
42
+ listDisplay = HtmlDisplay.create();
43
+ listDisplay.addHyperlinkListener(new LinkIt());
44
+ JScrollPane scrollPane = new JScrollPane(listDisplay);
45
+ setLayout(new BorderLayout());
46
+ add(scrollPane, BorderLayout.CENTER);
21547
216
- for (int i=pageStart; i<last; i++)
217
- {
218
- Act a=acts.get(i);
219
- page.append(html.makeItem(a,i));
220
- }
221
- }
222
- page.append(html.makeFooter());
223
- listDisplay.setText(page.toString());
224
- listDisplay.setCaretPosition(0);
225
- repaint();
226
- }
227
-
228
-
229
-
230
-
231
- @Override
232
- public String getName() {
233
- return "List";
234
- }
235
-
236
- static class ArrayRenderer extends DefaultTableCellRenderer {
237
- public void setValue(Object value) {
238
- setText(Display.arrayToString((Object[])value));
239
- }
240
- }
241
-
242
- public class LinkIt implements HyperlinkListener
243
- {
244
- public void hyperlinkUpdate(HyperlinkEvent e)
245
- {
246
- if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED)
247
- return;
248
-
249
- String s=e.getDescription();
250
- System.out.println(s);
251
- if (s.length()>0)
252
- {
253
- char c=s.charAt(0);
254
- if (c=='e') // code for "edit"
255
- {
256
- int i=Integer.parseInt(s.substring(1));
257
- EditRecordPanel.edit(getModel(), acts.get(i));
258
- return;
259
- }
260
-
261
- }
262
- Display.launchBrowser(e.getURL().toString());
263
-
264
- }
265
- }
48
+
49
+ controls = new JPanel();
50
+ controls.setLayout(null);
51
+ controls.setBackground(Color.white);
52
+
53
+ int x = 10, y = 10;
54
+ int ch = 25, pad = 5, cw = 160;
55
+ JLabel sortLabel = new JLabel("Sort Order", JLabel.LEFT);
56
+ controls.add(sortLabel);
57
+ sortLabel.setBounds(x, y, cw, ch);
58
+ y += ch + pad;
59
+
60
+ controls.add(sortMenu);
61
+ sortMenu.setBounds(x, y, cw, ch);
62
+ y += ch + 3 * pad;
63
+
64
+ controls.add(pageLabel);
65
+ pageLabel.setBounds(x, y, cw, ch);
66
+ y += ch + pad;
67
+ controls.add(pageMenu);
68
+ pageMenu.setBounds(x, y, cw, ch);
69
+
70
+ showPageMenu(false);
71
+ pageMenu.addActionListener(pageListener);
72
+ sortMenu.addActionListener(sortListener);
73
+ }
74
+
75
+ protected JComponent _getControls()
76
+ {
77
+ return controls;
78
+ }
79
+ ActionListener sortListener = new ActionListener()
80
+ {
81
+
82
+ @Override
83
+ public void actionPerformed(ActionEvent e)
84
+ {
85
+ if (changing || sortMenu.getItemCount() <= 0) // this means the action was fired after all items removed.
86
+ {
87
+ return;
88
+ }
89
+ sortField = getModel().getDB().getField((String) sortMenu.getSelectedItem());
90
+ sort = sortField == null ? null : ActComparator.by(sortField);
91
+ setToFirstPage();
92
+ makeList();
93
+ }
94
+ };
95
+ ActionListener pageListener = new ActionListener()
96
+ {
97
+
98
+ @Override
99
+ public void actionPerformed(ActionEvent e)
100
+ {
101
+ if (changing)
102
+ {
103
+ return;
104
+ }
105
+ pageStart = maxPerPage * pageMenu.getSelectedIndex();
106
+ System.out.println(e.getActionCommand());
107
+ makeList();
108
+ }
109
+ };
110
+
111
+ @Override
112
+ protected void onscreen(boolean majorChange)
113
+ {
114
+ _note(null);
115
+ }
116
+
117
+ public void _note(TFEvent e)
118
+ {
119
+ changing = true;
120
+ if (e == null || e.affectsSchema() || e.affectsRowSet())
121
+ {
122
+ sortMenu.removeActionListener(sortListener);
123
+ sortMenu.removeAllItems();
124
+ pageStart = 0;
125
+ java.util.List<Field> fields = getModel().getDB().getFields();
126
+ Field firstField = null;
127
+ if (fields.size() > 0)
128
+ {
129
+ firstField = fields.get(0);
130
+ }
131
+ for (Field f : fields)
132
+ {
133
+ sortMenu.addItem(f.getName());
134
+ }
135
+ sortField = getModel().getDB().getField(VirtualField.START);
136
+ if (sortField != null)
137
+ {
138
+ sortMenu.setSelectedItem(sortField.getName());
139
+ } else
140
+ {
141
+ sortField = firstField;
142
+ }
143
+ sortMenu.addActionListener(sortListener);
144
+ sort = null;
145
+ }
146
+ if (e != null && e.affectsData())
147
+ {
148
+ setToFirstPage();
149
+ }
150
+ changing = false;
151
+ makeList();
152
+ }
153
+
154
+ private void setToFirstPage()
155
+ {
156
+ pageStart = 0;
157
+ if (pageMenu.isVisible())
158
+ {
159
+ pageMenu.removeActionListener(pageListener);
160
+ pageMenu.setSelectedIndex(0);
161
+ pageMenu.addActionListener(pageListener);
162
+ }
163
+ }
164
+
165
+ void showPageMenu(boolean visible)
166
+ {
167
+ pageLabel.setVisible(visible);
168
+ pageMenu.setVisible(visible);
169
+ if (visible)
170
+ {
171
+ pageMenu.removeActionListener(pageListener);
172
+ pageMenu.setSelectedIndex(pageStart / maxPerPage);
173
+ pageMenu.addActionListener(pageListener);
174
+ }
175
+ }
176
+
177
+ void makeList()
178
+ {
179
+ HtmlFormat html = new HtmlFormat();
180
+ html.setModel(getModel());
181
+ StringBuffer page = new StringBuffer();
182
+
183
+ page.append(html.makeHeader());
184
+
185
+ ActList as = getModel().getActs();
186
+ if (as == null || as.size() == 0 && getModel().getDB().size() == 0)
187
+ {
188
+ page.append("<tr><td><h1><font color=#003399>Empty Database</font></h1></td></tr>");
189
+ showPageMenu(false);
190
+ } else
191
+ {
192
+
193
+ if (sort == null)
194
+ {
195
+ Field timeField = getModel().getDB().getField(VirtualField.START);
196
+ if (timeField != null)
197
+ {
198
+ sort = ActComparator.by(timeField);
199
+ }
200
+ }
201
+
202
+ acts = as.copy();
203
+ if (sort != null)
204
+ {
205
+ Collections.sort(acts, sort);
206
+ }
207
+
208
+ boolean pages = acts.size() > maxPerPage;
209
+ int last = Math.min(acts.size(), pageStart + maxPerPage);
210
+ if (pages)
211
+ {
212
+ int n = acts.size();
213
+ if (lastSize != n)
214
+ {
215
+ pageMenu.removeActionListener(pageListener);
216
+ pageMenu.removeAllItems();
217
+ for (int i = 0; i * maxPerPage < n; i++)
218
+ {
219
+ pageMenu.addItem("Items " + ((i * maxPerPage) + 1) + " to "
220
+ + Math.min(n, (i + 1) * maxPerPage));
221
+ }
222
+ pageMenu.addActionListener(pageListener);
223
+ lastSize = n;
224
+ }
225
+ }
226
+ showPageMenu(pages);
227
+
228
+ page.append("<tr><td><h1><font color=#003399>" + (pages ? (pageStart + 1) + "-" + (last) + " of " : "") + acts.size() + " Events</font></h1>");
229
+ page.append("<br><br></td></tr>");
230
+
231
+ for (int i = pageStart; i < last; i++)
232
+ {
233
+ Act a = acts.get(i);
234
+ page.append(html.makeItem(a, i));
235
+ }
236
+ }
237
+ page.append(html.makeFooter());
238
+ listDisplay.setText(page.toString());
239
+ listDisplay.setCaretPosition(0);
240
+ repaint();
241
+ }
242
+
243
+ @Override
244
+ public String getName()
245
+ {
246
+ return "List";
247
+ }
248
+
249
+ static class ArrayRenderer extends DefaultTableCellRenderer
250
+ {
251
+
252
+ public void setValue(Object value)
253
+ {
254
+ setText(Display.arrayToString((Object[]) value));
255
+ }
256
+ }
257
+
258
+ public class LinkIt implements HyperlinkListener
259
+ {
260
+
261
+ public void hyperlinkUpdate(HyperlinkEvent e)
262
+ {
263
+ if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED)
264
+ {
265
+ return;
266
+ }
267
+
268
+ String s = e.getDescription();
269
+ System.out.println(s);
270
+ if (s.length() > 0)
271
+ {
272
+ char c = s.charAt(0);
273
+ if (c == 'e') // code for "edit"
274
+ {
275
+ int i = Integer.parseInt(s.substring(1));
276
+ EditRecordPanel.edit(getModel(), acts.get(i));
277
+ return;
278
+ }
279
+
280
+ }
281
+ Display.launchBrowser(e.getURL().toString());
282
+
283
+ }
284
+ }
266285 }
timeflow/views/TimelineView.java
....@@ -1,21 +1,24 @@
11 package timeflow.views;
22
33 import timeflow.app.ui.ComponentCluster;
4
-import timeflow.data.db.*;
4
+import timeflow.app.ui.EditRecordPanel;
5
+import timeflow.data.db.DBUtils;
56 import timeflow.data.time.*;
67 import timeflow.model.*;
7
-import timeflow.views.CalendarView.CalendarPanel;
8
-import timeflow.views.CalendarView.ScrollingCalendar;
9
-import timeflow.vis.*;
8
+//import timeflow.views.CalendarView.CalendarPanel;
9
+//import timeflow.views.CalendarView.ScrollingCalendar;
10
+import timeflow.vis.Mouseover;
11
+import timeflow.vis.TimeScale;
12
+import timeflow.vis.VisualAct;
1013 import timeflow.vis.timeline.*;
1114
1215 import java.awt.*;
1316 import java.awt.event.*;
14
-import java.awt.image.*;
17
+//import java.awt.image.*;
1518
1619 import javax.swing.*;
1720
18
-import java.util.*;
21
+import java.util.ArrayList;
1922
2023 public class TimelineView extends AbstractView
2124 {
....@@ -67,12 +70,23 @@
6770
6871 // top part of grid: zoom buttons.
6972 ComponentCluster buttons = new ComponentCluster("Zoom");
70
- ImageIcon zoomOutIcon = new ImageIcon("images/zoom_out.gif");
71
- JButton zoomOut = new JButton(zoomOutIcon);
73
+ //ImageIcon zoomOutIcon = new ImageIcon("images/zoom_out.gif");
74
+ JButton zoomIn = new JButton("In 1/2X");
75
+ buttons.addContent(zoomIn);
76
+ zoomIn.addActionListener(new ActionListener()
77
+ {
78
+ @Override
79
+ public void actionPerformed(ActionEvent e)
80
+ {
81
+ Interval zoom = visuals.getViewInterval().subinterval(0.333, 0.667).intersection(visuals.getGlobalInterval());
82
+ moveTime(zoom);
83
+ }
84
+ });
85
+
86
+ JButton zoomOut = new JButton("Out 2X");
7287 buttons.addContent(zoomOut);
7388 zoomOut.addActionListener(new ActionListener()
7489 {
75
-
7690 @Override
7791 public void actionPerformed(ActionEvent e)
7892 {
....@@ -82,7 +96,7 @@
8296 });
8397
8498 ImageIcon zoomOut100Icon = new ImageIcon("images/zoom_out_100.gif");
85
- JButton zoomOutAll = new JButton(zoomOut100Icon);
99
+ JButton zoomOutAll = new JButton("Fit 100%");
86100 buttons.addContent(zoomOutAll);
87101 zoomOutAll.addActionListener(new ActionListener()
88102 {
....@@ -221,17 +235,27 @@
221235
222236 public void run()
223237 {
224
- int n = 15;
238
+ int n = 8;
225239 for (int i = 0; i < n; i++)
226240 {
227
- long start = ((n - i) * i1.start + i * i2.start) / n;
228
- long end = ((n - i) * i1.end + i * i2.end) / n;
241
+ final long start = ((n - i) * i1.start + i * i2.start) / n;
242
+ final long end = ((n - i) * i1.end + i * i2.end) / n;
229243 try
230244 {
231
- visuals.setTimeBounds(start, end);
232
- redraw();
245
+// visuals.setTimeBounds(start, end);
246
+// redraw();
247
+ SwingUtilities.invokeAndWait(new Runnable()
248
+ {
249
+
250
+ @Override
251
+ public void run()
252
+ {
253
+ visuals.setTimeBounds(start, end);
254
+ redraw();
255
+ }
256
+ });
233257
234
- sleep(20);
258
+ //sleep(20);
235259 } catch (Exception e)
236260 {
237261 }
....@@ -312,7 +336,20 @@
312336 {
313337 if (e.getClickCount() == 2)
314338 {
315
- moveTime(visuals.getViewInterval().subinterval(.333, .667));
339
+ Point p = new Point(e.getX(), e.getY());
340
+ Mouseover o = find(p);
341
+ //moveTime(visuals.getViewInterval().subinterval(.333, .667));
342
+ boolean onAct = o != null && o.thing instanceof VisualAct;
343
+ if (onAct)
344
+ {
345
+ VisualAct v = (VisualAct) o.thing;
346
+ selectedAct = v.getAct();
347
+ EditRecordPanel.edit(getModel(), selectedAct);
348
+ } else
349
+ {
350
+ selectedTime = getTime(p);
351
+ EditRecordPanel.add(getModel(), selectedTime);
352
+ }
316353 }
317354 }
318355
....@@ -358,6 +395,11 @@
358395 int a = firstMouse.x;
359396 int b = mouse.x;
360397
398
+ if (a == b)
399
+ {
400
+ return;
401
+ }
402
+
361403 long start = visuals.getTimeScale().toTime(a);
362404 long end = visuals.getTimeScale().toTime(b);
363405 if (b - a < 0)
....@@ -397,12 +439,18 @@
397439 @Override
398440 public void mouseWheelMoved(MouseWheelEvent e)
399441 {
400
- //bar.setValue(bar.getValue() + e.getWheelRotation() * 10);
401
- visuals.scale *= Math.exp(e.getWheelRotation()/10.0);
402
- visuals.scale = visuals.layout();
403
- //System.out.println(visuals.scale);
404
- timelinePanel.drawVisualization();
405
- scroller.calibrate();
442
+ if (e.isMetaDown())
443
+ {
444
+ visuals.scale *= Math.exp(e.getWheelRotation()/10.0);
445
+ visuals.scale = visuals.layout();
446
+ //System.out.println(visuals.scale);
447
+ timelinePanel.drawVisualization();
448
+ scroller.calibrate();
449
+ }
450
+ else
451
+ {
452
+ bar.setValue(bar.getValue() + e.getWheelRotation() * 40);
453
+ }
406454 repaint();
407455 }
408456 });
timeflow/vis/Mouseover.java
....@@ -5,90 +5,94 @@
55 import java.awt.*;
66 import java.util.ArrayList;
77
8
-public class Mouseover extends Rectangle {
9
- public Object thing;
10
- public Mouseover(Object thing, int x, int y, int w, int h)
11
- {
12
- super(x,y,w,h);
13
- this.thing=thing;
14
- }
15
-
16
- public void draw(Graphics2D g, int maxW, int maxH, Display display)
17
- {
18
- g.setColor(new Color(0,53,153));
19
- g.setColor(new Color(255,255,0,100));
20
- g.fill(this);
21
- }
22
-
23
- protected void draw(Graphics2D g, int maxW, int maxH, Display display, ArrayList labels, int numLines)
24
- {
25
- if (labels==null || labels.size()==0)
26
- return;
27
-
28
- // draw a background box.
29
-
30
- // find max number of chars, very very roughly!
31
- int boxW=50;
32
- for (int i=0; i<labels.size(); i+=2)
33
- {
34
- if (labels.get(i) instanceof String[])
35
- boxW=300;
36
- else if (labels.get(i) instanceof String)
37
- {
38
- boxW=Math.max(boxW, 50+50*((String)labels.get(i)).length());
39
- }
40
- }
41
-
42
-
43
- boxW=Math.min(350, boxW);
44
- int boxH=18*numLines+10;
45
- int mx=this.x+this.width+5;
46
- int my=this.y+this.height+35;
47
-
48
- // put box in a place where it does not obscure the data
49
- // or go off screen.
50
- if (my+boxH>maxH-10)
51
- {
52
- my=Math.max(10,this.y-boxH-5);
53
- }
54
- if (mx+boxW>maxW-10)
55
- {
56
- mx=Math.max(10,this.x-boxW-10);
57
- }
58
- int ty=my;
59
- g.setColor(new Color(0,0,0,70));
60
- g.fillRoundRect(mx-11, my-16, boxW, boxH,12,12);
61
- g.setColor(Color.white);
62
- g.fillRoundRect(mx-15, my-20, boxW, boxH,12,12);
63
- g.setColor(Color.darkGray);
64
- g.drawRoundRect(mx-15, my-20, boxW, boxH,12,12);
65
-
66
- // finally, draw the darn labels.
67
- for (int i=0; i<labels.size(); i+=2)
68
- {
69
- g.setFont(display.bold());
70
- String field=(String)labels.get(i);
71
- g.drawString(field,mx,ty);
72
- int sw=display.boldFontMetrics().stringWidth(field);
73
- g.setFont(display.plain());
74
- Object o=labels.get(i+1);
75
- if (o instanceof String)
76
- {
77
- g.drawString((String)o,mx+sw+9,ty);
78
- ty+=18;
79
- }
80
- else
81
- {
82
- ArrayList<String> lines=(ArrayList<String>)o;
83
- int dx=sw+9;
84
- for (String line: lines)
85
- {
86
- g.drawString((String)line,mx+dx,ty);
87
- ty+=18;
88
- dx=0;
89
- }
90
- ty+=5;
91
- }
92
- }
93
- }
8
+public class Mouseover extends Rectangle
9
+{
10
+ public Object thing;
11
+
12
+ public Mouseover(Object thing, int x, int y, int w, int h)
13
+ {
14
+ super(x, y, w, h);
15
+ this.thing = thing;
16
+ }
17
+
18
+ public void draw(Graphics2D g, int maxW, int maxH, Display display)
19
+ {
20
+ g.setColor(new Color(0, 53, 153));
21
+ g.setColor(new Color(255, 255, 0, 100));
22
+ g.fill(this);
23
+ }
24
+
25
+ protected void draw(Graphics2D g, int maxW, int maxH, Display display, ArrayList labels, int numLines)
26
+ {
27
+ if (labels == null || labels.size() == 0)
28
+ {
29
+ return;
30
+ }
31
+
32
+ // draw a background box.
33
+
34
+ // find max number of chars, very very roughly!
35
+ int boxW = 50;
36
+ for (int i = 0; i < labels.size(); i += 2)
37
+ {
38
+ if (labels.get(i) instanceof String[])
39
+ {
40
+ boxW = 300;
41
+ } else if (labels.get(i) instanceof String)
42
+ {
43
+ boxW = Math.max(boxW, 50 + 50 * ((String) labels.get(i)).length());
44
+ }
45
+ }
46
+
47
+
48
+ boxW = Math.min(350, boxW);
49
+ int boxH = 18 * numLines + 10;
50
+ int mx = this.x + this.width + 5;
51
+ int my = this.y + this.height + 35;
52
+
53
+ // put box in a place where it does not obscure the data
54
+ // or go off screen.
55
+ if (my + boxH > maxH - 10)
56
+ {
57
+ my = Math.max(10, this.y - boxH - 5);
58
+ }
59
+ if (mx + boxW > maxW - 10)
60
+ {
61
+ mx = Math.max(10, this.x - boxW - 10);
62
+ }
63
+ int ty = my;
64
+ g.setColor(new Color(0, 0, 0, 70));
65
+ g.fillRoundRect(mx - 11, my - 16, boxW, boxH, 12, 12);
66
+ g.setColor(Color.white);
67
+ g.fillRoundRect(mx - 15, my - 20, boxW, boxH, 12, 12);
68
+ g.setColor(Color.darkGray);
69
+ g.drawRoundRect(mx - 15, my - 20, boxW, boxH, 12, 12);
70
+
71
+ // finally, draw the darn labels.
72
+ for (int i = 0; i < labels.size(); i += 2)
73
+ {
74
+ g.setFont(display.bold());
75
+ String field = (String) labels.get(i);
76
+ g.drawString(field, mx, ty);
77
+ int sw = display.boldFontMetrics().stringWidth(field);
78
+ g.setFont(display.plain());
79
+ Object o = labels.get(i + 1);
80
+ if (o instanceof String)
81
+ {
82
+ g.drawString((String) o, mx + sw + 9, ty);
83
+ ty += 18;
84
+ } else
85
+ {
86
+ ArrayList<String> lines = (ArrayList<String>) o;
87
+ int dx = sw + 9;
88
+ for (String line : lines)
89
+ {
90
+ g.drawString((String) line, mx + dx, ty);
91
+ ty += 18;
92
+ dx = 0;
93
+ }
94
+ ty += 5;
95
+ }
96
+ }
97
+ }
9498 }
timeflow/vis/VisualAct.java
....@@ -12,7 +12,6 @@
1212
1313 public class VisualAct implements Comparable
1414 {
15
-
1615 Color color;
1716 String label;
1817 String mouseOver;
timeflow/vis/timeline/AxisRenderer.java
....@@ -9,80 +9,83 @@
99 import timeflow.vis.Mouseover;
1010 import timeflow.vis.TimeScale;
1111
12
-public class AxisRenderer {
13
-
14
- TimelineVisuals visuals;
15
-
16
- public AxisRenderer(TimelineVisuals visuals)
17
- {
18
- this.visuals=visuals;
19
- }
20
-
21
- public void render(Graphics2D g, Collection<Mouseover> objectLocations)
22
- {
23
- TFModel model=visuals.getModel();
24
- g.setColor(model.getDisplay().getColor("chart.background"));
25
- Rectangle bounds=visuals.getBounds();
26
-
27
- TimeScale scale=visuals.getTimeScale();
28
- java.util.List<AxisTicMarks> t=AxisTicMarks.allRelevant(scale.getInterval());
29
-
30
- int dateLabelH=model.getDisplay().getInt("timeline.datelabel.height");
31
- int y=bounds.y+bounds.height-dateLabelH;
32
-
33
- // draw in reverse order so bigger granularity at top.
34
- int n=t.size();
35
- for (int i=0; i<n; i++)
36
- {
37
- render(t.get(i), g, bounds.x, y, dateLabelH-1, bounds.y, i==0, objectLocations);
38
- y-=dateLabelH;
39
- }
40
- }
41
-
42
- void render(AxisTicMarks t, Graphics2D g, int x, int y, int h, int top, boolean full, Collection<Mouseover> objectLocations)
43
- {
44
- TFModel model=visuals.getModel();
12
+public class AxisRenderer
13
+{
14
+ TimelineVisuals visuals;
4515
46
- int n=t.tics.size();
47
- for (int i=0; i<n-1; i++)
48
- {
49
-
50
- long start=t.tics.get(i);
51
- long end=t.tics.get(i+1);
52
-
53
- int x0=Math.max(x,visuals.getTimeScale().toInt(start));
54
- int x1=visuals.getTimeScale().toInt(end);
55
-
56
- int dayOfWeek=TimeUtils.cal(start).get(Calendar.DAY_OF_WEEK);
57
-
58
- g.setColor(t.unit.isDayOrLess() && (dayOfWeek==1 || dayOfWeek==7) ?
59
- new Color(245,245,245) : new Color(240,240,240));
16
+ public AxisRenderer(TimelineVisuals visuals)
17
+ {
18
+ this.visuals = visuals;
19
+ }
6020
61
- g.fillRect(x0, y, x1-x0-1, h);
62
- g.setColor(Color.white);
63
- g.drawLine(x1-1, y, x1-1, y+h);
64
- g.drawLine(x0,y+h,x1,y+h);
65
- objectLocations.add(new Mouseover(new Interval(start,end), x0, y, x1-x0-1, h));
66
-
67
- g.setFont(model.getDisplay().timeLabel());
68
- String label=full? t.unit.formatFull(start) : t.unit.format(new Date(start));
69
- int tx=x0+3;
70
- int ty=y+h-5;
71
- g.setColor(full ? Color.darkGray : Color.gray);
72
- int sw=model.getDisplay().timeLabelFontMetrics().stringWidth(label);
73
- if (sw<x1-tx-3)
74
- g.drawString(label, tx,ty);
75
- else
76
- {
77
- int c=label.indexOf(':');
78
- if (c>0)
79
- {
80
- label=label.substring(0,c);
81
- sw=model.getDisplay().timeLabelFontMetrics().stringWidth(label);
82
- if (sw<x1-tx-3)
83
- g.drawString(label, tx,ty);
84
- }
85
- }
86
- }
87
- }
21
+ public void render(Graphics2D g, Collection<Mouseover> objectLocations)
22
+ {
23
+ TFModel model = visuals.getModel();
24
+ g.setColor(model.getDisplay().getColor("chart.background"));
25
+ Rectangle bounds = visuals.getBounds();
26
+
27
+ TimeScale scale = visuals.getTimeScale();
28
+ java.util.List<AxisTicMarks> t = AxisTicMarks.allRelevant(scale.getInterval());
29
+
30
+ int dateLabelH = model.getDisplay().getInt("timeline.datelabel.height");
31
+ int y = bounds.y + bounds.height - dateLabelH;
32
+
33
+ // draw in reverse order so bigger granularity at top.
34
+ int n = t.size();
35
+ for (int i = 0; i < n; i++)
36
+ {
37
+ render(t.get(i), g, bounds.x, y, dateLabelH - 1, bounds.y, i == 0, objectLocations);
38
+ y -= dateLabelH;
39
+ }
40
+ }
41
+
42
+ void render(AxisTicMarks t, Graphics2D g, int x, int y, int h, int top, boolean full, Collection<Mouseover> objectLocations)
43
+ {
44
+ TFModel model = visuals.getModel();
45
+
46
+ int n = t.tics.size();
47
+ for (int i = 0; i < n - 1; i++)
48
+ {
49
+
50
+ long start = t.tics.get(i);
51
+ long end = t.tics.get(i + 1);
52
+
53
+ int x0 = Math.max(x, visuals.getTimeScale().toInt(start));
54
+ int x1 = visuals.getTimeScale().toInt(end);
55
+
56
+ int dayOfWeek = TimeUtils.cal(start).get(Calendar.DAY_OF_WEEK);
57
+
58
+ g.setColor(t.unit.isDayOrLess() && (dayOfWeek == 1 || dayOfWeek == 7)
59
+ ? new Color(245, 245, 245) : new Color(240, 240, 240));
60
+
61
+ g.fillRect(x0, y, x1 - x0 - 1, h);
62
+ g.setColor(Color.white);
63
+ g.drawLine(x1 - 1, y, x1 - 1, y + h);
64
+ g.drawLine(x0, y + h, x1, y + h);
65
+ objectLocations.add(new Mouseover(new Interval(start, end), x0, y, x1 - x0 - 1, h));
66
+
67
+ g.setFont(model.getDisplay().timeLabel());
68
+ String label = full ? t.unit.formatFull(start) : t.unit.format(new Date(start));
69
+ int tx = x0 + 3;
70
+ int ty = y + h - 5;
71
+ g.setColor(full ? Color.darkGray : Color.gray);
72
+ int sw = model.getDisplay().timeLabelFontMetrics().stringWidth(label);
73
+ if (sw < x1 - tx - 3)
74
+ {
75
+ g.drawString(label, tx, ty);
76
+ } else
77
+ {
78
+ int c = label.indexOf(':');
79
+ if (c > 0)
80
+ {
81
+ label = label.substring(0, c);
82
+ sw = model.getDisplay().timeLabelFontMetrics().stringWidth(label);
83
+ if (sw < x1 - tx - 3)
84
+ {
85
+ g.drawString(label, tx, ty);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ }
8891 }
timeflow/vis/timeline/AxisTicMarks.java
....@@ -4,114 +4,116 @@
44
55 import timeflow.data.time.*;
66
7
-public class AxisTicMarks {
8
- public TimeUnit unit;
9
- public List<Long> tics;
10
-
11
- private static final TimeUnit[] units={
12
- TimeUnit.YEAR, TimeUnit.MONTH, TimeUnit.DAY, TimeUnit.HOUR, TimeUnit.MINUTE, TimeUnit.SECOND
13
- };
14
-
15
- private static final TimeUnit[] histUnits={
16
- TimeUnit.YEAR.times(100), TimeUnit.YEAR.times(50), TimeUnit.YEAR.times(25),
17
- TimeUnit.YEAR.times(10), TimeUnit.YEAR.times(5), TimeUnit.YEAR.times(2), TimeUnit.YEAR,
18
- TimeUnit.MONTH.times(6), TimeUnit.MONTH.times(3), TimeUnit.MONTH.times(2), TimeUnit.MONTH,
19
- TimeUnit.WEEK, TimeUnit.DAY.times(2), TimeUnit.DAY,
7
+public class AxisTicMarks
8
+{
9
+ public TimeUnit unit;
10
+ public List<Long> tics;
11
+ private static final TimeUnit[] units =
12
+ {
13
+ TimeUnit.YEAR, TimeUnit.MONTH, TimeUnit.DAY, TimeUnit.HOUR, TimeUnit.MINUTE, TimeUnit.SECOND
14
+ };
15
+ private static final TimeUnit[] histUnits =
16
+ {
17
+ TimeUnit.YEAR.times(100), TimeUnit.YEAR.times(50), TimeUnit.YEAR.times(25),
18
+ TimeUnit.YEAR.times(10), TimeUnit.YEAR.times(5), TimeUnit.YEAR.times(2), TimeUnit.YEAR,
19
+ TimeUnit.MONTH.times(6), TimeUnit.MONTH.times(3), TimeUnit.MONTH.times(2), TimeUnit.MONTH,
20
+ TimeUnit.WEEK, TimeUnit.DAY.times(2), TimeUnit.DAY,
21
+ TimeUnit.HOUR,
22
+ TimeUnit.MINUTE,
23
+ TimeUnit.SECOND
24
+ };
2025
21
- TimeUnit.HOUR,
22
- TimeUnit.MINUTE,
23
- TimeUnit.SECOND
24
- };
25
-
26
- public AxisTicMarks(TimeUnit unit, long start, long end)
27
- {
28
- this.unit=unit;
29
- tics=new ArrayList<Long>();
30
- RoughTime r=unit.roundDown(start);
31
- tics.add(r.getTime());
32
- do
33
- {
34
- unit.addTo(r);
35
- tics.add(r.getTime());
36
- } while (r.getTime()<end);
37
- }
38
-
39
-
40
-
41
- public static List<AxisTicMarks> allRelevant(Interval interval)
42
- {
43
- return allRelevant(interval.start, interval.end);
44
- }
45
-
46
- public static List<AxisTicMarks> allRelevant(long start, long end)
47
- {
48
- return allRelevant(start, end, 40);
49
- }
50
-
51
- public static AxisTicMarks histoTics(long start, long end)
52
- {
53
- for (int i=histUnits.length-1; i>=0; i--)
54
- {
55
- TimeUnit u=histUnits[i];
56
- long estimate=u.approxNumInRange(start, end);
57
- if (estimate<200 || i==0)
58
- {
59
- AxisTicMarks t=new AxisTicMarks(u, start, end);
60
- return t;
61
- }
62
- }
63
- return null;
64
- }
65
-
66
- public static List<AxisTicMarks> allRelevant(long start, long end, long maxTics)
67
- {
68
- List<AxisTicMarks> list=new ArrayList<AxisTicMarks>();
69
-
70
-
71
- for (int i=0; i<units.length; i++)
72
- {
73
- TimeUnit u=units[i];
74
- long estimate=u.approxNumInRange(start, end);
75
-
76
- if (estimate<maxTics)
77
- {
78
- AxisTicMarks t=new AxisTicMarks(u, start, end);
79
- if (list.size()>0)
80
- {
81
- AxisTicMarks last=list.get(0);
82
- if (last.tics.size()==t.tics.size())
83
- list.remove(0);
84
- }
85
- list.add(t);
86
-
87
- }
88
- }
89
- while (list.size()>2)
90
- list.remove(0);
91
-
92
- if (list.size()==0) // uh oh! must be many years. we will add in bigger increments.
93
- {
94
- long length=end-start;
95
- long size=365*24*60*60*1000L;
96
- int m=1;
97
- maxTics=15;
98
- while (m<2000000000 && length/(m*size)>maxTics)
99
- {
100
- if (length/(2*m*size)<=maxTics)
101
- {
102
- m*=2;
103
- break;
104
- }
105
- if (length/(5*m*size)<=maxTics)
106
- {
107
- m*=5;
108
- break;
109
- }
110
- m*=10;
111
- }
112
- AxisTicMarks t=new AxisTicMarks(TimeUnit.multipleYears(m), start, end);
113
- list.add(t);
114
- }
115
- return list;
116
- }
26
+ public AxisTicMarks(TimeUnit unit, long start, long end)
27
+ {
28
+ this.unit = unit;
29
+ tics = new ArrayList<Long>();
30
+ RoughTime r = unit.roundDown(start);
31
+ tics.add(r.getTime());
32
+ do
33
+ {
34
+ unit.addTo(r);
35
+ tics.add(r.getTime());
36
+ } while (r.getTime() < end);
37
+ }
38
+
39
+ public static List<AxisTicMarks> allRelevant(Interval interval)
40
+ {
41
+ return allRelevant(interval.start, interval.end);
42
+ }
43
+
44
+ public static List<AxisTicMarks> allRelevant(long start, long end)
45
+ {
46
+ return allRelevant(start, end, 40);
47
+ }
48
+
49
+ public static AxisTicMarks histoTics(long start, long end)
50
+ {
51
+ for (int i = histUnits.length - 1; i >= 0; i--)
52
+ {
53
+ TimeUnit u = histUnits[i];
54
+ long estimate = u.approxNumInRange(start, end);
55
+ if (estimate < 200 || i == 0)
56
+ {
57
+ AxisTicMarks t = new AxisTicMarks(u, start, end);
58
+ return t;
59
+ }
60
+ }
61
+ return null;
62
+ }
63
+
64
+ public static List<AxisTicMarks> allRelevant(long start, long end, long maxTics)
65
+ {
66
+ List<AxisTicMarks> list = new ArrayList<AxisTicMarks>();
67
+
68
+
69
+ for (int i = 0; i < units.length; i++)
70
+ {
71
+ TimeUnit u = units[i];
72
+ long estimate = u.approxNumInRange(start, end);
73
+
74
+ if (estimate < maxTics)
75
+ {
76
+ AxisTicMarks t = new AxisTicMarks(u, start, end);
77
+ if (list.size() > 0)
78
+ {
79
+ AxisTicMarks last = list.get(0);
80
+ if (last.tics.size() == t.tics.size())
81
+ {
82
+ list.remove(0);
83
+ }
84
+ }
85
+ list.add(t);
86
+
87
+ }
88
+ }
89
+ while (list.size() > 2)
90
+ {
91
+ list.remove(0);
92
+ }
93
+
94
+ if (list.size() == 0) // uh oh! must be many years. we will add in bigger increments.
95
+ {
96
+ long length = end - start;
97
+ long size = 365 * 24 * 60 * 60 * 1000L;
98
+ int m = 1;
99
+ maxTics = 15;
100
+ while (m < 2000000000 && length / (m * size) > maxTics)
101
+ {
102
+ if (length / (2 * m * size) <= maxTics)
103
+ {
104
+ m *= 2;
105
+ break;
106
+ }
107
+ if (length / (5 * m * size) <= maxTics)
108
+ {
109
+ m *= 5;
110
+ break;
111
+ }
112
+ m *= 10;
113
+ }
114
+ AxisTicMarks t = new AxisTicMarks(TimeUnit.multipleYears(m), start, end);
115
+ list.add(t);
116
+ }
117
+ return list;
118
+ }
117119 }