1
18
19 import java.awt.event.*;
20 import java.awt.*;
21 import java.awt.geom.*;
22 import java.util.*;
23 import java.io.*;
24 import java.util.zip.*;
25 import java.net.*;
26 import java.util.jar.*;
27 import java.awt.print.*;
28 import java.awt.image.*;
29 import javax.swing.*;
30 import java.lang.ref.*;
31 import java.text.NumberFormat;
32
33
39 public class Carto implements Serializable {
40
41 private static final long serialVersionUID = Version.getSUID();
42
43
47 static File filebase = new File(System.getProperty("user.dir"));
48
49 static GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment();
50 static GraphicsConfiguration gconf = genv.getDefaultScreenDevice().getDefaultConfiguration();
51
52 public static Selection cutbuffer = null;
53
54 public transient Selection[] selections = new Selection[4];
55
56
59 public TreeSet sizes;
60
61
64 public HashMap defaults = new HashMap(5,5);
65
66
67 public Survey survey = null;
68
69
72 public Vector complist = new Vector();
73
74
77 public Vector segmentlist = new Vector();
78
79
81 public Vector sectionlist = new Vector();
82
83
84 public EditState[] place = null;
85
86
89 public PrefEditor[] prefs = null;
90
91
94 public static Unit defscreenunit = Unit.inch;
95
96
99 public static Unit defmapunit = Unit.foot;
100
101
104 public Unit screenunit = defscreenunit;
105
106
110 public Unit mapunit = defmapunit;
111
112
113 public static Version runversion = new Version();
114
115
116 public String created_version = runversion.getVersion();
117
118 public String saved_version = runversion.getVersion();
119
120
123 public transient File base = null;
124
126 public transient ZipEntry zipent = null;
127
130 public transient ZipFile zipfile = null;
131
132
138 public static Thread background = null;
139
141 public static int kill = 0;
142
143
144 public static int COOKKILL = 1;
145
146 public static int PRINTKILL = 1;
147
148
149 public Carto() {
150 for (int i=0;i<4;i++)
151 selections[i] = new Selection(this);
152
153 FileDefaultable.sortOut(defaults);
154 }
155
156
158 public static File choose(Component parent) {
159 JFileChooser choose = Persist.current.getFileChooser();
160
161 choose.setFileFilter(new FileTypes(FileTypes.CARTO));
162 choose.rescanCurrentDirectory();
163 if (choose.showOpenDialog(parent)!=choose.APPROVE_OPTION) return(null);
164 return(choose.getSelectedFile());
165 }
166
167
172 public static Carto read(File filename) {
173 Object result = null;
174 File base = null;
175 ZipFile zip = null;
176 ZipEntry zipent = null;
177 try {
178 InputStream istream = null;
179 if (filename.getName().substring(filename.getName().lastIndexOf('.')+1).equals("cto")) {
180 istream = new FileInputStream(filename);
181 base = filename.getCanonicalFile().getParentFile();
182 }
183 else {
184 base = filename.getCanonicalFile();
185 zip = new ZipFile(filename);
186
187 Vector ctos = new Vector();
188 for (Enumeration zipnames = zip.entries();
189 zipnames.hasMoreElements();) {
190 ZipEntry ent = (ZipEntry)zipnames.nextElement();
191 String name = ent.getName();
192 int dot = name.lastIndexOf('.');
193 if (dot>=0 && name.substring(dot).equals("cto"))
194 ctos.add(ent);
195 }
196 if (ctos.size()==0) throw new FileNotFoundException(filename.getName()+
197 " does not conatain any .cto files");
198 else if (ctos.size()==1) zipent = (ZipEntry)ctos.elementAt(0);
199 else {
200 Object[] names = ctos.toArray();
201 zipent = (ZipEntry)JOptionPane.showInputDialog(null,
202 "Choose .cto file from zip",
203 "Zip",
204 JOptionPane.QUESTION_MESSAGE,
205 null,
206 names,
207 names[0]);
208 }
209 if (zipent==null) return(null);
210 istream = zip.getInputStream(zipent);
211 }
212 ObjectInputStream in = new ObjectInputStream(istream);
213 result = in.readObject();
214 istream.close();
215 } catch (Exception e) {
216 ErrorLog.log("Carto file not sucessfully read: "+filename);
217 ErrorLog.exception(e);
218 return(null);
219 }
220
221 if (result == null || !(result instanceof Carto)) {
222 ErrorLog.log("error: could not read Carto data from "+filename+".");
223 return(null);
224 }
225 else {
226 Carto res = (Carto)result;
227 FileDefaultable.sortOut(res.defaults);
228 res.zipfile = zip;
229 res.base = base;
230 res.zipent = zipent;
231 return(res);
232 }
233 }
234
235
238 public void prepareForSurveyUpdate() {
239 for (Iterator it = complist.iterator();it.hasNext();) {
240 ((Comp)it.next()).prepareForSurveyUpdate(null);
241 }
242 }
243
244
248 public void useSurveyUpdate() {
249 for (Iterator it = complist.iterator();it.hasNext();) {
250 ((Comp)it.next()).useSurveyUpdate();
251 }
252 }
253
254
257 public Vector getList(String name) {
258 if (name.equals(CartoFrame.SEGWORD)) return(segmentlist);
259 else if (name.equals(CartoFrame.COMPWORD)) return(complist);
260 else if (name.equals(CartoFrame.SECTION)) return(sectionlist);
261 return(new Vector());
262 }
263
264
268 public void clean() {
269 for (Iterator it = complist.iterator();it.hasNext();)
270 ((Comp)it.next()).clean(segmentlist);
271 }
272
273
280 public String used(Vertex station) {
281 String res = "";
282
283
284
285
286
287
288 for (Iterator it = segmentlist.iterator();it.hasNext();) {
289 Segment seg = (Segment)it.next();
290 if (seg.map.used(station))
291 res += " to morph segment "+seg+"\n";
292 }
293
294 if (res.length()==0) return(null);
295 return(res);
296 }
297
298
302 public void remove(Vertex station) {
303
304
305
306 for (Iterator it = segmentlist.iterator();it.hasNext();)
307 ((Segment)it.next()).map.remove(station);
308 }
309
310
311
313 public static boolean startBackground(Thread action) {
314 synchronized(Carto.class) {
315 if (background != null) {
316 ErrorLog.log("There is already a background process going on\n"+
317 "It should be stoped before starting another\n");
318 return(false);
319 }
320 background = action;
321 background.setPriority(background.getPriority()-1);
322 background.start();
323 return(true);
324 }
325 }
326
327
330 public static void cleanBackground() {
331 synchronized(Carto.class) {
332 background = null;
333 kill = 0;
334 }
335 }
336
337
339 public static void stopBackground(int killval) {
340 Thread deadthread;
341 synchronized(Carto.class) {
342 deadthread = Carto.background;
343 if (deadthread!=null)
344 Carto.kill = killval;
345 }
346 if (deadthread!= null)
347 while (background==deadthread) {
348 try {
349 Thread.sleep(50);
350 } catch (InterruptedException e) {}
351 }
352 }
353
354
358 public void reCookAll(final ThreadMessage message,final CartoFrame owner) {
359
360
361 if (Segment.cookondemand) {
362 ImageThread.stopLoading();
363 for (Iterator it = segmentlist.iterator();it.hasNext();) {
364 Segment seg = (Segment) it.next();
365 seg.doCook(null);
366 }
367 }
368 else {
369
370 startBackground(new Thread(){
371 public void run() {
372 try {
373 for (Iterator it = segmentlist.iterator();it.hasNext();) {
374 Segment seg = (Segment) it.next();
375 seg.unCook();
376 if (seg.cookable()) seg.cook(null);
377 }
378 } catch (CookKillException killex) {
379 } finally {
380 owner.repaint();
381 cleanBackground();
382 }
383 }});
384 }
385 }
386
387
392 public void hardReCookAll(final ThreadMessage message,final CartoFrame owner) {
393 reCookAll(message,owner);
394 }
395
396
399 public TreeSet getDefs(Class type) {
400 if (!defaults.containsKey(type))
401 defaults.put(type, new TreeSet());
402 return((TreeSet)defaults.get(type));
403 }
404
405
407 private void readObject(java.io.ObjectInputStream stream)
408 throws java.io.IOException,java.lang.ClassNotFoundException {
409 stream.defaultReadObject();
410
411
412
413 if (defaults==null) defaults = new HashMap(5,5);
414
415 if (!defaults.containsKey(Size.class)) {
416 if (sizes!=null) defaults.put(Size.class,sizes);
417 else defaults.put(Size.class,new TreeSet());
418 }
419
420 if (mapunit==null) mapunit = defmapunit;
421 if (screenunit==null) screenunit = defscreenunit;
422
423 if (sectionlist==null) sectionlist = new Vector();
424
425 if (selections==null || selections[0]==null) {
426 selections = new Selection[4];
427 for (int i=0;i<4;i++)
428 selections[i] = new Selection(this);
429 }
430 }
431
432
433 public static String[] getSubdirList(JarFile source,String dirname) throws IOException{
434 Vector list = new Vector();
435 for (Enumeration entries = source.entries();
436 entries.hasMoreElements();) {
437 String name = ((JarEntry)entries.nextElement()).getName();
438 if (name.startsWith(dirname)
439 && !name.equals(dirname)) list.add(name);
440 }
441 String[] res = new String[list.size()];
442 for (int i=0;i<list.size();i++) res[i] = (String)list.elementAt(i);
443 return(res);
444 }
445
446
450 public static void copyFiles(JarFile source,String[] names) throws IOException{
451 for (Enumeration entries = source.entries();
452 entries.hasMoreElements();) {
453 JarEntry ent = (JarEntry)entries.nextElement();
454 String name = ent.getName();
455 for (int i=0;i<names.length;i++) {
456 if (name.equals(names[i])) {
457 if (ent.isDirectory()) {
458 (new File(filebase,name)).mkdir();
459
460 String[] subs = getSubdirList(source,name);
461
462 copyFiles(source,subs);
463 } else {
464 File dest = new File(filebase,name);
465 try {
466 InputStream instr = source.getInputStream(ent);
467 OutputStream outstr = new FileOutputStream(dest);
468 byte[] buff = new byte[1000];
469 for (int num = 0;num>=0;) {
470 outstr.write(buff,0,num);
471 num = instr.read(buff);
472 }
473 outstr.close();
474 } catch (IOException e) {
475 ErrorLog.exception(e,"Cannot write "+dest);
476 }
477 }
478 }
479 }
480 }
481 }
482
483
484 public static void copyFile(String name){
485 URL source = runversion.getClass().getResource(name);
486
487 File dest = new File(filebase,name);
488 try {
489 InputStream instr = source.openStream();
490 OutputStream outstr = new FileOutputStream(dest);
491 byte[] buff = new byte[1000];
492 for (int num = 0;num>=0;) {
493 outstr.write(buff,0,num);
494 num = instr.read(buff);
495 }
496 outstr.close();
497 } catch (IOException e) {
498 ErrorLog.exception(e,"Cannot write "+dest);
499 }
500 }
501
502 public static String[] installfiles = {"gpl.txt","contributors.txt","version.txt","symbol/","stamp/","help/"};
503
504
505
511 public static void checkInstall() {
512 File name = new File(filebase,"version.txt");
513 if (!name.exists()) {
514 ErrorLog.logOK("Installing files");
515 try {
516 JarFile source = ((JarURLConnection)(runversion.getClass().
517 getResource("version.txt").openConnection())).getJarFile();
518 copyFiles(source,installfiles);
519
520
521
522 } catch (IOException e) {ErrorLog.exception(e,"trouble installing");}
523 }
524 if (!Persist.statefile.exists()) {
525 ErrorLog.logOK("Creating new default Preferences :"+Persist.statefile);
526 (new Persist()).saveState();
527 }
528 }
529
530
532 public void printStats(PrintStream out) {
533 double area = 0;
534 double afact = 0;
535 String aname = "hectares";
536 NumberFormat form = NumberFormat.getNumberInstance();
537 form.setMaximumFractionDigits(2);
538
539 afact = Unit.meter.toUnit(mapunit);
540 afact *= afact;
541 afact /= 10000;
542
543 if (mapunit == Unit.foot) {
544 afact/= 0.4047;
545 aname = "acres";
546 }
547
548 out.println("last survey update "+survey.name);
549 out.println(""+survey.stations.size()+" stations "+survey.shots.size()+" shots");
550
551 out.println("\n"+segmentlist.size()+" Segments");
552
553 int namemax = 0;
554 int filemax = 0;
555 for (Iterator it = segmentlist.iterator(); it.hasNext();) {
556 Segment seg = (Segment)it.next();
557 int length = seg.name.length();
558 if (length>namemax) namemax = length;
559 length = seg.isource.source.getName().length();
560 if (length>filemax) filemax = length;
561 }
562
563 for (Iterator it = segmentlist.iterator(); it.hasNext();) {
564 Segment seg = (Segment)it.next();
565 double sarea = seg.area();
566 area += sarea;
567 StringBuffer buff = new StringBuffer();
568 buff.append(seg.name);
569 while (buff.length() < namemax+5) buff.append(' ');
570 buff.append("file = "+seg.isource.source.getName());
571 while (buff.length() < namemax+filemax+18) buff.append(' ');
572 buff.append("area = "+form.format(sarea)+" sq "+mapunit+
573 " ("+form.format(sarea*afact)+" "+aname+")");
574 out.println(buff);
575 }
576 out.println("\nTotal area of segments = "+form.format(area)+" square "+mapunit+
577 " ("+form.format(area*afact)+" "+aname+")");
578
579 area = Segment.totalArea(segmentlist);
580 out.println("\nEstimated Cave area = "+form.format(area)+" square "+mapunit+
581 " ("+form.format(area*afact)+" "+aname+")");
582
583 out.println("\n"+complist.size()+" Composites");
584
585 for (Iterator it = complist.iterator(); it.hasNext();)
586 out.println(""+((Comp)it.next()).name);
587 }
588
589
594 static public void main(String args[]) {
595 boolean stats = false;
596 int i;
597
598 String filename = null;
599 for (i=0;i<args.length;i++) {
600 if (args[i].equals("-b")) {
601 filebase = new File(filebase,args[i+1]);
602 i++;
603 }
604 if (args[i].equals("-s")) {
605
606 stats = true;
607 i++;
608 break;
609 }
610 else if (i==args.length-1)
611 filename = args[i];
612 }
613
614 ErrorLog log = null;
615
616 try {
617 System.setErr(log=new ErrorLog());
618 } catch (Exception e2) {
619 System.out.println("Trying to set up the error file itself caused an error");
620 System.out.println("RunID = "+Persist.current.getRunID());
621 e2.printStackTrace();
622 }
623
624 checkInstall();
625
626 Persist.restore();
627
628 log.logMessage();
629
630 System.out.print(runversion.getAbout());
631
632 File startfile = null;
633 if (filename!=null) startfile = new File(filebase,filename);
634
635 if (stats) {
636 try {
637
638
639
640
641 for (;i<args.length;i++) {
642 File file = new File(filebase,args[i]);
643 System.out.println("\nCarto File "+file.getName());
644 read(file).printStats(System.out);
645 }
646 } catch (Exception ex) {
647 log.exception(ex,"Trouble printing stats");
648 System.exit(1);
649 }
650 }
651 else {
652 CartoFrame frame = new CartoFrame(startfile);
653
654 frame.show();
655
656 frame.setLocation(CartoFrame.initialx,CartoFrame.initialy);
657 }
658 }
659 }
660
661