View Javadoc

1   /*
2    * jcurl java curling software framework https://JCurl.mro.name Copyright (C)
3    * 2005-2009 M. Rohrmoser
4    * 
5    * This program is free software; you can redistribute it and/or modify it under
6    * the terms of the GNU General Public License as published by the Free Software
7    * Foundation; either version 2 of the License, or (at your option) any later
8    * version.
9    * 
10   * This program is distributed in the hope that it will be useful, but WITHOUT
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13   * details.
14   * 
15   * You should have received a copy of the GNU General Public License along with
16   * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17   * Place, Suite 330, Boston, MA 02111-1307 USA
18   */
19  
20  package org.jcurl.demo.tactics.old;
21  
22  import java.awt.Component;
23  import java.awt.Cursor;
24  import java.awt.Graphics;
25  import java.awt.Rectangle;
26  import java.awt.geom.Point2D;
27  import java.awt.image.BufferedImage;
28  import java.io.File;
29  import java.io.IOException;
30  
31  import javax.imageio.ImageIO;
32  import javax.swing.JFileChooser;
33  import javax.swing.filechooser.FileFilter;
34  
35  import org.apache.commons.logging.Log;
36  import org.jcurl.core.api.ComputedTrajectorySet;
37  import org.jcurl.core.api.IceSize;
38  import org.jcurl.core.api.RockDouble;
39  import org.jcurl.core.api.RockSet;
40  import org.jcurl.core.api.RockSetUtils;
41  import org.jcurl.core.api.Unit;
42  import org.jcurl.core.api.RockType.Pos;
43  import org.jcurl.core.api.RockType.Vel;
44  import org.jcurl.core.helpers.AnnoHelper;
45  import org.jcurl.core.helpers.NotImplementedYetException;
46  import org.jcurl.core.impl.CollissionSpin;
47  import org.jcurl.core.impl.CurlerDenny;
48  import org.jcurl.core.impl.CurveManager;
49  import org.jcurl.core.impl.NewtonCollissionDetector;
50  import org.jcurl.core.io.IONode;
51  import org.jcurl.core.io.IOTrajectories;
52  import org.jcurl.core.io.JCurlSerializer;
53  import org.jcurl.core.io.JDKSerializer;
54  import org.jcurl.core.log.JCLoggerFactory;
55  import org.jcurl.demo.tactics.TrajectoryBean;
56  import org.jcurl.demo.tactics.old.ActionRegistry.JCAction;
57  
58  /**
59   * @author <a href="mailto:JCurl@mro.name">M. Rohrmoser </a>
60   * @version $Id$
61   */
62  public class MenuFile {
63  	@ActionRegistry.JCMenu("&File")
64  	public static class Controller {
65  		private static final Log log = JCLoggerFactory
66  				.getLogger(Controller.class);
67  
68  		/**
69  		 * tighten to a given point.
70  		 * 
71  		 * TODO play a shy slurping sound.
72  		 * 
73  		 * @param frame
74  		 * @param steps
75  		 * @param millis
76  		 */
77  		private static void vanish(final Component frame, final int steps,
78  				final int millis) {
79  			if (false)
80  				// TODO on a wicked Mac do nothing more but exit...
81  				return;
82  			final Rectangle siz0 = frame.getBounds();
83  			// final BufferedImage img = new
84  			// BufferedImage(frame.getContentPane()
85  			// .getWidth(), frame.getContentPane().getHeight(),
86  			// BufferedImage.TYPE_INT_RGB);
87  			// frame.getContentPane().paint(img.getGraphics());
88  			// img.getGraphics().dispose();
89  
90  			// why does this have no effect?
91  			// frame.getContentPane().removeAll();
92  			frame.repaint();
93  			final Point2D dst = new Point2D.Double(siz0.x + siz0.width * 1 / 3,
94  					siz0.y + siz0.height * 1 / 3);
95  			for (int i = steps - 1; i >= 0; i--) {
96  				final Rectangle siz = frame.getBounds();
97  				siz.x = (int) (dst.getX() + (siz0.x - dst.getX()) * i / steps);
98  				siz.y = (int) (dst.getX() + (siz0.y - dst.getY()) * i / steps);
99  				siz.height = (int) ((float) siz0.height * i / steps);
100 				siz.width = (int) ((float) siz0.width * i / steps);
101 				frame.setBounds(siz);
102 				try {
103 					Thread.sleep(millis / steps);
104 				} catch (final InterruptedException e) {
105 					return;
106 				}
107 			}
108 		}
109 
110 		private final JFileChooser fcJcx;
111 		private final JFileChooser fcPng;
112 		private Model model = new Model();
113 		private final Component parent;
114 		private final Component shootable;
115 		private final TrajectoryBean td;
116 
117 		public Controller(final Component parent, final Component shootable,
118 				final TrajectoryBean td) {
119 			this.parent = parent;
120 			this.shootable = shootable;
121 			this.td = td;
122 			final File base = new File(".");
123 			fcJcx = new JFileChooser(base);
124 			fcJcx.setName("Open");
125 			fcJcx.setMultiSelectionEnabled(false);
126 			fcJcx.setAcceptAllFileFilterUsed(true);
127 			fcJcx.setFileFilter(new FileFilter() {
128 				@Override
129 				public boolean accept(final File f) {
130 					if (f == null)
131 						return false;
132 					return f.isDirectory() || f.getName().endsWith(".jcx")
133 							|| f.getName().endsWith(".jcz");
134 				}
135 
136 				@Override
137 				public String getDescription() {
138 					return "JCurl Setup Files (.jcx) (.jcz)";
139 				}
140 			});
141 			fcPng = new JFileChooser(base);
142 			fcPng.setName("Save Screenshot");
143 			fcPng.setDialogTitle(fcPng.getName());
144 			fcPng.setMultiSelectionEnabled(false);
145 			fcPng.setAcceptAllFileFilterUsed(true);
146 			fcPng.setFileFilter(new FileFilter() {
147 				@Override
148 				public boolean accept(final File f) {
149 					if (f == null)
150 						return false;
151 					return f.isDirectory() || f.getName().endsWith(".png");
152 				}
153 
154 				@Override
155 				public String getDescription() {
156 					return "Png Bitmap Images (.png)";
157 				}
158 			});
159 		}
160 
161 		@JCAction(title = "Clea&r", idx = 0, accelerator = "CTRL-R")
162 		public void clear() {
163 			log.info("");
164 			final Cursor cu = switchCursor(waitc);
165 			try {
166 				// This cast just eases code navigation. Remove it later.
167 				td.setCurves(null);
168 			} finally {
169 				switchCursor(cu);
170 			}
171 		}
172 
173 		@JCAction(title = "E&xit", idx = 60, separated = true)
174 		public void exitFile() {
175 			log.info("");
176 			// if (!discardUnsavedChanges())
177 			// fileSave.actionPerformed(null);
178 			final Cursor cu = switchCursor(waitc);
179 			vanish(parent, 10, 200);
180 			System.exit(0);
181 		}
182 
183 		@JCAction(title = "Export SV&G", idx = 51, accelerator = "CTRL-G")
184 		public void exportSvg() {
185 			// if (JFileChooser.APPROVE_OPTION == fcPng.showSaveDialog(parent))
186 			// {
187 			// final File dst = fcPng.getSelectedFile();
188 			final File dst = new File("/tmp/tactics");
189 			final Cursor cu = switchCursor(waitc);
190 			try {
191 				model.exportSvg(shootable, dst);
192 			} catch (final Exception e1) {
193 				log.error("", e1);
194 			} finally {
195 				switchCursor(cu);
196 			}
197 			// }
198 		}
199 
200 		public Model getModel() {
201 			return model;
202 		}
203 
204 		@JCAction(title = "&New", idx = 10, accelerator = "CTRL-N", separated = true)
205 		public void newFile() {
206 			log.info("");
207 			final Cursor cu = switchCursor(waitc);
208 			try {
209 				// ...
210 			} finally {
211 				switchCursor(cu);
212 			}
213 		}
214 
215 		@JCAction(title = "&Open", idx = 20, accelerator = "CTRL-O")
216 		public void openFile() {
217 			log.info("");
218 			fcJcx.setDialogTitle("Open");
219 			if (JFileChooser.APPROVE_OPTION == fcJcx.showOpenDialog(parent)) {
220 				final Cursor cu = switchCursor(waitc);
221 				try {
222 					td.setCurves(model.open(td, fcJcx.getSelectedFile()));
223 				} catch (final Exception e1) {
224 					log.error("", e1);
225 				} finally {
226 					switchCursor(cu);
227 				}
228 			}
229 		}
230 
231 		@JCAction(title = "Save &As", idx = 40)
232 		public void saveAsFile() {
233 			log.info("");
234 			fcJcx.setDialogTitle("Save As");
235 			if (JFileChooser.APPROVE_OPTION == fcJcx.showSaveDialog(parent)) {
236 				final Cursor cu = switchCursor(waitc);
237 				try {
238 					model.saveAs(td, fcJcx.getSelectedFile());
239 				} catch (final Exception e1) {
240 					log.error("", e1);
241 				} finally {
242 					switchCursor(cu);
243 				}
244 			}
245 		}
246 
247 		@JCAction(title = "&Save", idx = 30, separated = true, accelerator = "CTRL-S")
248 		public void saveFile() {
249 			log.info("");
250 			final Cursor cu = switchCursor(waitc);
251 			try {
252 
253 				// ...
254 			} finally {
255 				switchCursor(cu);
256 			}
257 		}
258 
259 		@JCAction(title = "S&creenshot", idx = 50, separated = true, accelerator = "CTRL-P")
260 		public void screenShot() {
261 			if (JFileChooser.APPROVE_OPTION == fcPng.showSaveDialog(parent)) {
262 				final File dst = fcPng.getSelectedFile();
263 				final Cursor cu = switchCursor(waitc);
264 				try {
265 					model.exportPng(shootable, dst);
266 				} catch (final Exception e1) {
267 					log.error("", e1);
268 				} finally {
269 					switchCursor(cu);
270 				}
271 			}
272 		}
273 
274 		public void setModel(final Model model) {
275 			this.model = model;
276 		}
277 
278 		@JCAction(title = "Show &Hammy", idx = 1, accelerator = "CTRL-H")
279 		public void showHammy() {
280 			log.info("");
281 			final Cursor cu = switchCursor(waitc);
282 			try {
283 				td.setCurves(model.createHammy(td));
284 			} finally {
285 				switchCursor(cu);
286 			}
287 		}
288 
289 		private Cursor switchCursor(final Cursor neo) {
290 			final Cursor cu = parent.getCursor();
291 			parent.setCursor(neo);
292 			Thread.yield();
293 			return cu;
294 		}
295 	}
296 
297 	public static class Model {
298 		private File file;
299 		private ComputedTrajectorySet tpm;
300 
301 		public ComputedTrajectorySet createHammy(final Object context) {
302 			// This cast just eases code navigation. Remove it later.
303 			final ComputedTrajectorySet ret = initHammy(tpm);
304 			ret.setCurrentTime(30);
305 			setTpm(ret);
306 			return ret;
307 		}
308 
309 		private File ensureProperSuffix(File dst) {
310 			if (!(dst.getName().endsWith(".jcx") || dst.getName().endsWith(
311 					".jcz")))
312 				dst = new File(dst.getAbsoluteFile() + ".jcz");
313 			return dst;
314 		}
315 
316 		public void exportPng(final Component src, File dst) throws IOException {
317 			final BufferedImage img = new BufferedImage(src.getWidth(), src
318 					.getHeight(), BufferedImage.TYPE_INT_ARGB);
319 			final Graphics g = img.getGraphics();
320 			try {
321 				src.paintAll(g);
322 			} finally {
323 				g.dispose();
324 			}
325 			if (!dst.getName().endsWith(".png"))
326 				dst = new File(dst.getAbsoluteFile() + ".png");
327 			ImageIO.write(img, "png", dst);
328 		}
329 
330 		public void exportSvg(final Component src, final File dst)
331 				throws IOException {
332 			throw new NotImplementedYetException();
333 			// if (false) {
334 			// if (!dst.getName().endsWith(".svg"))
335 			// dst = new File(dst.getAbsoluteFile() + ".svg");
336 			// final Graphics g = Graphics2Svg.createGraphics(src.getWidth(),
337 			// src.getHeight(), dst);
338 			// try {
339 			// src.paintAll(g);
340 			// } finally {
341 			// g.dispose();
342 			// }
343 			// } else {
344 			// final BufferedImage img = new BufferedImage(src.getWidth(), src
345 			// .getHeight(), BufferedImage.TYPE_INT_ARGB);
346 			// final Graphics g;
347 			// if (false)
348 			// g = new Graphics2DWrap(img.createGraphics());
349 			// else
350 			// g = new Graphics2DWrap(src.getGraphics());
351 			// try {
352 			// src.paintAll(g);
353 			// } finally {
354 			// g.dispose();
355 			// }
356 			// // if (!dst.getName().endsWith(".png"))
357 			// // dst = new File(dst.getAbsoluteFile() + ".png");
358 			// // ImageIO.write(img, "png", dst);
359 			// }
360 		}
361 
362 		public File getFile() {
363 			return file;
364 		}
365 
366 		public ComputedTrajectorySet getTpm() {
367 			return tpm;
368 		}
369 
370 		ComputedTrajectorySet open(final Object context, final File src)
371 				throws IOException {
372 			final IONode n = new JCurlSerializer().read(src);
373 			final IOTrajectories it = (IOTrajectories) n;
374 			setTpm((ComputedTrajectorySet) it.trajectories().get(0));
375 			setFile(src);
376 			tpm.setCurrentTime(30);
377 			return tpm;
378 		}
379 
380 		void saveAs(final Object context, final File dst) throws IOException {
381 			final IOTrajectories it = new IOTrajectories();
382 			// Add some properties about the file.
383 			it.annotations().put("foo", "bar");
384 			it.trajectories().add(tpm);
385 			new JCurlSerializer().write(it, ensureProperSuffix(dst),
386 					JDKSerializer.class);
387 		}
388 
389 		public void setFile(final File file) {
390 			this.file = file;
391 		}
392 
393 		public void setTpm(final ComputedTrajectorySet tpm) {
394 			this.tpm = tpm;
395 		}
396 	}
397 
398 	private static final Cursor defau = Cursor.getDefaultCursor(); // getPredefinedCursor(Cursor.DEFAULT_CURSOR);
399 
400 	private static final Cursor waitc = Cursor
401 			.getPredefinedCursor(Cursor.WAIT_CURSOR);
402 
403 	static ComputedTrajectorySet initHammy(ComputedTrajectorySet te) {
404 		if (te == null)
405 			te = new CurveManager();
406 		te.setCollider(new CollissionSpin(0.5, 0.0));
407 		te.setCollissionDetector(new NewtonCollissionDetector());
408 		te.setCurler(new CurlerDenny(24, 1));
409 		te.setInitialPos(RockSetUtils.allOut());
410 		te.setInitialVel(new RockSet<Vel>(new RockDouble<Vel>()));
411 		te.getAnnotations().put(AnnoHelper.HammerK, AnnoHelper.HammerVDark);
412 		te.getAnnotations().put(AnnoHelper.DarkTeamK, "Scotland");
413 		te.getAnnotations().put(AnnoHelper.LightTeamK, "Canada");
414 		te.getAnnotations().put(AnnoHelper.GameK, "Semifinal");
415 		te.getAnnotations().put(AnnoHelper.EventK,
416 				"World Curling Championships");
417 		te.getAnnotations().put(AnnoHelper.DateK, "1992");
418 		te.getAnnotations().put(AnnoHelper.LocationK, "Garmisch");
419 		initHammy(te.getInitialPos(), te.getInitialVel());
420 		return te;
421 	}
422 
423 	static void initHammy(final RockSet<Pos> p, final RockSet<Vel> s) {
424 		RockSetUtils.allOut(p);
425 		// te.getInitialPos().getLight(1-1).setLocation(
426 		p.getLight(2 - 1).setLocation(Unit.f2m(-1.170732), Unit.f2m(15.365854),
427 				0);
428 		p.getLight(3 - 1)
429 				.setLocation(Unit.f2m(0.292683), Unit.f2m(8.780488), 0);
430 		p.getLight(4 - 1).setLocation(Unit.f2m(2.195122), Unit.f2m(12), 0);
431 		p.getLight(5 - 1)
432 				.setLocation(Unit.f2m(1.463415), Unit.f2m(5.707317), 0);
433 		p.getLight(6 - 1).setLocation(Unit.f2m(1.463415), Unit.f2m(-2.780488),
434 				0);
435 		p.getLight(7 - 1).setLocation(Unit.f2m(-0.439024), Unit.f2m(-5.560976),
436 				0);
437 		p.getLight(8 - 1).setLocation(Unit.f2m(-1.756098), Unit.f2m(-1.609756),
438 				0);
439 		// p.getDark(1-1).setLocation(
440 		// p.getDark(2-1).setLocation(
441 		p.getDark(3 - 1)
442 				.setLocation(Unit.f2m(0.878049), Unit.f2m(14.341463), 0);
443 		p.getDark(4 - 1).setLocation(Unit.f2m(-2.634146), Unit.f2m(13.170732),
444 				0);
445 		p.getDark(5 - 1)
446 				.setLocation(Unit.f2m(4.536585), Unit.f2m(-0.439024), 0);
447 		p.getDark(6 - 1).setLocation(Unit.f2m(0.731707), Unit.f2m(-3.95122), 0);
448 		p.getDark(7 - 1).setLocation(Unit.f2m(-2.780488), Unit.f2m(-4.390244),
449 				0);
450 		p.getDark(8 - 1).setLocation(Unit.f2m(3.89991), IceSize.HOG_2_TEE, 0);
451 		RockSet.allZero(s);
452 		s.getDark(8 - 1).setLocation(0, -3, 100 * Math.PI / 180);
453 
454 		p.getDark(8 - 1).setLocation(0, IceSize.FAR_HACK_2_TEE, 0);
455 		s.getDark(8 - 1).setLocation(0.188, -3, -100 * Math.PI / 180);
456 
457 		p.getDark(8 - 1).setLocation(0, IceSize.FAR_HACK_2_TEE, 0);
458 		s.getDark(8 - 1).setLocation(0.1785, -4, -100 * Math.PI / 180);
459 	}
460 }