8 class FordFulk extends Applet
10 int WIRESHIFT=8,WIREARROW=16;
11 double NODEGAPSCALE=1./2;
12 double WIREFONTSCALE=1.,NODEFONTSCALE=3./2;
13 double WIRECAPBALANCE=3./5,WIREFLGBALANCE=4./5;
16 Color wirecolor=Color.blue,
17 wiretextfgcolor=Color.yellow,
18 wiretextbgcolor=Color.black,
19 wireflgyescolor=Color.green,
20 wireflgnocolor =Color.red,
21 wirebackcolor =Color.green,
22 nodeactivecolor=Color.magenta,
23 nodepassedcolor=Color.blue,
24 tgttextfgcolor =Color.white,
25 tgttextbgcolor =Color.black,
26 tgtarrowcolor =Color.cyan;
30 TextField linenotext,stopattext,statustext;
31 Button singlestep,nextlinestep,advancestep,continuerun,stopnow,resetnow;
33 FordFulkTextArea guidearea;
34 int lineno=0,stopat=0,linestot=0;
35 boolean stopplus=false;
36 static String cs_s[]={"fastest","100ms","1/2s","2s"},stext[]={"Working...","Delaying...","Ready."};
37 Hashtable guides=new Hashtable();
39 FordFulkThread thread;
40 boolean suspendtest=true,suspendbug=true;
43 static String sectionToString(FordFulkDataStream is,String sep) throws IOException
47 while ((l=is.getLine())!=null) { if (f) f=false; else s+=sep; s+=l; }
52 static StreamTokenizer sectionStreamTokenizer(FordFulkDataStream is) throws IOException
53 { return new StreamTokenizer(new StringBufferInputStream(sectionToString(is,"\n"))); }
55 static Vector readNumberChunk(FordFulkDataStream ffds,int divisor) throws IOException
57 StreamTokenizer fs=sectionStreamTokenizer(ffds);
58 Vector r=new Vector();
59 do switch (fs.nextToken()) {
61 r.addElement(new Integer(new Double(fs.nval).intValue()));
63 case fs.TT_EOF: break;
65 throw new IOException("Unexpected data type "+fs.ttype+",nval="+fs.nval+",sval="+fs.sval);
66 } while (fs.ttype!=fs.TT_EOF);
67 if ((r.size()%divisor)!=0) throw new IOException("Trailing specification of number data (div="+divisor+")");
71 public void initError(String s,Exception e)
72 { s="Applet init error: "+s+" of \""+DATAFN+"\": "+e.toString(); showStatus(s); System.out.println(s); }
74 public TextField labeledText(Panel p,String lab,String ini)
77 p1.setLayout(new GridBagLayout());
78 if (lab!=null) p1.add(new Label(lab));
79 TextField r=new TextField(ini,ini.length());
88 DATAFN=getParameter("DataFile");
89 setLayout(new GridLayout(1,0));
90 Vector pnts,wires,inis;
91 { Panel p=new Panel();
92 GridBagLayout gb=new GridBagLayout();
94 GridBagConstraints gbc=new GridBagConstraints();
95 gbc.fill=GridBagConstraints.BOTH;
96 gbc.gridwidth=GridBagConstraints.REMAINDER;
98 p.setBackground(Color.lightGray);
100 { Panel p1=new Panel();
101 p1.setLayout(new FlowLayout());
102 linenotext=labeledText(p1,"Line","- ");
103 stopattext=labeledText(p1,"Stop","- ");
104 { Panel p2=new Panel();
105 p2.setLayout(new GridBagLayout());
106 p2.add(new Label("Delay"));
107 p2.add(codespeed=new Choice());
108 for (int i=0;i<4;i++) codespeed.addItem(cs_s[i]);
112 statustext=labeledText(p1,null,stext[0]);
114 gb.setConstraints(p1,gbc);
117 { Panel p1=new Panel();
118 p1.setLayout(new GridLayout(2,3));
119 p1.add(singlestep =new Button("Single step" ));
120 p1.add(nextlinestep=new Button("Stop @ next" ));
121 p1.add(advancestep =new Button("Any further" ));
122 p1.add(continuerun =new Button("Continue/Run"));
123 p1.add(stopnow =new Button("Stop now" ));
124 p1.add(resetnow =new Button("Reset & stop"));
126 gb.setConstraints(p1,gbc);
129 codelist=new List(20,false);
130 FordFulkDataStream f=new FordFulkDataStream(new URL(getDocumentBase(),DATAFN).openStream());
132 while ((line=f.getLine())!=null) {
133 codelist.addItem(": "+line);
136 int lnol=new Integer(linestot).toString().length();
137 for (int i=1;i<=linestot;i++) {
138 String s="0000"+new Integer(i).toString();
139 codelist.replaceItem(s.substring(s.length()-lnol)+codelist.getItem(i-1),i-1);
146 which=readNumberChunk(f,1);
147 if (which.size()==0) break;
151 for (int i=0;i<which.size();i++) {
152 int j=((Integer)which.elementAt(i)).intValue();
153 if (j<0) { mult=true; rng+=" to "+(lj=-j); }
155 if (rng.length()!=0) { mult=true; rng+=", "; }
159 String s=(!mult && lj==0?"":("Comment for line"+(mult?"s ":" ")+rng+":\n"));
160 s+=sectionToString(f," ").replace('|','\n');
162 for (int i=0;i<which.size();i++) {
163 int j=((Integer)which.elementAt(i)).intValue();
164 if (j<0) while (lj<=-j) {
165 guides.put(new Integer(lj),s);
168 else guides.put(new Integer(j),s);
173 pnts=readNumberChunk(f,2);
174 wires=readNumberChunk(f,3);
175 inis=readNumberChunk(f,2);
176 if (inis.size()!=2) throw new IOException("Source/dest chunk must have 2 values, not "+inis.size()+"!");
178 catch (MalformedURLException e) { initError("Malformed URL",e); return; }
179 catch (IOException e) { initError("Read",e); return; }
180 net=new FordFulkNet(this);
181 net.setup(pnts,wires,inis);
183 gbc.gridheight=GridBagConstraints.REMAINDER;
184 gb.setConstraints(net,gbc);
188 { Panel p=new Panel();
189 GridBagLayout gb=new GridBagLayout();
191 GridBagConstraints gbc=new GridBagConstraints();
192 gbc.fill=GridBagConstraints.BOTH;
193 gbc.gridwidth=GridBagConstraints.REMAINDER;
196 gb.setConstraints(codelist,gbc);
199 guidearea=new FordFulkTextArea();
200 guidearea.setEditable(false);
202 gb.setConstraints(guidearea,gbc);
210 lineno=0; codeListSelect();
213 thread=new FordFulkThread(this,false);
215 new FordFulkThread(this,true).start();
218 public synchronized void setNumText(TextField t,int i,boolean ifplus)
222 case -1: s="single"; break;
223 case 0: s="stop"; break;
224 case Integer.MAX_VALUE: s="never"; break;
225 default: s=new Integer(i).toString()+(ifplus?"+":"");
230 public synchronized void codeListSelect()
232 setNumText(linenotext,lineno,false);
234 codelist.select(lineno-1);
235 codelist.makeVisible(lineno-1);
237 else codelist.deselect(codelist.getSelectedIndex());
238 String s=(String)guides.get(new Integer(lineno));
239 if (s==null) s="Sorry, no guide defined for line "+lineno+".";
240 guidearea.setRawText(s);
243 public synchronized void newStopAt(int newstop)
245 setNumText(stopattext,stopat=newstop,stopplus);
246 if (thread==null) return;
247 thread.resume(); thread.interrupt();
250 public synchronized boolean handleEvent(Event ev)
252 if (ev.target==codelist && (ev.id==ev.LIST_SELECT || ev.id==ev.LIST_DESELECT || ev.id==ev.ACTION_EVENT))
253 { newStopAt(codelist.getSelectedIndex()+1); return true; }
257 case ev.ACTION_EVENT:
258 if (ev.target==nextlinestep)
259 { stopplus=false; newStopAt(lineno+1); return true; }
260 if (ev.target==singlestep)
261 { newStopAt(-1); return true; }
262 if (ev.target==continuerun)
263 { newStopAt(Integer.MAX_VALUE); return true; }
264 if (ev.target==advancestep)
265 { stopplus=true; newStopAt(lineno+1); return true; }
266 if (ev.target==stopnow)
267 { newStopAt(0); return true; }
268 if (ev.target==resetnow)
270 lineno=0; codeListSelect();
280 public String getAppletInfo()
283 "FordFulk by Jan Kratochvil <short@ucw.cz> in 1998.\n"+
284 "Redistribution permitted under GNU General Public License (AKA GPL) version 2 (exactly) found on ftp://prep.ai.mit.edu/pub/gnu/GPL."
288 public static void drawLine(Graphics g,Point p1,Point p2)
289 { g.drawLine(p1.x,p1.y,p2.x,p2.y); }
290 public static void drawString(Graphics g,String s,FordFulkPoint p,Color Bg,boolean docen,double fntscl)
293 g.setFont(new Font(of.getName(),of.getStyle(),(int)(of.getSize()*fntscl)));
294 FontMetrics m=g.getFontMetrics();
295 int w=m.stringWidth(s);
296 if (docen) p.translate(-w/2.,+m.getAscent()/2.);
299 int h=m.getAscent()+m.getDescent();
300 Color tc=g.getColor();
302 g.fillRect(ip.x,ip.y-m.getAscent(),w,h);
305 g.drawString(s,ip.x,ip.y);
308 public static void fillCircleColor(Graphics g,Point p,int r,Color c)
310 if (c!=null) g.setColor(c);
311 g.fillOval(p.x,p.y,r,r);
314 Enumeration l2e=null;
315 FordFulkWire l3w=null,l5w=null,l20w=null;
317 int l7S=0,l9T=0,l17D=0,l18J=0,l19I=0;
319 public synchronized void javaCleanCode(boolean hard)
321 FordFulk main=this; //for future separation
323 Enumeration e=main.net.W.elements();
324 while (e.hasMoreElements()) {
325 FordFulkWire w=(FordFulkWire)e.nextElement();
326 w.flgforw=w.flgback=null;
329 for (int i=0;i<main.net.nodes;i++) {
330 main.net.A[i].state=null;
331 main.net.A[i].back=-1;
333 for (int i=0;i<7;i++) main.net.tgtseta(i,null);
334 main.net.tgtsetD(null);
338 public int javaCode()
340 FordFulk main=this; //for future separation
349 l2e=main.net.W.elements();
352 if (!l2e.hasMoreElements()) {
356 l3w=(FordFulkWire)l2e.nextElement();
357 main.net.tgtseta(0,main.net.A[l3w.i]);
358 main.net.tgtseta(1,l3w);
359 main.net.tgtseta(2,null);
360 main.net.tgtseta(3,main.net.A[l3w.j]);
364 l3w.flgforw=((l3w.T<l3w.C) ?main.wireflgyescolor:main.wireflgnocolor);
365 l5w=(FordFulkWire)main.net.W.get(new Point(l3w.j,l3w.i));
366 main.net.tgtseta(2,l5w);
370 l3w.flgback=((l5w!=null && l5w.T>0) ?main.wireflgyescolor:main.wireflgnocolor);
371 for (int i=0;i<=3;i++) main.net.tgtseta(i,null);
375 main.net.A[main.net.iniS].state=main.nodeactivecolor;
377 l6v.addElement(new Integer(main.net.iniS));
381 if (l6v.size()==0) return 14;
382 l7S=((Integer)l6v.elementAt(0)).intValue();
383 main.net.tgtseta(4,main.net.A[l7S]);
387 if (l7S==main.net.iniD) return 14;
391 while (++l9T<main.net.nodes)
392 if (main.net.A[l9T].state==null) {
393 main.net.tgtseta(6,main.net.A[l9T]);
397 main.net.tgtseta(5,null);
398 main.net.tgtseta(6,null);
402 FordFulkWire wST=(FordFulkWire)main.net.W.get(new Point(l7S,l9T));
403 FordFulkWire wTS=(FordFulkWire)main.net.W.get(new Point(l9T,l7S));
404 if (!((wST!=null && wST.flgforw==main.wireflgyescolor)
405 ||(wTS!=null && wTS.flgback==main.wireflgyescolor)))
407 main.net.tgtseta(5,wST);
411 main.net.A[l9T].state=main.nodeactivecolor;
412 l6v.addElement(new Integer(l9T));
416 main.net.A[l9T].back=l7S;
420 l6v.removeElementAt(0);
421 main.net.A[l7S].state=main.nodepassedcolor;
425 if (l6v.size()!=0) return 16;
431 for (i=0;i<main.net.nodes;i++) main.net.A[i].backused=false;
433 for (i=main.net.iniD;i>=0;i=main.net.A[i].back) main.net.A[i].backused=true;
434 for (i=0;i<main.net.nodes;i++)
435 if (!main.net.A[i].backused) main.net.A[i].back=-1;
439 l17D=Integer.MAX_VALUE;
440 main.net.tgtsetD("inf");
445 main.net.tgtseta(0,main.net.A[l19I=main.net.iniD]);
450 main.net.tgtseta(1,null);
451 main.net.tgtseta(3,main.net.A[l18J=l19I]);
452 if ((l19I=main.net.A[l18J].back)==-1) {
453 main.net.tgtseta(0,null);
454 main.net.tgtseta(1,null);
456 return lineno+5;//19->24,25->30
458 main.net.tgtseta(0,main.net.A[l19I]);
459 l20w=(FordFulkWire)main.net.W.get(new Point(l19I,l18J));
460 main.net.tgtseta(1,l20w);
465 if (l20w==null || l20w.flgforw!=main.wireflgyescolor) return lineno+2;//20->22,26->28
466 main.net.tgtseta(1,l20w);
470 l17D=Math.min(l17D,l20w.C-l20w.T);
471 main.net.tgtsetD(new Integer(l17D).toString());
480 if (l20w==null || l20w.flgback!=main.wireflgyescolor) return lineno-3;//22->19,28->25
483 l17D=Math.min(l17D,((FordFulkWire)main.net.W.get(new Point(l18J,l19I))).T);
484 main.net.tgtsetD(new Integer(l17D).toString());
488 ((FordFulkWire)main.net.W.get(new Point(l18J,l19I))).T-=l17D;
492 javaCleanCode(false);
500 public synchronized void cycle()
502 statustext.setText(stext[0]);
504 if (stopat==0) return;
506 if ((newline=javaCode())==0) newline=lineno+1;
507 if (newline>linestot) {
509 setNumText(stopattext,stopat=0,stopplus=false);
511 if (stopat==-1 || stopat==newline || (stopat<newline && stopplus))
512 setNumText(stopattext,stopat=0,stopplus=false);
518 class FordFulkTextArea extends TextArea
520 private String conts="";
521 static final int VBARWIDTH=40,CHARWIDTH=8;
522 boolean painted=false,once=true;
525 public void setRawText(String s)
527 if (conts==s) return;
530 if (!painted) rawRefresh(null);
534 public void paint(Graphics g)
539 System.out.println("M$ Internet Explorer TextArea paint() override bug was a false alarm, this JVM is OK, sorry.");
541 rawRefresh(g.getFontMetrics());
545 public synchronized void rawRefresh(FontMetrics m)
547 int cols=Math.max(10,size().width-VBARWIDTH);
548 if (cols==lastwidth) return;
549 String s=new String(conts),line="",nline;
552 int spl=(m==null?CHARWIDTH/2:m.stringWidth(" "));
553 int ll=Integer.MAX_VALUE,cl;
554 while ((cl=s.length())<ll && cl>0) {
557 if (s.charAt(0)=='\n') {
558 appendText(line+"\n");
563 while ((i=s.indexOf(' '))==0) s=s.substring(1);
564 if (i==-1) i=s.length();
565 if ((j=s.substring(0,i).indexOf('\n'))!=-1) i=j;
566 nline=new String(line);
567 if (line.length()!=0) nline+=" ";
568 nline+=s.substring(0,i);
570 if (m!=null) thisw=m.stringWidth(nline);
571 else thisw=nline.length()*CHARWIDTH;
572 if (thisw>cols && line.length()!=0) {
573 appendText(line+"\n");
574 line=s.substring(0,i);
583 class FordFulkThread extends Thread
586 static int cs_v[]={0,100,500,2000};
589 public FordFulkThread(FordFulk _main,boolean _justfortest)
592 if (justfortest=_justfortest) setDaemon(true);
598 while (main.suspendtest) {
600 main.thread.countStackFrames();
601 main.suspendbug=false;
602 main.thread.resume();
603 if (!main.suspendtest) break;
605 catch (IllegalThreadStateException e) {}
606 try { sleep(main.BUGGYSLEEP); }
607 catch (InterruptedException e) {}
613 main.suspendtest=false;
615 System.out.println("Netscape Communicator suspend() bug, workarounding it...");
618 if (main.stopat==0) {
619 main.statustext.setText(main.stext[2]);
620 while (main.stopat==0) {
621 if (!main.suspendbug) suspend();
622 else try { sleep(main.BUGGYSLEEP); }
623 catch (InterruptedException e) {}
627 main.statustext.setText(main.stext[1]);
628 if (main.guidearea.once) {
629 main.guidearea.once=false;
630 System.out.println("M$ Internet Explorer TextArea paint() override bug, workarounding it...");
632 try { sleep((long)cs_v[main.codespeed.getSelectedIndex()]); }
633 catch (InterruptedException e) {}
639 class FordFulkDataStream extends DataInputStream
641 private String TERM="-";
644 public FordFulkDataStream(InputStream s)
646 public void lineLimit(int _togo)
649 public String getLine() throws IOException
651 if (togo==0) return null;
653 if (l==null) { togo=0; return null; }
654 if (l.trim().compareTo(TERM)==0) { togo=0; return null; }
659 public void nextSection() throws IOException
661 if (togo!=0) throw new IOException("nextSection() but togo=="+togo+"!");
670 public FordFulkPoint(int _x,int _y)
672 public FordFulkPoint(double _x,double _y)
674 public FordFulkPoint(FordFulkPoint p)
676 public FordFulkPoint(Point p)
678 public FordFulkPoint(FordFulkPoint p1,FordFulkPoint p2,double w)
679 { x=p1.point().x*(1-w)+p2.point().x*w; y=p1.point().y*(1-w)+p2.point().y*w; }
680 public FordFulkPoint(FordFulkPoint p1,FordFulkPoint p2) //arit. avg
681 { x=(p1.x+p2.x)/2; y=(p1.y+p2.y)/2; }
682 public void sub(FordFulkPoint p)
684 public void sub(Point p)
685 { sub(new FordFulkPoint(p)); }
687 { return new Point((int)x,(int)y); }
688 public Dimension dimension()
689 { return new Dimension((int)x,(int)y); }
690 public void translate(double _x,double _y)
692 public void translate(FordFulkPoint p)
693 { translate(p.x,p.y); }
694 public void rotplus90()
695 { double t=x; x=-y; y=t; }
696 public void rotminus90()
697 { double t=x; x=y; y=-t; }
698 public double length()
699 { return Math.sqrt(x*x+y*y); }
700 public void multiply(double c)
702 public void normalize(double len)
703 { multiply(len/length()); }
706 public String toString()
707 { return "FFP(x="+x+",y="+y+")"; }
710 interface FordFulkTargetable
712 public FordFulkPoint center();
713 public FordFulkPoint ffpSize();
716 class FordFulkWire implements FordFulkTargetable
721 Color flgforw=null,flgback=null;
725 public FordFulkWire(FordFulk _main,int _i,int _j,int _C)
726 { main=_main; i=_i; j=_j; C=_C; }
727 public void setup12(int shift)
730 p1=main.net.A[i].center();
731 p2=main.net.A[j].center();
732 rln=new FordFulkPoint(p2);
735 rln.normalize(shift);
736 p1.translate(rln); p2.translate(rln);
738 public synchronized void drawArrow(Graphics g,int shift)
741 anyArrow(main,g,p1,p2,main.net.nodeSize/2);
744 public static void anyArrow(FordFulk main,Graphics g,FordFulkPoint p1,FordFulkPoint p2,double shorten)
746 FordFulkPoint arrdir,arrwing,efix;
748 arrdir=new FordFulkPoint(p2);
750 efix=new FordFulkPoint(arrdir);
751 efix.normalize(-(shorten-1));
753 FordFulk.drawLine(g,p1.point(),p2.point());
754 arrdir.normalize(main.WIREARROW);
755 arrwing=new FordFulkPoint(arrdir);
757 arrdir=new FordFulkPoint(arrdir,arrwing);
759 arrwing=new FordFulkPoint(p2); arrwing.translate(arrdir);
760 FordFulk.drawLine(g,p2.point(),arrwing.point());
762 arrwing=new FordFulkPoint(p2); arrwing.translate(arrdir);
763 FordFulk.drawLine(g,p2.point(),arrwing.point());
768 public synchronized FordFulkPoint center()
770 setup12(main.WIRESHIFT);
771 return new FordFulkPoint(p1,p2);
773 public FordFulkPoint ffpSize()
774 { return new FordFulkPoint(1,1); }
776 public synchronized void paint(Graphics g)
778 if (main==null) return;
779 g.setColor(main.wirecolor);
780 drawArrow(g,main.WIRESHIFT);
782 g.setColor(main.wiretextfgcolor);
783 FordFulk.drawString(g,T+"/"+C,
784 new FordFulkPoint(p1,p2,main.WIRECAPBALANCE),
785 main.wiretextbgcolor,true,main.WIREFONTSCALE);
787 FordFulk.fillCircleColor(g,
788 new FordFulkPoint(p1,p2,main.WIREFLGBALANCE).point(),
789 main.WIREFLGRADIUS,flgforw);
791 FordFulk.fillCircleColor(g,
792 new FordFulkPoint(p1,p2,1-main.WIREFLGBALANCE).point(),
793 main.WIREFLGRADIUS,flgback);
797 class FordFulkNode implements FordFulkTargetable
806 public FordFulkNode(FordFulk _main,int _no,Point _pxy)
808 main=_main; pxy=_pxy;
809 no_s=new Integer(no=_no).toString();
810 if (no==main.net.iniS) no_s+="s";
811 if (no==main.net.iniD) no_s+="d";
814 public FordFulkPoint ffpSize()
815 { return new FordFulkPoint(main.net.nodeSize,main.net.nodeSize); }
816 public Dimension size()
817 { return ffpSize().dimension(); }
818 public FordFulkPoint ffpLocation()
819 { return new FordFulkPoint(
820 main.net.unitShift.x+main.net.unitSize.x*pxy.x,
821 main.net.unitShift.y+main.net.unitSize.y*pxy.y);
823 public Point location()
824 { return ffpLocation().point(); }
825 public Rectangle bounds()
826 { return new Rectangle(location(),size()); }
828 public void justBack(Graphics g)
830 if (no<0 || back<0) return;
831 FordFulkWire ffw=new FordFulkWire(main,no,back,0);
832 g.setColor(main.wirebackcolor);
836 public void paint(Graphics g)
839 Rectangle me=bounds();
840 g.setColor(main.net.getBackground());
841 g.fillOval(me.x,me.y,me.width,me.height);
842 g.setColor(main.net.getForeground());
843 g.drawOval(me.x,me.y,me.width,me.height);
845 FordFulk.drawString(g,no_s,center(),null,true,main.NODEFONTSCALE);
848 public FordFulkPoint center()
850 FordFulkPoint xy=ffpLocation(),wh=ffpSize();
851 return new FordFulkPoint(xy.x+wh.x/2,xy.y+wh.y/2);
855 class FordFulkNet extends Panel
860 Hashtable W=new Hashtable();
862 Vector blind=new Vector();
863 int nodesx=1,nodesy=1;
865 FordFulkPoint unitShift,unitSize;
867 String tgts[]={"i","Eij","Eji","j","s","Est","t",null};
868 FordFulkTargetable tgta[]=new FordFulkTargetable[7];
870 public FordFulkNet(FordFulk _main)
872 public void setup(Vector pnts,Vector wires,Vector inis)
874 setBackground(Color.white);
876 iniS=((Integer)inis.elementAt(0)).intValue();
877 iniD=((Integer)inis.elementAt(1)).intValue();
878 Hashtable ndh=new Hashtable();
879 for (int i=0;i<nodes;i++) {
880 int y=((Integer)pnts.elementAt(i*2 )).intValue(),
881 x=((Integer)pnts.elementAt(i*2+1)).intValue();
882 nodesy=Math.max(nodesy,y+1);
883 nodesx=Math.max(nodesx,x+1);
884 ndh.put(new Point(x,y),new Integer(i));
886 A=new FordFulkNode[nodes];
887 for (int i=0;i<7;i++) tgta[i]=null;
888 for (int y=0;y<nodesy;y++)
889 for (int x=0;x<nodesx;x++) {
891 Point pxy=new Point(x,y);
892 if ((ii=(Integer)ndh.get(pxy))==null)
893 blind.addElement(new FordFulkNode(main,-1,pxy));
895 A[ii.intValue()]=new FordFulkNode(main,ii.intValue(),pxy);
897 int wirecnt=wires.size()/3;
898 for (int i=0;i<wirecnt;i++) addWire(
899 ((Integer)wires.elementAt(i*3 )).intValue(),
900 ((Integer)wires.elementAt(i*3+1)).intValue(),
901 ((Integer)wires.elementAt(i*3+2)).intValue());
903 public void remWire(int i,int j)
904 { W.remove(new Point(i,j)); repaint(); }
905 public void addWire(int i,int j,int C)
906 { W.put(new Point(i,j),new FordFulkWire(main,i,j,C)); repaint(); }
908 public synchronized void tgtsetD(String d)
909 { tgts[7]=(d==null?null:"+"+d); }
910 public synchronized void tgtseta(int i,FordFulkTargetable tgt)
912 public synchronized void paint(Graphics gg)
916 Image img=createImage(sz.width,sz.height);
917 Graphics g=img.getGraphics();
919 unitSize=new FordFulkPoint(
920 sz.width /(nodesx+1-main.NODEGAPSCALE),
921 sz.height/(nodesy+1-main.NODEGAPSCALE));
922 nodeSize=Math.min(unitSize.x,unitSize.y);
923 unitShift=new FordFulkPoint(
924 unitSize.x*(1-main.NODEGAPSCALE)+(unitSize.x-nodeSize)/2,
925 unitSize.y*(1-main.NODEGAPSCALE)+(unitSize.y-nodeSize)/2);
926 nodeSize*=main.NODEGAPSCALE;
927 //System.out.println("nodeSize="+nodeSize+",unitShift="+unitShift+",unitSize="+unitSize+",nodesx="+nodesx+",nodesy="+nodesy);
929 Enumeration e=W.elements();
930 while (e.hasMoreElements()) ((FordFulkWire)e.nextElement()).paint(g);
931 for (int i=0;i<nodes;i++) A[i].justBack(g);
932 for (int i=0;i<nodes;i++) A[i].paint(g);
934 double dist=sz.width/9.;
935 FontMetrics m=g.getFontMetrics();
936 int fny=sz.height-2*m.getLeading()-(m.getAscent()+m.getDescent())/2;
937 for (int i=0;i<7;i++) {
938 if (tgta[i]==null) continue;
939 double fnx=(i+1)*dist;
940 g.setColor(main.tgttextfgcolor);
941 FordFulk.drawString(g," "+tgts[i]+" ",new FordFulkPoint(fnx,(double)fny),main.tgttextbgcolor,true,1.);
942 g.setColor(main.tgtarrowcolor);
943 FordFulkWire.anyArrow(main,g,new FordFulkPoint(fnx,(double)(sz.height-m.getHeight()-1)),tgta[i].center(),tgta[i].ffpSize().x/4);
946 g.setColor(main.tgttextfgcolor);
947 FordFulk.drawString(g," d="+tgts[7]+" ",new FordFulkPoint(8*dist,(double)(fny-1)),main.tgttextbgcolor,true,1.);
949 gg.drawImage(img,0,0,this);
951 public void update(Graphics gg)