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
26
27 package hacks;
28
29 import java.awt.Color;
30 import java.awt.Graphics;
31 import java.awt.Graphics2D;
32 import java.awt.RenderingHints;
33 import java.awt.geom.Point2D;
34 import java.awt.image.BufferedImage;
35 import java.io.File;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.logging.Level;
40 import java.util.logging.Logger;
41
42 import javax.imageio.ImageIO;
43 import javax.swing.BorderFactory;
44 import javax.swing.ImageIcon;
45 import javax.swing.JLabel;
46
47 import org.sigtec.graphix.Points;
48 import org.sigtec.ink.Note;
49 import org.sigtec.ink.Point;
50 import org.sigtec.ink.input.TimestampedInputEvent;
51 import org.sigtec.ink.input.TimestampedLocation;
52 import org.sigtec.input.InputHandler;
53 import org.sigtec.util.Constant;
54
55
56
57
58
59
60
61
62
63 public class JNote extends JLabel implements InputHandler {
64
65 private static final Logger LOGGER = Logger.getLogger(JNote.class.getName());
66
67 private BufferedImage bufferedImage;
68
69 private Graphics graphic;
70
71 private Point lastPoint;
72
73 private double scale;
74
75 private int[] space;
76
77 private int[] translation;
78
79 private int traceNumber;
80
81 private int initialSpaceWidth;
82
83 private int initialSpaceHeight;
84
85 private List<Point> locationBuffer;
86
87 private static final int MAX_TIME = 180;
88
89 private static final int MARKER_RADIUS = 6;
90
91 private static final int INITIAL_WIDHT = 50;
92
93 private static final int INITIAL_HEIGHT = 50;
94
95 private static final int STRETCH_FACTOR = 2;
96
97 private boolean freeze;
98
99 public static String PNG = "png";
100
101 public static String JPEG = "jpeg";
102
103
104
105
106
107
108
109
110 public JNote(int width, int height) {
111 this(width, height, INITIAL_WIDHT, INITIAL_HEIGHT);
112 }
113
114
115
116
117
118
119
120
121
122
123 public JNote(int width, int height, int spaceWidth, int spaceHeight) {
124 super();
125 traceNumber = 0;
126 locationBuffer = new ArrayList<Point>();
127 freeze = false;
128 this.initialSpaceHeight = spaceHeight;
129 this.initialSpaceWidth = spaceWidth;
130 space = new int[] { spaceWidth, spaceHeight };
131 setSize(width, height);
132 bufferedImage = new BufferedImage(width, height,
133 BufferedImage.TYPE_INT_ARGB);
134 graphic = bufferedImage.getGraphics();
135 ((Graphics2D)graphic).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
136 RenderingHints.VALUE_ANTIALIAS_ON);
137 setIcon(new ImageIcon(bufferedImage));
138 graphic.setColor(Color.BLACK);
139 this.setBorder(BorderFactory.createLineBorder(Color.black, 2));
140
141 }
142
143
144 public void handle(Object invoker, TimestampedInputEvent timestampedEvent) {
145 if (timestampedEvent instanceof TimestampedLocation) {
146 TimestampedLocation location = (TimestampedLocation)timestampedEvent;
147
148 if (freeze) {
149 clear();
150 freeze = false;
151 }
152
153 drawNextPoint(location.toPoint());
154 }
155 }
156
157
158
159
160
161
162
163 public void setNote(Note note) {
164 clear();
165
166 for (final Point point : note.getPoints()) {
167 drawNextPoint(point);
168 }
169
170 }
171
172
173
174
175
176
177
178 public void freeze() {
179 freeze = true;
180 }
181
182
183
184
185
186
187
188
189 public void exportImage(File file, String format) {
190 try {
191 ImageIO.write(bufferedImage, format, file);
192 }
193 catch (final IOException e) {
194 LOGGER.log(Level.SEVERE, Constant.EMPTY_STRING, e);
195 }
196
197 }
198
199
200
201
202
203
204
205 public void exportPNGImage(File file) {
206 exportImage(file, PNG);
207 }
208
209
210
211
212
213 public synchronized void drawNextPoint(Point currentPoint) {
214 if (!locationBuffer.contains(currentPoint)) {
215 locationBuffer.add(currentPoint);
216 }
217
218 if (translation == null) {
219 updateMiddlePoint(currentPoint);
220 }
221 else if (!isInArea(translate(currentPoint))) {
222 space[0] *= STRETCH_FACTOR;
223 space[1] *= STRETCH_FACTOR;
224 updateMiddlePoint(computeCenterPoint());
225 }
226
227 if (lastPoint != null && isNewTrace(lastPoint, currentPoint)) {
228 drawLine(translate(lastPoint), translate(currentPoint));
229 }
230 else {
231 drawPoint(translate(currentPoint), MARKER_RADIUS);
232 numberTrace(translate(currentPoint), traceNumber++);
233 }
234
235 repaint();
236 lastPoint = currentPoint;
237 }
238
239
240
241
242
243 private synchronized void updateMiddlePoint(Point point) {
244 scale = Math.min((double)bufferedImage.getWidth() / space[0],
245 (double)bufferedImage.getHeight() / space[1]);
246 translation = new int[2];
247 translation[0] = (int)(bufferedImage.getWidth() / 2 - point.getX() * scale);
248 translation[1] = (int)(bufferedImage.getHeight() / 2 - point.getY()
249 * scale);
250 refresh();
251 }
252
253
254
255
256
257
258 private synchronized void refresh() {
259 clearBufferedImage();
260 traceNumber = 0;
261 final Point tmp = lastPoint;
262 lastPoint = null;
263
264 for (final Point ts : locationBuffer) {
265 drawNextPoint(ts);
266 }
267
268 lastPoint = tmp;
269 }
270
271
272
273
274
275
276
277
278 private void drawLine(Point startPoint, Point endPoint) {
279 graphic.drawLine((int)startPoint.getX(), (int)startPoint.getY(),
280 (int)endPoint.getX(), (int)endPoint.getY());
281 }
282
283
284
285
286
287
288
289
290 private void drawPoint(Point point, int radius) {
291 graphic.setColor(Color.RED);
292 graphic.fillOval((int)point.getX() - radius / 2, (int)point.getY()
293 - radius / 2, radius, radius);
294 graphic.setColor(Color.BLACK);
295 }
296
297
298
299
300
301 private void numberTrace(Point point, int number) {
302 graphic.setColor(Color.RED);
303 graphic.drawString(String.valueOf(number), (int)point.getX() - 5,
304 (int)point.getY() - 5);
305 graphic.setColor(Color.BLACK);
306 }
307
308
309
310
311
312
313
314 private Point translate(Point point) {
315 final double x = (point.getX() * scale + translation[0]);
316 final double y = (point.getY() * scale + translation[1]);
317 return new Point((int)x, (int)y);
318 }
319
320
321
322
323
324
325
326
327 private boolean isInArea(Point point) {
328 if (point.getX() > bufferedImage.getWidth()
329 || point.getY() > bufferedImage.getHeight() || point.getX() < 0
330 || point.getY() < 0) {
331 return false;
332 }
333
334 return true;
335 }
336
337
338
339
340
341
342
343 private Point computeCenterPoint() {
344 final List<Point2D> points = new ArrayList<Point2D>();
345
346 for (final Point ts : locationBuffer) {
347 points.add(new Point2D.Double(ts.getX(), ts.getY()));
348 }
349
350 final Point2D point = Points.getCentre(points);
351 return new Point((int)point.getX(), (int)point.getY());
352 }
353
354
355
356
357
358 private boolean isNewTrace(Point loc1, Point loc2) {
359 return loc2.getTimestamp() - loc1.getTimestamp() < MAX_TIME;
360 }
361
362
363
364
365
366
367 public void clear() {
368 locationBuffer.clear();
369 lastPoint = null;
370 translation = null;
371 space = new int[] { initialSpaceWidth, initialSpaceHeight };
372 clearBufferedImage();
373 traceNumber = 0;
374 repaint();
375 }
376
377
378 private void clearBufferedImage() {
379 graphic.setColor(Color.WHITE);
380 graphic
381 .fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
382 graphic.setColor(Color.BLACK);
383 }
384
385
386 public BufferedImage getImage() {
387 return bufferedImage;
388 }
389
390 }