1 package org.catacomb.graph.gui;
2
3 import org.catacomb.datalish.SpriteAnimation;
4 import org.catacomb.interlish.report.Logger;
5 import org.catacomb.interlish.structure.ModeSettable;
6 import org.catacomb.interlish.structure.MovieOperator;
7 import org.catacomb.interlish.structure.MovieStateDisplay;
8 import org.catacomb.movie.gif.AnimatedGifEncoder;
9 import org.catacomb.report.E;
10 import org.catacomb.util.AWTUtil;
11 import java.awt.Color;
12 import java.awt.Dimension;
13 import java.awt.image.BufferedImage;
14 import java.awt.BorderLayout;
15
16 import java.io.File;
17
18
19
20
21
22
23 public class MovieDisplay extends BasePanel
24 implements ModeSettable, MovieOperator {
25
26
27 static final long serialVersionUID = 1001;
28
29 MoviePaintInstructor moviePaintInstructor;
30 MovieStateDisplay movieStateDisplay;
31
32 PickWorldCanvas pwCanvas;
33 BasePanel controlPanel;
34 Dimension prefDim;
35 Color bgColor;
36
37
38 double speed = 1.;
39 boolean isPaused = false;
40 MovieFramePlayer movieFramePlayer;
41 int nFrame;
42 int shownFrame;
43
44
45
46 public MovieDisplay(int w, int h) {
47 super();
48 bgColor = Color.gray;
49
50 prefDim = new Dimension(w, h);
51 setPreferredSize(prefDim);
52 pwCanvas = new PickWorldCanvas(w, h, true);
53 pwCanvas.setOnGridAxes();
54 pwCanvas.setFixedAspectRatio(1.0);
55
56 setLayout(new BorderLayout(0, 0));
57 add("Center", pwCanvas);
58 }
59
60
61 public Dimension getPreferredSize() {
62 return prefDim;
63 }
64
65
66 public void setBg(Color c) {
67 bgColor = c;
68 pwCanvas.setBg(c);
69 }
70
71
72
73 public void setMode(String dom, String mod) {
74 pwCanvas.setMode(dom, mod);
75 }
76
77
78 public void setMode(String dom, boolean b) {
79 pwCanvas.setMode(dom, b);
80 }
81
82
83
84 public void setMovie(SpriteAnimation sanim) {
85 setMoviePaintInstructor(new SpriteMoviePainter(sanim));
86 nFrame = moviePaintInstructor.getNFrames();
87 if (nFrame > 0) {
88 showFrame(nFrame-1);
89 }
90 }
91
92
93
94 public void setMoviePaintInstructor(MoviePaintInstructor mpi) {
95 moviePaintInstructor = mpi;
96 pwCanvas.setPaintInstructor(mpi);
97 }
98
99
100
101 public void attach(Object obj) {
102 boolean done = false;
103
104 if (obj instanceof MoviePaintInstructor) {
105 setMoviePaintInstructor((MoviePaintInstructor)obj);
106 done = true;
107 }
108
109
110 if (!done) {
111 E.error("cant attach " + obj + " to a data Display");
112 }
113 }
114
115
116
117 public void setLimits(double[] xyxy) {
118 pwCanvas.setXRange(xyxy[0], xyxy[2]);
119 pwCanvas.setYRange(xyxy[1], xyxy[3]);
120 }
121
122
123 public void setXRange(double low, double high) {
124 pwCanvas.setXRange(low, high);
125 }
126
127
128 public double[] getXRange() {
129 return pwCanvas.getXRange();
130 }
131
132
133 public double[] getYRange() {
134 return pwCanvas.getYRange();
135 }
136
137
138 public void setFixedAspectRatio(double ar) {
139 pwCanvas.setFixedAspectRatio(ar);
140 }
141
142
143 public void viewChanged() {
144 if (pwCanvas != null) {
145 pwCanvas.repaint();
146 }
147 }
148
149
150 public void reframe() {
151 pwCanvas.reframe();
152 }
153
154
155 public void advanceToFrame(int ifr) {
156 if (moviePaintInstructor != null) {
157 moviePaintInstructor.advanceToFrame(ifr);
158 shownFrame = ifr;
159 displayFrame();
160 }
161 }
162
163
164 public void showFrame(int ifr) {
165 if (moviePaintInstructor != null) {
166 moviePaintInstructor.setFrame(ifr);
167 shownFrame = ifr;
168 displayFrame();
169 }
170 }
171
172 private void displayFrame() {
173 pwCanvas.repaint();
174 nFrame = moviePaintInstructor.getNFrames();
175
176 if (movieStateDisplay != null) {
177 movieStateDisplay.frameChangedTo(shownFrame,
178 moviePaintInstructor.getFrameDescription(shownFrame));
179 }
180 }
181
182
183 public int getNFrame() {
184 return nFrame;
185 }
186
187
188
189 public void reset() {
190 stop();
191 showFrame(0);
192 }
193
194 public void play() {
195 stop();
196 reset();
197 start();
198 dePause();
199 }
200
201
202 public void resume() {
203 dePause();
204 start();
205 }
206
207
208 public void pause() {
209 pauseDePause();
210 }
211
212 public void pauseDePause() {
213 if (isPaused) {
214 dePause();
215 start();
216
217 } else {
218 rePause();
219 stop();
220 }
221 }
222
223
224 public void dePause() {
225 isPaused = false;
226 }
227
228 private void rePause() {
229 isPaused = true;
230 }
231
232
233
234 public void start() {
235 nFrame = moviePaintInstructor.getNFrames();
236 if (canAdvance()) {
237
238 } else {
239 reset();
240 }
241 if (nFrame > 0) {
242 movieFramePlayer = new MovieFramePlayer(this);
243 movieFramePlayer.start();
244 }
245 }
246
247
248 public void stop() {
249 nFrame = moviePaintInstructor.getNFrames();
250 if (movieFramePlayer != null) {
251 movieFramePlayer.stop();
252 }
253 }
254
255
256
257
258 public void faster() {
259 speed *= 1.3;
260 }
261
262 public void slower() {
263 speed /= 1.3;
264 }
265 public boolean canAdvance() {
266 return (shownFrame < nFrame - 1);
267 }
268
269
270 public void advance() {
271 advanceToFrame(shownFrame + 1);
272 }
273
274
275 public double getSpeed() {
276 return speed;
277 }
278
279
280 public void setMovieStateDisplay(MovieStateDisplay msd) {
281 movieStateDisplay = msd;
282 }
283
284
285 public void reluctantReframe() {
286 pwCanvas.reluctantReframe();
287
288 }
289
290
291
292 public BufferedImage getBufferedImage(int ithick) {
293
294
295
296
297
298 BufferedImage ret = AWTUtil.getBufferedImage(this);
299
300
301
302 return ret;
303 }
304
305
306
307
308
309 public void record(File f, Logger l) {
310 stop();
311 reset();
312
313 MDThreadRunner mdtr = new MDThreadRunner(this, f, l);
314 Thread thr = new Thread(mdtr);
315 thr.setPriority(Thread.MIN_PRIORITY);
316 thr.start();
317 l.init("writing animated gif " + f);
318 }
319
320
321
322 class MDThreadRunner implements Runnable {
323 File file;
324 Logger logger;
325 MovieDisplay movdisplay;
326
327 MDThreadRunner(MovieDisplay md, File f, Logger l) {
328 movdisplay = md;
329 file = f;
330 logger = l;
331 }
332
333 public void run() {
334 movdisplay.threadRecord(file, logger);
335 }
336 }
337
338
339
340 protected void threadRecord(File f, Logger l) {
341 int delay = (int)(20. / speed);
342
343 AnimatedGifEncoder enc = new AnimatedGifEncoder();
344
345 enc.start(f);
346 enc.setDelay(delay);
347
348 int ifr = 0;
349 E.info("animated gif - frame " + ifr);
350 enc.addFrame(getBufferedImage(1));
351
352 while (canAdvance()) {
353 advance();
354 ifr += 1;
355 E.info("frame " + ifr);
356 l.optionalIncrementLog(ifr, "frame");
357 enc.addFrame(getBufferedImage(1));
358 }
359 enc.finish();
360
361 l.end();
362 }
363
364
365 }