Back to index

wims  3.65+svn20090927
ZirkelCanvas.java
Go to the documentation of this file.
00001 package rene.zirkel;
00002 
00003 // file: ZirkelCanvas.java
00004 
00005 import java.awt.*;
00006 import java.awt.datatransfer.*;
00007 import java.awt.event.*;
00008 import java.util.*;
00009 import java.util.zip.*;
00010 import java.io.*;
00011 
00012 import rene.util.xml.*;
00013 import rene.gui.*;
00014 import rene.dialogs.*;
00015 import rene.zirkel.construction.*;
00016 import rene.zirkel.constructors.*;
00017 import rene.zirkel.dialogs.*;
00018 import rene.zirkel.expression.*;
00019 import rene.zirkel.graphics.*;
00020 import rene.zirkel.listener.*;
00021 import rene.zirkel.macro.*;
00022 import rene.zirkel.objects.*;
00023 import rene.zirkel.structures.*;
00024 import rene.zirkel.tools.*;
00025 import rene.util.*;
00026 import rene.util.sort.*;
00027 
00028 import atp.sHotEqn;
00029 
00036 public class ZirkelCanvas extends Panel
00037        implements MouseListener,MouseMotionListener,ItemListener,
00038               AddEventListener,ActionListener,ChangedListener,MouseWheelListener
00039 // the canvas to do the construction
00040 {      ObjectConstructor OC=new MoverTool();
00041               // the current object constructor
00042        Construction C=new Construction(),COriginal;
00043               // the construction (collection of Constructor-Objects)
00044        StatusListener SL=null;
00045               // for displaying a status message
00046        public Image I=null;
00047        MyGraphics IG;
00048        Image Background=null;
00049        FontMetrics FM;
00050        double PointSize=4.0; // Size of a point
00051        double MinPointSize=3.0; // Default minimal point size
00052        double FontSize=12.0; // Size of font
00053        double MinFontSize=12.0; // Default minimal font size
00054        public int IW=0,IH=0; // Image and its dimensions
00055        public double Xmin,DX,Ymin,DY;
00056        boolean ShowHidden=false; // show hidden objects
00057        Frame F=new Frame();
00058        boolean ReadOnly;
00059        boolean AllowRightMouse=true;
00060        PopupMenu PM;
00061        CheckboxMenuItem CheckboxHidden;
00062        MenuItem Replay,Empty;
00063        boolean Job=false; // this is a job (save as such)
00064        String Last=""; // Last displayed job object
00065        Vector Targets=new Vector(); // Target names
00066        ConstructionObject TargetO[],TargetS[]; // Target objects and solutions
00067        int ShowColor=0; // 0=all, 1=green etc. (black displays always)
00068        static public double // factors for rounding
00069               EditFactor=1000000.0,
00070               LengthsFactor=100.0,
00071               AnglesFactor=1.0;
00072        public boolean 
00073               Visual=Global.getParameter("options.visual",true);
00074        boolean All;
00075        boolean Interactive=true;
00076        public int GridColor=0,GridThickness=ConstructionObject.THIN;
00077        public boolean ShowGrid=false,AxesOnly=false;
00078        public boolean GridLabels=true,GridBold=false,GridLarge=false;
00079 
00088        public ZirkelCanvas (boolean readonly, boolean replay, boolean hidden)
00089        {      ReadOnly=readonly;
00090               AllowRightMouse=!readonly;
00091               if (Global.getParameter("options.nopopupmenu",false))
00092               {      PM=null;
00093               }
00094               else if (ReadOnly)
00095               {      PM=new PopupMenu();
00096                      CheckboxHidden=new MyCheckboxMenuItem(
00097                             Zirkel.name("popup.hidden"));
00098                      CheckboxHidden.addItemListener(this);
00099                      if (hidden) PM.add(CheckboxHidden);
00100                      Replay=new MyMenuItem(
00101                             Zirkel.name("popup.replay"));
00102                      Replay.addActionListener(this);
00103                      if (replay) PM.add(Replay);
00104                      if (hidden || replay) add(PM);
00105                      else PM=null;
00106               }
00107               else
00108               {      PM=new PopupMenu();
00109                      Empty=new MyMenuItem(
00110                             Zirkel.name("popup.empty"));
00111                      add(PM);
00112               }
00113               C.CL=this;
00114               clear();
00115               updateDigits();
00116               C.addAddEventListener(this);
00117               addMouseWheelListener(this);
00118        }
00119        public ZirkelCanvas (boolean readonly)
00120        {      this(readonly,true,true);
00121        }
00122        public ZirkelCanvas ()
00123        {      this(false,true,true);
00124        }
00125        
00126        public Dimension UseSize=null;
00127        
00128        public Dimension getMinimumSize ()
00129        {      if (Background==null || !Global.getParameter("background.usesize",false))
00130               {      if (UseSize!=null) return UseSize;
00131                      else return new Dimension(600,600);
00132               }
00133               else
00134               {      int iw=Background.getWidth(this);
00135                      if (iw<10) return new Dimension(600,600);
00136                      int ih=Background.getHeight(this);
00137                      if (Global.getParameter("background.usewidth",false))
00138                      {      int w=getSize().width,h=(int)((double)ih/iw*w+0.5);
00139                             return new Dimension(w,h);
00140                      }
00141                      else
00142                             return new Dimension(iw,ih);
00143               }
00144        }
00145        
00146        public Dimension getPreferredSize ()
00147        {      return getMinimumSize();
00148        }
00149 
00150        public void updateDigits ()
00151        {      EditFactor=Math.pow(10,
00152                      Global.getParameter("digits.edit",5));
00153               LengthsFactor=Math.pow(10,
00154                      Global.getParameter("digits.lengths",5));
00155               AnglesFactor=Math.pow(10,
00156                      Global.getParameter("digits.angles",0));
00157        }
00158 
00159        public void itemStateChanged (ItemEvent e)
00160        {      if (e.getSource()==CheckboxHidden)
00161               {      ShowHidden=CheckboxHidden.getState();
00162                      repaint();
00163               }
00164        }
00165 
00166        ZirkelCanvasInterface ZCI;
00167        
00168        public void setZirkelCanvasListener (ZirkelCanvasInterface zci)
00169        {      ZCI=zci;
00170        }
00171        
00172        public String loadImage ()
00173        {      return ZCI.loadImage();
00174        }
00175        
00176        public Image doLoadImage (String filename)
00177        {      return ZCI.doLoadImage(filename);
00178        }
00179        
00180        public void actionPerformed (ActionEvent e)
00181        {      if (!Interactive) return;
00182               if (e.getSource()==Replay)
00183               {      if (ZCI!=null) ZCI.replayChosen();
00184               }
00185               else
00186               {      Enumeration en=Macros.elements();
00187                      while (en.hasMoreElements())
00188                      {      MacroItem m=(MacroItem)en.nextElement();
00189                             if (m.I==e.getSource())
00190                             {      if (ZCI!=null) ZCI.runMacro(m.M);
00191                                    break;
00192                             }
00193                      }
00194               }
00195        }
00196 
00197        // Some transfer functions to compute screen coordinates etc.
00198        
00199        public double col (double x)
00200        {      return (x-Xmin)/DX*IW;
00201        }
00202        public double row (double y)
00203        {      return IH-(y-Ymin)/DY*IH;
00204        }
00205        public int width ()
00206        {      return IW;
00207        }
00208        public int height ()
00209        {      return IH;
00210        }
00211        public double x (int c)
00212        {      return Xmin+DX*c/IW;
00213        }
00214        public double y (int r)
00215        {      return Ymin+DY*(IH-r)/IH;
00216        }
00217        public double dx (int c)
00218        {      return DX*c/IW;
00219        }
00220        public double dy (int r)
00221        {      return DY*r/IH;
00222        }
00223        public double dx (double c)
00224        {      return DX*c/IW;
00225        }
00226        public double dy (double r)
00227        {      return DY*r/IH;
00228        }
00229        public double maxX ()
00230        {      return Xmin+DX;
00231        }
00232        public double minX ()
00233        {      return Xmin;
00234        }
00235        public double maxY ()
00236        {      return Ymin+DY;
00237        }
00238        public double minY ()
00239        {      return Ymin;
00240        }
00241        public boolean isInside (double x, double y)
00242        {      return x>=Xmin && x<Xmin+DX && y>=Ymin && y<Ymin+DY;
00243        }
00244        public double dCenter (double x, double y)
00245        {      double dx=x-(Xmin+DX/2),dy=y-(Ymin+DY/2);
00246               return Math.sqrt(dx*dx+dy*dy)/
00247                      Math.max(DX/2,DY/2);
00248        }
00249        public void recompute ()
00250        {      if (IH<IW)
00251               {      Xmin=C.getX()-C.getW();
00252                      DX=C.getW()*2;
00253                      DY=DX/IW*IH;
00254                      Ymin=C.getY()-DY/2;
00255               }
00256               else
00257               {      Ymin=C.getY()-C.getW();
00258                      DY=C.getW()*2;
00259                      DX=DY/IH*IW;
00260                      Xmin=C.getX()-DY/2;
00261               }
00262               C.setH(DY);
00263               if (DX>0) C.setPixel(getSize().width/DX);
00264        }
00265 
00266        DoneListener DL;
00267        public void setDoneListener (DoneListener dl) { DL=dl; }
00268 
00272        public void addObject (ConstructionObject o)
00273        // called by the ObjectConstructor
00274        {      C.add(o);
00275               if (Preview)
00276               {      o.setIndicated(true);
00277                      o.setSelectable(false);
00278               }
00279               C.updateCircleDep();
00280        }
00281        
00286        public void added (Construction c, ConstructionObject o)
00287        {      if (displayJob() && TargetO.length>0)
00288               {      boolean olddone=true;
00289                      for (int i=0; i<TargetO.length; i++)
00290                      {      if (TargetS[i]!=null && !TargetS[i].isInConstruction())
00291                                    TargetS[i]=null;
00292                             if (TargetS[i]!=null) continue;
00293                             else olddone=false;
00294                             if (TargetO[i].equals(o))
00295                             {      TargetS[i]=o;
00296                             }
00297                      }
00298                      boolean done=true;
00299                      for (int i=0; i<TargetO.length; i++)
00300                      {      if (TargetS[i]==null)
00301                             {      done=false; break;
00302                             }
00303                      }
00304                      if (done && DL!=null && !olddone)
00305                      {      repaint();
00306                             DL.notifyDone();
00307                             freeJob();
00308                      }
00309               }
00310               repaint();
00311        }
00312 
00313        public boolean check (Construction c)
00314        {      int n=TargetO.length;
00315               for (int i=0; i<n; i++)
00316               {      TargetS[i]=null;
00317               }
00318               int found=0;
00319               Enumeration e=c.elements();
00320               while (e.hasMoreElements())
00321               {      ConstructionObject o=(ConstructionObject)e.nextElement();
00322                      if (o.isKeep()) continue;
00323                      for (int i=0; i<n; i++)
00324                      {      if (TargetS[i]!=null) continue;
00325                             if (o.equals(TargetO[i]))
00326                             {      TargetS[i]=o;
00327                                    found++; break;
00328                             }
00329                      }
00330               }
00331               return found==n;
00332        }
00333        
00337        public void check ()
00338        {      if (displayJob() && TargetO.length>0)
00339               {      boolean olddone=true;
00340                      for (int i=0; i<TargetO.length; i++)
00341                      {      if (TargetS[i]!=null && !TargetS[i].isInConstruction())
00342                                    TargetS[i]=null;
00343                             if (TargetS[i]!=null) continue;
00344                             else olddone=false;
00345                      }
00346                      boolean done=check(C);
00347                      if (done && DL!=null && !olddone)
00348                      {      repaint();
00349                             DL.notifyDone();
00350                             freeJob();
00351                      }
00352               }
00353        }
00354 
00355        int Moved=0;
00356        
00357        boolean Dragging=false,RightClicked=false;
00358        
00359        boolean Control=false; // Control-Taste bei letztem Mausdruck aktiv?
00360        
00361        public boolean SmartBoardPreview=false;
00362        
00363        // mouse events:
00364        public synchronized void mousePressed (MouseEvent e)
00365        {      if (!Interactive) return;
00366               SmartBoardPreview=false;
00367               clearIndicated();
00368               clearPreview();
00369               repaint();
00370               requestFocus();
00371               Dragging=false;
00372               RightClicked=false;
00373               Moved=0;
00374               if (e.isMetaDown() && AllowRightMouse) // right mouse button!
00375               {      if (!ReadOnly)
00376                      {      ConstructionObject o=selectLabel(e.getX(),e.getY());
00377                             if (o!=null)
00378                             {      Dragging=true;
00379                                    setTool(new LabelMover(OC,this,e.getX(),e.getY(),
00380                                           o,e.isShiftDown()));
00381                                    return;
00382                             }
00383                             if (e.isShiftDown() && e.isControlDown()) // hiding shortcut
00384                             {      o=selectObject(e.getX(),e.getY());
00385                                    if (o==null) return;
00386                                    o.toggleHidden();
00387                                    repaint();
00388                                    return;
00389                             }
00390                             if (e.isControlDown()) // edit conditionals
00391                             {      o=selectObject(e.getX(),e.getY());
00392                                    if (o==null) return;
00393                                    new EditConditionals(getFrame(),o);
00394                                    validate();
00395                                    repaint();
00396                                    return;
00397                             }
00398                      }
00399                      ConstructionObject p=selectImmediateMoveableObject(
00400                             e.getX(),e.getY());
00401                      RightClicked=true;
00402                      if (p!=null)
00403                      {      Dragging=true;
00404                             setTool(new MetaMover(OC,this,p,e));
00405                             return;
00406                      }
00407                      else if (!Global.getParameter("options.nomousezoom",false)) // Drag mit rechter Maustaste
00408                      {      if (selectObjects(e.getX(),e.getY()).size()==0)
00409                             {      setTool(new ZoomerTool(OC,e,this));
00410                             }
00411                             return;
00412                      }
00413               }
00414               else // left mouse button!
00415               {      if (!SmartBoardPreview && Global.getParameter("smartboard",false) 
00416                             && OC.useSmartBoard())
00417                      {      OC.mouseMoved(e,this,
00418                                    Global.getParameter("options.indicate.simple",false));
00419                             SmartBoardPreview=true;
00420                             return;
00421                      }
00422                      else
00423                      {      Control=e.isControlDown();
00424                             OC.mousePressed(e,this); // pass to ObjectConstructor
00425                             Control=false;
00426                      }
00427               }
00428        }
00429 
00430        public synchronized void mouseReleased (MouseEvent e)
00431        {      if (!Interactive) return;
00432               if (DT!=null) DT.waitReady();
00433               if (RightClicked)
00434               {      RightClicked=false;
00435                      OC.mouseReleased(e,this);
00436                      if (Moved<=2 && AllowRightMouse && !ReadOnly)
00437                      {      MyVector v=selectObjects(e.getX(),e.getY());
00438                             if (v.size()>0)
00439                             {      ConstructionObject o=select(v,e.getX(),e.getY());
00440                                    if (o!=null)
00441                                    {      new EditTool().mousePressed(e,o,this);
00442                                           check();
00443                                           return;
00444                                    }
00445                                    else
00446                                    repaintCD();
00447                                    return;
00448                             }
00449                      }
00450                      if (Moved<=2 && PM!=null && !Global.getParameter("restricted",false))
00451                      {      int n=2;
00452                             if (ReadOnly || !Global.getParameter("options.doubleclick",false))
00453                                    n=1;
00454                             if (e.getClickCount()>=n && 
00455                                           (ReadOnly || Macros.size()!=0))
00456                                    PM.show(e.getComponent(),e.getX(),e.getY());
00457                      }
00458                      repaintCD();
00459                      return;
00460               }
00461               if (SmartBoardPreview && Global.getParameter("smartboard",false))
00462               {      Control=e.isControlDown();
00463                      clearIndicated();
00464                      clearPreview();
00465                      repaint();
00466                      Dragging=false;
00467                      OC.mousePressed(e,this);
00468                      SmartBoardPreview=false;
00469                      mouseReleased(e);
00470                      return;
00471               }
00472               if (!Dragging)
00473               {      OC.mouseReleased(e,this);
00474                      Dragging=false;
00475                      repaintCD();
00476                      return;
00477               }
00478               if (Moved<=1)
00479               {      if (OC instanceof LabelMover)
00480                      {      ((LabelMover)OC).resetPoint();
00481                             OC.mouseReleased(e,this);
00482                      }
00483                      else if (OC instanceof MetaMover)
00484                      {      OC.mouseReleased(e,this);
00485                             if (!ReadOnly) new EditTool().mousePressed(e,this);
00486                      }
00487               }
00488               else OC.mouseReleased(e,this);
00489               repaintCD();
00490               check();
00491               Dragging=false;
00492        }
00493 
00494        public synchronized void mouseClicked (MouseEvent e) {}
00495        
00496        public synchronized void mouseExited (MouseEvent e)
00497        {      if (!Interactive) return;
00498               clearIndicated();
00499               clearPreview();
00500               repaint();
00501               SmartBoardPreview=false;
00502               RightClicked=false;
00503               repaintCD();
00504        }
00505        
00506        public void mouseEntered (MouseEvent e) {}
00507        
00508        public synchronized void mouseMoved (MouseEvent e)
00509        {      if (!Interactive ||
00510                      !Global.getParameter("options.indicate",true)) return;
00511               if (Global.getParameter("smartboard",false)) return;
00512               Count.setAllAlternate(true);
00513               OC.mouseMoved(e,this,Global.getParameter("options.indicate.simple",false));
00514               Count.setAllAlternate(false);
00515               repaintCD();
00516        }
00517        
00518        DragThread DT=null;
00519 
00520        public synchronized void mouseDragged (MouseEvent e)
00521        {      if (!Interactive) return;
00522               if (DT==null) DT=new DragThread(this);
00523               if (SmartBoardPreview 
00524                      && Global.getParameter("smartboard",false)) 
00525                             OC.mouseMoved(e,this,
00526                                    Global.getParameter("options.indicate.simple",false));
00527               else 
00528               {      DT.mouseDragged(e);
00529                      Moved++;
00530               }
00531               repaintCD();
00532        }
00533        
00534        public synchronized void doMouseDragged (MouseEvent e)
00535        {      OC.mouseDragged(e,this);
00536        }
00537        
00538        ConstructionObject LastPaint=null;
00539 
00540        public void newImage ()
00541        {      I=null; repaint();
00542        }
00543 
00544        boolean Frozen=false;
00545        public void setFrozen (boolean f)
00546        {      Frozen=f;
00547        }
00548        
00549        MessageWindow MW;
00550 
00551        final double PointSizeFactor=240.0;
00552        
00553        int CC=0;
00554        
00555        // repaint events
00556        public synchronized void paint (Graphics g)
00557        {      if (Frozen) return;
00558               int w=getSize().width,h=getSize().height;
00559               if (I==null || IW!=w || IH!=h)
00560               {      if (w==0 || h==0) return;
00561                      IW=w; IH=h;
00562                      I=createImage(IW,IH);
00563                      if (!Global.getParameter("printscalepreview",false)
00564                             || !Global.getParameter("printscale.sizes",false))
00565                      {      if (!Global.getParameter("simplegraphics",false))
00566                             {      IG=new MyGraphics13(I.getGraphics(),this);
00567                                    IG.setSize(IW,IH);
00568                             }
00569                             else
00570                             {      IG=new MyGraphics11(I.getGraphics());
00571                                    IG.setSize(IW,IH);
00572                             }
00573                             PointSize=IH/PointSizeFactor;
00574                             FontSize=PointSize*4;
00575                             MinPointSize=Global.getParameter("minpointsize",3);
00576                             if (PointSize<MinPointSize) PointSize=MinPointSize;
00577                             MinFontSize=Global.getParameter("minfontsize",12);
00578                             if (FontSize<MinFontSize) FontSize=MinFontSize;
00579                             IG.setDefaultFont((int)FontSize,
00580                                    Global.getParameter("font.large",false),
00581                                    Global.getParameter("font.bold",false));
00582                      }
00583                      else
00584                      {      double dpi=IW/
00585                                    Global.getParameter("printscale.width",5.0);
00586                             if (!Global.getParameter("simplegraphics",false))
00587                             {      IG=new MyGraphics13(I.getGraphics(),
00588                                           Global.getParameter("printscale.linewidth",0.02)*dpi,
00589                                           this,null);
00590                                    IG.setSize(IW,IH);
00591                             }
00592                             else
00593                             {      IG=new MyGraphics11(I.getGraphics());
00594                                    IG.setSize(IW,IH);
00595                             }
00596                             PointSize=Global.getParameter("printscale.pointsize",0.07)*dpi;
00597                             FontSize=Global.getParameter("printscale.textsize",0.3)*dpi;
00598                             IG.setDefaultFont((int)FontSize,
00599                                    Global.getParameter("font.large",false),
00600                                    Global.getParameter("font.bold",false));
00601                      }
00602                      recompute();
00603                      C.dovalidate();
00604               }
00605               IG.clearRect(0,0,IW,IH,getBackground());                
00606               if (Background!=null)
00607               {      int bw=Background.getWidth(this),
00608                             bh=Background.getHeight(this);
00609                      if (bw==IW && bh==IH)
00610                      {      IG.drawImage(Background,0,0,this);
00611                      }
00612                      else if (Global.getParameter("background.tile",true)
00613                             && bw<IW && bh<IH)
00614                      {      for (int i=(IW%bw)/2-bw; i<IW; i+=bw)
00615                                    for (int j=(IH%bh)/2-bh; j<IH; j+=bh)
00616                                           IG.drawImage(Background,i,j,this);
00617                      }
00618                      else if (Global.getParameter("background.center",true))
00619                      {      IG.drawImage(Background,(IW-bw)/2,(IH-bh)/2,this);
00620                      }
00621                      else
00622                      {      IG.drawImage(Background,0,0,IW,IH,this);
00623                      }
00624               }
00625               if (MW==null) 
00626               {      C.computeTracks(this);
00627                      dopaint(IG);
00628               }
00629               if (Global.getParameter("printscale.middle",false) &&
00630                      Global.getParameter("printscalepreview",false))
00631               {      
00632                      //IG.setColor(Color.red);
00633                      int PW=Global.getParameter("printscale.w",IW);
00634                      int PH=Global.getParameter("printscale.h",IH);
00635                      IG.drawRect(IW/2-PW/2-3,IH/2-PH/2-3,PW+7,PH+7);
00636               }
00637               g.drawImage(I,0,0,this);
00638        }
00639 
00640        public synchronized void resetGraphics ()
00641        {      I=null; repaint();
00642        }
00643        
00644        MyVector Breaks=new MyVector();
00645        
00646        public void updateBreakHide ()
00647        {      Breaks.removeAllElements();
00648               Enumeration e=C.elements();
00649               while (e.hasMoreElements())
00650               {      ConstructionObject o=(ConstructionObject)e.nextElement();
00651                      if (o==LastPaint || o==C.last()) break;
00652                      if (o.isBreak()) Breaks.addElement(o);
00653               }
00654               e=C.elements();
00655               ConstructionObject NextBreak=null;
00656               Enumeration eb=Breaks.elements();
00657               if (eb.hasMoreElements()) NextBreak=(ConstructionObject)eb.nextElement();
00658               while (e.hasMoreElements())
00659               {      ConstructionObject o=(ConstructionObject)e.nextElement();
00660                      if (NextBreak!=null && NextBreak.isHideBreak()) 
00661                             o.setBreakHide(true);
00662                      else 
00663                             o.setBreakHide(false);
00664                      if (o==NextBreak)
00665                      {      if (eb.hasMoreElements()) 
00666                                    NextBreak=(ConstructionObject)eb.nextElement();
00667                             else NextBreak=null;
00668                      }
00669                      if (o==LastPaint) break;
00670               }
00671        }
00672 
00673        void dopaint (MyGraphics IG)
00674        {      
00675               if (ShowGrid) 
00676               {      if (AxesOnly) paintAxes(IG);
00677                      else paintGrid(IG);
00678               }
00679               long time=System.currentTimeMillis();
00680               updateBreakHide();
00681               // count z-buffer elements and mark all as non-painted
00682               Enumeration e=C.elements();
00683               int n=0;
00684               while (e.hasMoreElements())
00685               {      ConstructionObject o=(ConstructionObject)e.nextElement();
00686                      o.HasZ=false;
00687                      o.IsDrawn=false;
00688                      try
00689                      {      if (!o.selected())
00690                             {      o.Value=-o.getZ(); o.HasZ=true; n++;
00691                             }
00692                      }
00693                      catch (Exception ex) {}
00694                      if (o==LastPaint) break;
00695               }
00696               // paint background objects
00697               e=C.elements();
00698               while (e.hasMoreElements())
00699               {      ConstructionObject o=(ConstructionObject)e.nextElement();
00700                      if (o.isBack() && !o.HasZ)
00701                      {      o.paint(IG,this); o.IsDrawn=true;
00702                      }
00703                      if (o==LastPaint) break;
00704               }
00705               // paint objects with z-buffer value in their order
00706               if (n>0)
00707               {      ConstructionObject os[]=new ConstructionObject[n];
00708                      e=C.elements();
00709                      n=0;
00710                      while (e.hasMoreElements())
00711                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
00712                             if (o.HasZ) os[n++]=o;
00713                      }
00714                      Sorter.sort(os);
00715                      for (int i=0; i<n; i++)
00716                      {      os[i].paint(IG,this);
00717                             os[i].IsDrawn=true;
00718                      }
00719               }
00720               // paint non-selected objects
00721               e=C.elements();
00722               while (e.hasMoreElements())
00723               {      ConstructionObject o=(ConstructionObject)e.nextElement();
00724                      if (!o.selected() && !o.IsDrawn)
00725                      {      o.paint(IG,this);
00726                             o.IsDrawn=true;
00727                      }
00728                      if (o==LastPaint) break;
00729               }
00730               // paint selected objects
00731               e=C.elements();
00732               while (e.hasMoreElements())
00733               {      ConstructionObject o=(ConstructionObject)e.nextElement();
00734                      if (!o.IsDrawn) 
00735                      {      o.paint(IG,this);
00736                             o.IsDrawn=true;
00737                      }
00738                      if (o==LastPaint) break;
00739               }
00740               if (LastPaint==null) paintTrack(IG);
00741               if (Interactive && IndicatePoint!=null) IndicatePoint.paint(IG,this);
00742               time=System.currentTimeMillis()-time;
00743               if (time>250 && PolygonDrawer.step<50) 
00744                      PolygonDrawer.step=PolygonDrawer.step*2;
00745               if (time<100 && PolygonDrawer.step>4) 
00746                      PolygonDrawer.step=PolygonDrawer.step/2;
00747               paintDrawings(IG);
00748        }
00749        
00750        void dopaintFig (MyGraphicsFig IG)
00751        {      if (ShowGrid) paintGrid(IG);
00752               IG.pushLayer(true);
00753               int layer=0;
00754               while (true)
00755               {      IG.pushLayer();
00756                      int l=0;
00757                      Enumeration e=C.elements();
00758                      while (e.hasMoreElements())
00759                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
00760                             if (o==LastPaint) break;
00761                             if (l==layer && o.isBack()) o.paint(IG,this);
00762                             if (o.isBreak())
00763                             {      l++;
00764                                    if (l>layer) break;
00765                             }
00766                      }
00767                      if (l<layer) break;
00768                      l=0;
00769                      e=C.elements();
00770                      while (e.hasMoreElements())
00771                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
00772                             if (o==LastPaint) break;
00773                             if (l==layer && !o.isBack() && !o.selected()) o.paint(IG,this);
00774                             if (o.isBreak())
00775                             {      l++;
00776                                    if (l>layer) break;
00777                             }
00778                      }
00779                      l=0;
00780                      e=C.elements();
00781                      while (e.hasMoreElements())
00782                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
00783                             if (o==LastPaint) break;
00784                             if (l==layer && !o.isBack() && o.selected()) o.paint(IG,this);
00785                             if (o.isBreak())
00786                             {      l++;
00787                                    if (l>layer) break;
00788                             }
00789                      }
00790                      layer++;
00791               }
00792               IG.pushLayer(false);
00793               if (LastPaint==null) paintTrack(IG);
00794        }
00795        
00796        int xg[]=new int[64],yg[]=new int[64];
00797        
00798        public void setGrid ()
00799        {      ShowGrid=Global.getParameter("showgrid",false);
00800               AxesOnly=Global.getParameter("axesonly",false);
00801               GridThickness=Global.getParameter("grid.thickness",ConstructionObject.THIN);
00802               GridColor=Global.getParameter("grid.colorindex",0);
00803               GridBold=Global.getParameter("grid.bold",false);
00804               GridLarge=Global.getParameter("grid.large",false);
00805               GridLabels=Global.getParameter("grid.labels",true);
00806        }
00807        
00812        void paintGrid (MyGraphics IG)
00813        {
00814               if (GridThickness==ConstructionObject.NORMAL)
00815                      IG.setColor(ZirkelFrame.Colors[Global.getParameter("grid.colorindex",0)]);
00816               else
00817                      IG.setColor(ZirkelFrame.LightColors[GridColor]);               
00818               IG.setFont(GridLarge,GridBold);
00819               double gridsize=getGridSize();
00820               //int dd=IH/200;
00821               // evers 14/03/2008
00822               int dd=IH;
00823               //if (dd<1) dd=1;
00824               double x1=Math.floor(
00825                      (C.getX()-C.getW())/gridsize-1)*gridsize;
00826               int xi=0;
00827               while (x1<(C.getX()+C.getW()) && xi<64)
00828               {      int c=(int)col(x1);
00829                      xg[xi++]=c;
00830                      x1+=gridsize;
00831               }
00832               double y1=Math.floor(
00833                      (C.getY()-C.getW())/gridsize-1)*gridsize;
00834               int yi=0;
00835               while (y1<(C.getY()+C.getW()) && yi<64)
00836               {      int r=(int)row(y1);
00837                      yg[yi++]=r;
00838                      y1+=gridsize;
00839               }
00840               for (int i=0; i<xi; i++)
00841               {      for (int j=0; j<yi; j++)
00842                      {      IG.drawLine(xg[i],yg[j]-dd,xg[i],yg[j]+dd);
00843                             IG.drawLine(xg[i]-dd,yg[j],xg[i]+dd,yg[j]);
00844                      }
00845               }
00846               if (GridThickness!=ConstructionObject.INVISIBLE)
00847               {      if (0<C.getX()+C.getW() && 0>C.getX()-C.getW())
00848                      {      int c=(int)col(0);
00849                             if (GridThickness!=ConstructionObject.THICK)
00850                                    IG.drawLine(c,0,c,IH);
00851                             else
00852                                    IG.drawThickLine(c,0,c,IH);
00853                      }
00854                      if (0<C.getY()+C.getW() && 0>C.getY()-C.getW())
00855                      {      int r=(int)row(0);
00856                             if (GridThickness!=ConstructionObject.THICK)
00857                                    IG.drawLine(0,r,IW,r);
00858                             else
00859                                    IG.drawThickLine(0,r,IW,r);
00860                      }
00861               }
00862 
00863               dd=dd*2;
00864               double labelsize=Math.pow(10,Math.floor(
00865                      Math.log(C.getW()*2)/Math.log(10)))/10;
00866               while (C.getW()*2/labelsize>=10) labelsize*=10;
00867               if (C.getW()*2/labelsize<5) labelsize/=2;
00868               FontMetrics fm=IG.getFontMetrics();
00869               int FH=fm.getHeight();
00870               x1=Math.floor(
00871                      (C.getX()-C.getW())/labelsize-1)*labelsize;
00872               int lh=(int)row(0);
00873               if (lh<0 || lh>IH-FH){      
00874                   lh=IH-FH;
00875               }
00876 
00877               while (x1<(C.getX()+C.getW()))
00878               {      int c=(int)col(x1);
00879                      String s=format(x1);
00880                      if (s.length()>0) 
00881                      {      if (GridLabels) IG.drawString(s,c+3,lh+FH);
00882                             IG.drawLine(c,lh-dd,c,lh+dd);
00883                      }
00884                      x1+=labelsize;
00885               }
00886               int lw=(int)col(0);
00887               if (lw<0 || lw>IW-20)
00888               {      lw=0;
00889               }
00890               y1=Math.floor((C.getY()-C.getW())/labelsize-1)*labelsize;
00891               while (y1<(C.getY()+C.getW()))
00892               {      int r=(int)row(y1);
00893                      String s=format(y1);
00894                      if (s.length()>0) 
00895                      {      if (GridLabels) IG.drawString(s,lw+3,r+FH);
00896                             IG.drawLine(lw-dd,r,lw+dd,r);
00897                      }
00898                      y1+=labelsize;
00899               }
00900               //axes jm.evers
00901               if(!Zirkel.IsApplet){
00902                   IG.drawThickLine((int)col(0),0,(int)col(0),IH);
00903                   IG.drawThickLine(0,(int)row(0),IW,(int)row(0));
00904                   IG.setColor(Color.red);
00905                   FontMetrics tm=IG.getFontMetrics();
00906                   int fh=tm.getHeight();
00907                   String yas=ZirkelApplet.yaxis_text+" ";
00908                   String xas=ZirkelApplet.xaxis_text;
00909                   IG.drawString(xas,(double)(col(0) + 3*fh),(double)(row(0) + fh));
00910                   int sy=yas.length();
00911                   if(ZirkelApplet.yaxis_text_vertical){
00912                      String char_y="";int p=0;int begin=0;int end=1;int r=0;
00913                      while( p < sy ){
00914                          char_y=yas.substring(begin,end);
00915                          if(char_y.indexOf(" ") == -1){
00916                             end++;
00917                          }
00918                          else
00919                          {
00920                             IG.drawString(char_y,(double)(col(0) - 2*fh),(double)(row(0) - (8*fh) + r*fh));
00921                             begin=end;
00922                             end++;
00923                             r++;
00924                          }
00925                          p++;
00926                      }
00927                   }
00928                   else
00929                   {
00930                      IG.drawString(yas,(double)(col(0) - (sy*fh)/2),(double)(row(0) - 10*fh));
00931                   }
00932               }
00933               // end jm.evers
00934        }
00935        
00940        void paintAxes (MyGraphics IG)
00941        {      if (GridThickness==ConstructionObject.NORMAL)
00942                      IG.setColor(ZirkelFrame.Colors[GridColor]);
00943               else
00944                      IG.setColor(ZirkelFrame.LightColors[GridColor]);               
00945               IG.setFont(GridLarge,GridBold);
00946               double gridsize=getGridSize();
00947               double x1=Math.floor(
00948                      (C.getX()-C.getW())/gridsize-1)*gridsize;
00949               int r0=(int)row(0);
00950               //int dd=IH/200;
00951               // evers 14/03/2008
00952               int dd=IH;
00953               //if (dd<1) dd=1;
00954               while (x1<(C.getX()+C.getW()))
00955               {      int c=(int)col(x1);
00956                      IG.drawLine(c,r0-dd,c,r0+dd);
00957                      x1+=gridsize;
00958               }
00959               double y1=Math.floor(
00960                      (C.getY()-C.getW())/gridsize-1)*gridsize;
00961               int c0=(int)col(0);
00962               while (y1<(C.getY()+C.getW()))
00963               {      int r=(int)row(y1);
00964                      IG.drawLine(c0-dd,r,c0+dd,r);
00965                      y1+=gridsize;
00966               }
00967 
00968               if (GridThickness!=ConstructionObject.INVISIBLE)
00969               {      if (0<C.getX()+C.getW() && 0>C.getX()-C.getW())
00970                      {      int c=(int)col(0);
00971                             if (GridThickness!=ConstructionObject.THICK)
00972                                    IG.drawLine(c,0,c,IH);
00973                             else
00974                                    IG.drawThickLine(c,0,c,IH);
00975                      }
00976                      if (0<C.getY()+C.getW() && 0>C.getY()-C.getW())
00977                      {      int r=(int)row(0);
00978                             if (GridThickness!=ConstructionObject.THICK)
00979                                    IG.drawLine(0,r,IW,r);
00980                             else
00981                                    IG.drawThickLine(0,r,IW,r);
00982                      }
00983               }
00984               // evers 14/03/2008
00985               //dd=dd*2;
00986               double labelsize=Math.pow(10,Math.floor(
00987                      Math.log(C.getW()*2)/Math.log(10)))/10;
00988               while (C.getW()*2/labelsize>=10) labelsize*=10;
00989               if (C.getW()*2/labelsize<5) labelsize/=2;
00990               FontMetrics fm=IG.getFontMetrics();
00991               int FH=fm.getHeight();
00992               x1=Math.floor(
00993                      (C.getX()-C.getW())/labelsize-1)*labelsize;
00994               int lh=(int)row(0);
00995               if (lh<0 || lh>IH-FH){      lh=IH-FH; }
00996               while (x1<(C.getX()+C.getW()))
00997               {      int c=(int)col(x1);
00998                      String s=format(x1);
00999                      if (GridLabels)      IG.drawString(s,c+4,lh+FH);
01000                      if (s.length()>0) IG.drawLine(c,lh-dd,c,lh+dd);
01001                      x1+=labelsize;
01002               }
01003               int lw=(int)col(0);
01004               if (lw<0 || lw>IW-20)
01005               {      lw=0;
01006               }
01007               y1=Math.floor(
01008                      (C.getY()-C.getW())/labelsize-1)*labelsize;
01009               while (y1<(C.getY()+C.getW()))
01010               {      int r=(int)row(y1);
01011                      String s=format(y1);
01012                      if (GridLabels) IG.drawString(s,lw+3,r+FH);
01013                      if (s.length()>0) IG.drawLine(lw-dd,r,lw+dd,r);
01014                      y1+=labelsize;
01015               }
01016 
01017        }
01018        
01019        
01020        public double pointSize ()
01021        {      return PointSize;
01022        }
01023        
01024        public double SelectionPointFactor=Global.getParameter("selectionsize",1.5);
01025        
01026        public double selectionSize ()
01027        {      return SelectionPointFactor*PointSize;
01028        }
01029        
01030        public double Scale=1.0;
01031        
01032        public int scale (int x)
01033        {      return (int)(Scale*x);
01034        }
01035        
01036        static char c[]=new char[20];
01037        int nc;
01038        public String format (double x)
01039        {      // double xx=x;
01040               nc=0;
01041               boolean minus=false;
01042               if (x<-1e-12)
01043               {      minus=true; x=-x;
01044               }
01045               x+=1e-12;
01046               double h=x-Math.floor(x);
01047               if (rekformat(h,8)) c[nc++]='.';
01048               while (x>=1)
01049               {      double s=Math.floor(x/10);
01050                      c[nc++]=(char)('0'+(int)(x-s*10));
01051                      x=s;
01052               }
01053               if (nc>0 && minus) c[nc++]='-';
01054               // revert c:
01055               for (int i=0; i<nc/2; i++)
01056               {      char hc=c[nc-1-i];
01057                      c[nc-1-i]=c[i];
01058                      c[i]=hc;
01059               }
01060               // System.out.println(xx+" -> "+new String(c,0,nc));
01061               return new String(c,0,nc);
01062        }
01063        
01064        boolean rekformat (double h, int k)
01065        {      h=h*10;
01066               double x=Math.floor(h);
01067               if (k==0)
01068               {      int i=(int)x;
01069                      if (i>0)
01070                      {      c[nc++]=(char)('0'+i);
01071                             return true;
01072                      }
01073                      else return false;
01074               }
01075               else
01076               {      int i=(int)x;
01077                      if (rekformat(h-x,k-1) || i>0)
01078                      {      c[nc++]=(char)('0'+i);
01079                             return true;
01080                      }
01081                      else return false;
01082               }
01083        }
01084        
01085        public void update (Graphics g)
01086        {      paint(g);
01087        }
01088        
01089        public void paintUntil (ConstructionObject o)
01090        {      if (LastPaint==o) return;
01091               LastPaint=o;
01092               repaint();
01093        }
01094        
01095        // validate all elements
01096        public void validate ()
01097        {      dovalidate();
01098               if (OC instanceof TrackPainter)
01099                      ((TrackPainter)OC).validate(this);
01100        }
01101        
01106        synchronized public void dovalidate ()
01107        {      C.dovalidate();
01108        }
01109 
01110        // selection routines:
01111 
01112        // This vector is used by ALL selection and indication routines for
01113        // performance reasons.
01114        MyVector V=new MyVector();
01115 
01116        public void sort (MyVector V)
01117        {      if (V.size()<2) return;
01118               Sorter.QuickSort(V.getArray(),0,V.size()-1);
01119        }
01120        
01125        public void sortRow (MyVector V)
01126        {      ConstructionObject o[]=new ConstructionObject[V.size()];
01127               V.copyInto(o);
01128               V.removeAllElements();
01129               Enumeration e=C.elements();
01130               while (e.hasMoreElements())
01131               {      ConstructionObject oo=(ConstructionObject)e.nextElement();
01132                      for (int i=0; i<o.length; i++)
01133                      {      if (o[i]==oo)
01134                             {      V.addElement(oo);
01135                                    break;
01136                             }
01137                      }
01138               }
01139        }
01140 
01144        public ConstructionObject selectCircleLine (int x, int y, boolean multiple)
01145        // select a circle or a line
01146        {      MyVector v=selectCircleLineObjects(x,y,multiple,false);
01147               return select(v);
01148        }
01149        public ConstructionObject selectCircleLine (int x, int y)
01150        // select a circle or a line
01151        {      return selectCircleLine(x,y,true);
01152        }
01153        
01157        public ConstructionObject selectPointonObject (int x, int y, boolean multiple)
01158        // select a circle or a line
01159        {      MyVector v=selectPointonObjects(x,y,multiple,false);
01160               return select(v);
01161        }
01162        public ConstructionObject selectPointonObject (int x, int y)
01163        // select a circle or a line
01164        {      return selectPointonObject(x,y,true);
01165        }
01166        
01176        public MyVector selectCircleLineObjects (int x, int y, boolean multiple, 
01177               boolean testlocal)
01178        // select a circle or a line
01179        {      Enumeration e=C.elements();
01180               V.removeAllElements();
01181               while (e.hasMoreElements())
01182               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01183                      if (o.isSelectable() && (o instanceof PrimitiveLineObject ||
01184                             o instanceof PrimitiveCircleObject)
01185                             && o.nearto(x,y,true,this) &&
01186                             (multiple || !o.selected()))
01187                      {      if (testlocal)
01188                             {      Enumeration ev=V.elements();
01189                                    while (ev.hasMoreElements())
01190                                    {      ConstructionObject ov=(ConstructionObject)ev.nextElement();
01191                                           if (o.locallyLike(ov))
01192                                           {      o=null;
01193                                                  break;
01194                                           }
01195                                    }
01196                             }
01197                             if (o!=null)
01198                             {      V.addElement(o);
01199                             }
01200                      }
01201               }
01202               return V;
01203        }
01204        public MyVector selectCircleLineObjects (int x, int y, boolean multiple)
01205        {      return selectCircleLineObjects(x,y,multiple,false);
01206        }
01207        public MyVector selectCircleLineObjects (int x, int y)
01208        {      return selectCircleLineObjects(x,y,true,false);
01209        }
01210 
01218        public MyVector selectPointonObjects (int x, int y, boolean multiple, 
01219               boolean testlocal)
01220        // select a circle or a line
01221        {      Enumeration e=C.elements();
01222               V.removeAllElements();
01223               while (e.hasMoreElements())
01224               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01225                      if (o.isSelectable() && (o instanceof PointonObject)
01226                             && o.nearto(x,y,true,this) &&
01227                             (multiple || !o.selected()))
01228                      {      if (testlocal)
01229                             {      Enumeration ev=V.elements();
01230                                    while (ev.hasMoreElements())
01231                                    {      ConstructionObject ov=(ConstructionObject)ev.nextElement();
01232                                           if (o.locallyLike(ov))
01233                                           {      o=null;
01234                                                  break;
01235                                           }
01236                                    }
01237                             }
01238                             if (o!=null)
01239                             {      V.addElement(o);
01240                             }
01241                      }
01242               }
01243               return V;
01244        }
01245        public MyVector selectPointonObjects (int x, int y, boolean multiple)
01246        {      return selectPointonObjects(x,y,multiple,false);
01247        }
01248        public MyVector selectPointonObjects (int x, int y)
01249        {      return selectPointonObjects(x,y,true,false);
01250        }
01251 
01256        public MyVector selectObjects (int x, int y, boolean multiple)
01257        {      Enumeration e=C.elements();
01258               V.removeAllElements();
01259               while (e.hasMoreElements())
01260               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01261                      if (o.isSelectable() && o.nearto(x,y,this) && (multiple || !o.selected()))
01262                             V.addElement(o);
01263               }
01264               return V;
01265        }
01266 
01267        public MyVector selectObjects (int x, int y)
01268        {      return selectObjects(x,y,true);
01269        }
01270 
01274        public ConstructionObject selectObject (int x, int y, boolean multiple)
01275        {      MyVector v=selectObjects(x,y,multiple);
01276               return select(v,x,y);
01277        }
01278 
01279        public ConstructionObject selectObject (int x, int y)
01280        {      return selectObject(x,y,true);
01281        }
01282 
01286        public MyVector selectConstructableObjects (int x, int y, boolean multiple)
01287        // select an enumeration of objects
01288        {      Enumeration e=C.elements();
01289               V.removeAllElements();
01290               while (e.hasMoreElements())
01291               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01292                      if (o.valid() && o.isFlag() && o.nearto(x,y,this) &&
01293                             (multiple || !o.selected()))
01294                             V.addElement(o);
01295               }
01296               return V;
01297        }
01298 
01299        public MyVector selectConstructableObjects (int x, int y)
01300        {      return selectConstructableObjects(x,y,true);
01301        }
01302 
01306        public ConstructionObject selectConstructableObject (int x, int y)
01307        {      MyVector v=selectConstructableObjects(x,y,true);
01308               return select(v,x,y); // user determines
01309        }
01310 
01311 
01316        public PrimitiveLineObject selectLine (int x, int y, boolean multiple)
01317        {      selectLineObjects(x,y,multiple);
01318               return (PrimitiveLineObject)select(V);
01319        }
01320        public void selectLineObjects (int x, int y, boolean multiple)
01321        {      Enumeration e=C.elements();
01322               V.removeAllElements();
01323               while (e.hasMoreElements())
01324               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01325                      if (o.isSelectable() && (o instanceof PrimitiveLineObject)
01326                             && o.nearto(x,y,this)
01327                             && (multiple || !o.selected()))
01328                             V.addElement(o);
01329               }
01330        }
01331        public PrimitiveLineObject selectLine (int x, int y)
01332        {      return selectLine(x,y,true);
01333        }
01334 
01338        public void selectPointsOrLines (int x, int y, boolean multiple)
01339        {      Enumeration e=C.elements();
01340               V.removeAllElements();
01341               while (e.hasMoreElements())
01342               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01343                      if (o.isSelectable() && (o instanceof PrimitiveLineObject
01344                             || o instanceof PointObject)
01345                             && o.nearto(x,y,this)
01346                             && (multiple || !o.selected()))
01347                             V.addElement(o);
01348               }
01349        }
01350 
01354        public TwoPointLineObject selectTwoPointLine (int x, int y, boolean multiple)
01355        {      selectTwoPointLines(x,y,multiple);
01356               return (TwoPointLineObject)select(V);
01357        }
01358        public void selectTwoPointLines (int x, int y, boolean multiple)
01359        {      Enumeration e=C.elements();
01360               V.removeAllElements();
01361               while (e.hasMoreElements())
01362               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01363                      if (o.isSelectable() && (o instanceof TwoPointLineObject)
01364                             && o.nearto(x,y,this)
01365                             && (multiple || !o.selected()))
01366                             V.addElement(o);
01367               }
01368        }
01369        public TwoPointLineObject selectTwoPointLine (int x, int y)
01370        {      return selectTwoPointLine(x,y,true);
01371        }
01372        
01376        public SegmentObject selectSegment (int x, int y, boolean multiple)
01377        {      selectSegments(x,y,multiple);
01378               return (SegmentObject)select(V);
01379        }
01380        public void selectSegments (int x, int y, boolean multiple)
01381        {      Enumeration e=C.elements();
01382               V.removeAllElements();
01383               while (e.hasMoreElements())
01384               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01385                      if (o.isSelectable() && (o instanceof SegmentObject)
01386                             && o.nearto(x,y,this)
01387                             && (multiple || !o.selected()))
01388                             V.addElement(o);
01389               }
01390        }
01391        public SegmentObject selectSegment (int x, int y)
01392        {      return selectSegment(x,y,true);
01393        }
01394        
01398        public RayObject selectRay (int x, int y, boolean multiple)
01399        {      selectRays(x,y,multiple);
01400               return (RayObject)select(V);
01401        }
01402        public void selectRays (int x, int y, boolean multiple)
01403        {      Enumeration e=C.elements();
01404               V.removeAllElements();
01405               while (e.hasMoreElements())
01406               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01407                      if (o.isSelectable() && (o instanceof RayObject)
01408                             && o.nearto(x,y,this)
01409                             && (multiple || !o.selected()))
01410                             V.addElement(o);
01411               }
01412        }
01413        public RayObject selectRay (int x, int y)
01414        {      return selectRay(x,y,true);
01415        }
01416        
01421        public PrimitiveCircleObject selectCircle (int x, int y, boolean multiple)
01422        {      selectCircles(x,y,multiple);
01423               return (PrimitiveCircleObject)select(V);
01424        }
01425        public void selectCircles (int x, int y, boolean multiple)
01426        {      Enumeration e=C.elements();
01427               V.removeAllElements();
01428               boolean haveNotFilled=false;
01429               while (e.hasMoreElements())
01430               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01431                      if (o.isSelectable() && (o instanceof PrimitiveCircleObject)
01432                             && o.nearto(x,y,this)
01433                             && (multiple || !o.selected()))
01434                             {      V.addElement(o);
01435                                    if (!o.isFilledForSelect()) haveNotFilled=true;
01436                             }
01437               }
01438               if (haveNotFilled)
01439               {      e=V.elements();
01440                      while (e.hasMoreElements())
01441                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
01442                             if (o.isFilledForSelect()) V.removeElement(o);
01443                      }
01444               }
01445        }
01446        public PrimitiveCircleObject selectCircle (int x, int y)
01447        {      return selectCircle(x,y,true);
01448        }
01449 
01453        public PointObject selectPoint (int x, int y, boolean multiple)
01454        {      selectPointObjects(x,y,multiple);
01455               return (PointObject)select(V);
01456        }
01457        public void selectPointObjects (int x, int y, boolean multiple)
01458        {      Enumeration e=C.elements();
01459               V.removeAllElements();
01460               while (e.hasMoreElements())
01461               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01462                      if (o.isSelectable() && o instanceof PointObject && o.nearto(x,y,this)
01463                             && (multiple || !o.selected()))
01464                             V.addElement(o);
01465               }
01466        }
01467        public PointObject selectPoint (int x, int y)
01468        {      return selectPoint(x,y,true);
01469        }
01470        public PointObject selectPoint (int x, int y, boolean multiple, 
01471               ConstructionObject until)
01472        {      selectPointObjects(x,y,multiple,until);
01473               return (PointObject)select(V);
01474        }
01475        public void selectPointObjects (int x, int y, boolean multiple, 
01476               ConstructionObject until)
01477        {      Enumeration e=C.elements();
01478               V.removeAllElements();
01479               while (e.hasMoreElements())
01480               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01481                      if (o==until) break;
01482                      if (o.isSelectable() && o instanceof PointObject && o.nearto(x,y,this)
01483                             && (multiple || !o.selected()))
01484                             V.addElement(o);
01485               }
01486        }
01487        public PointObject selectPoint (int x, int y, ConstructionObject until)
01488        {      return selectPoint(x,y,true,until);
01489        }
01490 
01491        boolean NewPoint=false;
01492        public boolean isNewPoint () { return NewPoint; }
01493 
01502        public PointObject selectCreatePoint (int x, int y, boolean multiple,
01503               boolean any)
01504        {      NewPoint=false;
01505               if (Preview)
01506               {      PointObject p=new PointObject(C,x(x),y(y));
01507                      addObject(p);
01508                      p.setSuperHidden(true);
01509                      PreviewObject=p;
01510                      return p;
01511               }
01512               
01513               // User selects a known point:
01514               Enumeration e=C.elements();
01515               V.removeAllElements();
01516               while (e.hasMoreElements())
01517               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01518                      if (o.isSelectable() && o instanceof PointObject && o.nearto(x,y,this)
01519                             && (multiple || !o.selected()))
01520                                    V.addElement(o);
01521                      sort(V);
01522               }
01523               if (V.size()>0)
01524               {      if (any) return (PointObject)(V.elementAt(0));
01525                      ConstructionObject o=select(V,Control 
01526                             || !Global.getParameter("options.indicate",true));
01527                      if (o!=null) return (PointObject)o;
01528                      return null;
01529               }
01530               
01531               // User creates a new point:
01532               ConstructionObject oc=tryCreateIntersection(x,y,true);
01533               if (oc!=null) return (PointObject)oc;
01534               if (!IntersectionYes) return null;
01535               MyVector w=selectPointonObjects(x,y,true,false);
01536               filter(w,x,y,true);
01537               if (w.size()>0)
01538               {      oc=select(w,!Control); 
01539                      if (oc==null) return null;
01540                      if (oc!=null)
01541                      {      boolean yes=true;
01542                             if (Global.getParameter("options.pointon",false))
01543                             {      AgainQuestion q=new AgainQuestion(F,
01544                                           Zirkel.name("question.pointon"),
01545                                           Zirkel.name("question.title"));
01546                                    q.center(F);
01547                                    q.setVisible(true);
01548                                    yes=q.yes();
01549                                    Global.setParameter("options.pointon",q.again());
01550                             }
01551                             if (yes)
01552                             {      PointObject o=new PointObject(C,x(x),y(y),oc);
01553                                    if (ShowGrid  && Global.getParameter("grid.leftsnap",true)){o.snap(this);}
01554                                    o.setUseAlpha(true);
01555                                    addObject(o);
01556                                    validate();
01557                                    o.setDefaults();
01558                                    NewPoint=true;
01559                                    return o;
01560                             }
01561                             else return null;
01562                      }
01563               }
01564               PointObject p=new PointObject(C,x(x),y(y));
01565               if (ShowGrid && Global.getParameter("grid.leftsnap",true)){p.snap(this);}
01566               addObject(p);
01567               p.setDefaults();
01568               NewPoint=true;
01569               return p;
01570        }
01571        
01572        boolean IntersectionYes=false;
01573 
01574        public ConstructionObject tryCreateIntersection (int x, int y, boolean ask)
01575        {      MyVector w=selectPointonObjects(x,y,true,true);
01576               sort(w);
01577               IntersectionYes=true;
01578               if (w.size()<2) return null;
01579               ConstructionObject P1=(ConstructionObject)w.elementAt(0);
01580               ConstructionObject P2=(ConstructionObject)w.elementAt(1);
01581               if (!(P1 instanceof PointonObject && P2 instanceof PointonObject)) return null;
01582               if (!((PointonObject)P1).canInteresectWith(P2) 
01583                      || !((PointonObject)P2).canInteresectWith(P1)) return null;
01584               IntersectionObject o[]=IntersectionConstructor.construct(P1,P2,C);
01585               if (o.length==1 && !o[0].valid()) return null;
01586               if (o.length==2 && !o[0].valid() && !o[1].valid()) return null;
01587               if (ask && Global.getParameter("options.intersection",false))
01588               {      AgainQuestion q=new AgainQuestion(F,
01589                             Zirkel.name("question.intersection"),
01590                             Zirkel.name("question.title"));
01591                      q.center(F);
01592                      q.setVisible(true);
01593                      IntersectionYes=q.yes();
01594                      Global.setParameter("options.intersection",q.again());
01595               }
01596               if (IntersectionYes)
01597               {      if (o.length==1 || !o[1].valid())
01598                      {      addObject(o[0]);
01599                             o[0].autoAway();
01600                             o[0].validate(x(x),y(y));
01601                             validate();
01602                             o[0].setDefaults();
01603                             o[0].setRestricted(getRestricted());
01604                             return o[0];
01605                      }
01606                      if (!o[0].valid())
01607                      {      addObject(o[1]);
01608                             o[1].autoAway();
01609                             validate();
01610                             o[1].setDefaults();
01611                             o[1].setRestricted(getRestricted());
01612                             return o[1];
01613                      }                    
01614                      IntersectionObject oc=o[0];
01615                      double d0=o[0].distanceTo(x,y,this),
01616                             d1=o[1].distanceTo(x,y,this);
01617                      if (d1<d0) oc=o[1];
01618                      addObject(oc);
01619                      oc.autoAway();
01620                      oc.validate(x(x),y(y));
01621                      validate();
01622                      oc.setDefaults();
01623                      oc.setRestricted(getRestricted());
01624                      NewPoint=true;
01625                      return oc;
01626               }
01627               else return null;
01628        }
01629 
01630        public PointObject selectCreatePoint (int x, int y)
01631        {      return selectCreatePoint(x,y,true,false);
01632        }
01633 
01634        public PointObject selectCreatePoint (int x, int y, boolean multiple)
01635        {      return selectCreatePoint(x,y,multiple,false);
01636        }
01637 
01641        public ConstructionObject selectMoveablePoint (int x, int y)
01642        {      ConstructionObject s=findSelectedObject();
01643               if (s instanceof PointObject && 
01644                             ((MoveableObject)s).moveable() && s.nearto(x,y,this))
01645                      return s;
01646               V.removeAllElements();
01647               Enumeration e=C.elements();
01648               while (e.hasMoreElements())
01649               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01650                      if (o.isSelectable() && (o instanceof PointObject) &&
01651                             ((MoveableObject)o).moveable() &&
01652                             o.nearto(x,y,this))
01653                      {      V.addElement(o);
01654                      }
01655               }
01656               if (V.size()==1) return (ConstructionObject)V.elementAt(0);
01657               ConstructionObject o=select(V);
01658               if (o!=null) o.setSelected(true);
01659               return null;
01660        }
01661 
01665        public ConstructionObject selectWithSelector (int x, int y, 
01666               Selector sel, ConstructionObject until, boolean choice)
01667        {      V.removeAllElements();
01668               Enumeration e=C.elements();
01669               while (e.hasMoreElements())
01670               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01671                      if (o==until) break;
01672                      if (o.isSelectable() && sel.isAdmissible(this,o) &&
01673                             o.nearto(x,y,this))
01674                      {      V.addElement(o);
01675                      }
01676               }
01677               if (V.size()==1) return (ConstructionObject)V.elementAt(0);
01678               if (!choice)
01679               {      if (V.size()>0) return (ConstructionObject)V.elementAt(0);
01680                      else return null;
01681               }
01682               ConstructionObject o=select(V,x,y);
01683               return o;
01684        }
01685        public ConstructionObject selectWithSelector (int x, int y, 
01686               Selector sel, ConstructionObject until)
01687        {      return selectWithSelector(x,y,sel,until,true);
01688        }
01689        public ConstructionObject selectWithSelector (int x, int y, 
01690               Selector sel, boolean choice)
01691        {      return selectWithSelector(x,y,sel,null,choice);
01692        }
01693        public ConstructionObject selectWithSelector (int x, int y, Selector sel)
01694        {      return selectWithSelector(x,y,sel,null,true);
01695        }
01696 
01697 
01701        public ConstructionObject selectImmediateMoveablePoint (int x, int y)
01702        {      Enumeration e=C.elements();
01703               V.removeAllElements();
01704               while (e.hasMoreElements())
01705               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01706                      if (o.isSelectable() &&
01707                             o instanceof PointObject && ((MoveableObject)o).moveable() &&
01708                             o.nearto(x,y,this))
01709                                    V.addElement(o);
01710               }
01711               if (V.size()==0) return null;
01712               return (ConstructionObject)V.elementAt(0);
01713        }
01714 
01718        public ConstructionObject selectMoveableObject (int x, int y)
01719        {      ConstructionObject s=findSelectedObject();
01720               if (s instanceof MoveableObject && 
01721                             ((MoveableObject)s).moveable() && s.nearto(x,y,this))
01722                      return s;
01723               selectMoveableObjects(x,y);
01724               if (V.size()==1) return (ConstructionObject)V.elementAt(0);
01725               ConstructionObject o=select(V);
01726               if (o!=null)
01727               {      if (!Global.getParameter("options.choice",true)) return o;
01728                      o.setSelected(true);
01729               }
01730               return null;
01731        }
01732        public void selectMoveableObjects (int x, int y, boolean control)
01733        {      V.removeAllElements();
01734               ConstructionObject s=findSelectedObject();
01735               if (s instanceof MoveableObject && 
01736                             ((MoveableObject)s).moveable() && s.nearto(x,y,this))
01737               {      V.addElement(s);
01738                      return;
01739               }
01740               else if (control && s instanceof FixedCircleObject && s.nearto(x,y,this) &&
01741                      ((FixedCircleObject)s).fixedByNumber())
01742               {      V.addElement(s);
01743                      return;
01744               }
01745               else if (control && s instanceof FixedAngleObject && s.nearto(x,y,this) &&
01746                      ((FixedAngleObject)s).fixedByNumber())
01747               {      V.addElement(s);
01748                      return;
01749               }
01750               Enumeration e=C.elements();
01751               while (e.hasMoreElements())
01752               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01753                      if (!control && o.isSelectable() && 
01754                             o instanceof MoveableObject && ((MoveableObject)o).moveable() &&
01755                             o.nearto(x,y,this))
01756                                    V.addElement(o);
01757                      else if (control && o instanceof FixedCircleObject && o.nearto(x,y,this) &&
01758                             ((FixedCircleObject)o).fixedByNumber())
01759                                    V.addElement(o);
01760                      else if (control && o instanceof FixedAngleObject && o.nearto(x,y,this) &&
01761                             ((FixedAngleObject)o).fixedByNumber())
01762                                    V.addElement(o);
01763               }
01764               filter(V,x,y);
01765        }
01766        public void selectMoveableObjects (int x, int y)
01767        {      selectMoveableObjects(x,y,false);
01768        }
01769 
01773        public ConstructionObject selectImmediateMoveableObject (int x, int y)
01774        {      Enumeration e=C.elements();
01775               V.removeAllElements();
01776               while (e.hasMoreElements())
01777               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01778                      if (o.isSelectable() &&
01779                             o instanceof MoveableObject && ((MoveableObject)o).moveable() &&
01780                             o.nearto(x,y,this))
01781                                    V.addElement(o);
01782               }
01783               filter(V,x,y);
01784               if (V.size()==0) return null;
01785               return (ConstructionObject)V.elementAt(0);
01786        }
01787 
01792        public void filter (MyVector v, int x, int y, boolean choice)
01793        {      boolean HasPoints=false,HasNotFilled=false;
01794               Enumeration e=v.elements();
01795               while (e.hasMoreElements())
01796               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01797                      if (o instanceof PointObject)
01798                      {      HasPoints=true;
01799                      }
01800                      if (!o.isFilledForSelect())
01801                      {      HasNotFilled=true;
01802                      }
01803               }
01804               if (HasPoints)
01805               {      e=v.elements();
01806                      while (e.hasMoreElements())
01807                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
01808                             if (!o.onlynearto(x,y,this)) v.removeElement(o);
01809                      }
01810               }
01811               else if (HasNotFilled)
01812               {      e=v.elements();
01813                      while (e.hasMoreElements())
01814                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
01815                             if (o.isFilledForSelect()) v.removeElement(o);
01816                      }
01817               }
01818               sort(v);
01819               if (!choice)
01820               {      v.truncate(1);
01821               }
01822        }
01823        public void filter (MyVector v, int x, int y)
01824        {      filter(v,x,y,Global.getParameter("options.choice",true) || Control);
01825        }
01826 
01832        public ConstructionObject select (MyVector v, int x, int y, boolean choice)
01833        {      if (v.size()==0) return null;
01834               if (v.size()==1) return (ConstructionObject)v.elementAt(0);
01835               filter(v,x,y);
01836               if (v.size()==1) return (ConstructionObject)v.elementAt(0);
01837               if (!choice) return (ConstructionObject)v.elementAt(0);
01838               sortRow(V);
01839               RightClicked=false;
01840               SelectDialog d=new SelectDialog(F,v);
01841               if (d.isAborted()) return null;
01842               return d.getObject();
01843        }
01844        public ConstructionObject select (MyVector v, int x, int y)
01845        {      return select(v,x,y,Global.getParameter("options.choice",true) || Control);
01846        }
01847 
01852        public ConstructionObject select (MyVector v, boolean choice)
01853        {      if (v.size()==0) return null;
01854               if (v.size()==1) return (ConstructionObject)v.elementAt(0);
01855               if (!choice) return (ConstructionObject)v.elementAt(0);
01856               sortRow(V);
01857               RightClicked=false;
01858               SelectDialog d=new SelectDialog(F,v);
01859               if (d.isAborted()) return null;
01860               return d.getObject();
01861        }
01862        public ConstructionObject select (MyVector v)
01863        {      return select(v,Global.getParameter("options.choice",true) || Control);
01864        }
01865 
01871        public ConstructionObject selectLabel (int x, int y)
01872        {      Enumeration e=C.elements();
01873               while (e.hasMoreElements())
01874               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01875                      if (o.isSelectable() && o.textcontains(x,y,this)) return o;
01876               }
01877               return null;
01878        }
01879 
01880        public ConstructionObject findSelectedObject ()
01881        {      Enumeration e=C.elements();
01882               while (e.hasMoreElements())
01883               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01884                      if (o.selected()) return o;
01885               }
01886               return null;
01887        }
01888        
01889        // Indication functions
01890 
01891        MyVector Indicated=new MyVector();
01892        PointObject IndicatePoint=null;
01893        
01894        public void indicate (MyVector v, boolean showname)
01895        {      if (v.size()==1)
01896               {      if (showname)
01897                             setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
01898                      else if (v.elementAt(0) instanceof PointObject)
01899                             setCursor(new Cursor(Cursor.HAND_CURSOR));                            
01900               }
01901               else
01902                      setCursor(Cursor.getDefaultCursor());
01903               if (Indicated.equalsIdentical(v)) return;
01904               Enumeration e=Indicated.elements();
01905               while (e.hasMoreElements())
01906                      ((ConstructionObject)e.nextElement()).setIndicated(false);
01907               Indicated.removeAllElements();
01908               e=v.elements();
01909               while (e.hasMoreElements())
01910               {      ConstructionObject o=(ConstructionObject)e.nextElement();
01911                      Indicated.addElement(o);
01912                      o.setIndicated(true,showname);
01913               }
01914               repaint();
01915        }
01916        
01917        public void indicate (MyVector v)
01918        {      indicate(v,false);
01919        }
01920        
01921        public void clearIndicated ()
01922        {      IndicatePoint=null;
01923               if (Indicated.size()==0) return;
01924               Enumeration e=Indicated.elements();
01925               while (e.hasMoreElements())
01926                      ((ConstructionObject)e.nextElement()).setIndicated(false);
01927               Indicated.removeAllElements();
01928               setCursor(Cursor.getDefaultCursor());
01929               repaint();
01930        }
01931 
01932        boolean Preview=false;
01933        ConstructionObject LastNonPreview=null;
01934        MoveableObject PreviewObject=null;
01935        
01936        public void movePreview (MouseEvent e)
01937        {      if (PreviewObject!=null)
01938               {      PreviewObject.move(x(e.getX()),y(e.getY()));
01939                      validate();
01940                      repaint();
01941               }
01942        }
01943 
01944        public void prepareForPreview (MouseEvent e)
01945        {      LastNonPreview=C.last();
01946               Preview=true;
01947        }
01948        
01949        public boolean isPreview ()
01950        {      return Preview;
01951        }
01952        
01953        public void clearPreview ()
01954        {      if (!Preview) return;
01955               C.clearAfter(LastNonPreview);
01956               LastNonPreview=null;
01957               PreviewObject=null;
01958               Preview=false;
01959               Count.fixAll(false);
01960        }
01961 
01962        public void setPreviewObject (MoveableObject o)
01963        {      PreviewObject=o;
01964        }
01965 
01966        public ConstructionObject indicateTryCreateIntersection (int x, int y, boolean ask)
01967        {      MyVector w=selectPointonObjects(x,y,true,true);
01968               sort(w);
01969               IntersectionYes=true;
01970               if (w.size()<2) return null;
01971               IntersectionObject o[]=IntersectionConstructor.construct(
01972                      (ConstructionObject)w.elementAt(0),
01973                      (ConstructionObject)w.elementAt(1),C);
01974               if (o.length==1 && !o[0].valid()) return null;
01975               if (o.length==2)
01976               {      if (!o[1].valid())
01977                      {      if (!o[0].valid()) return null;
01978                      }
01979                      else
01980                      {      IntersectionObject h=o[0];
01981                             o[0]=o[1]; o[1]=h;
01982                      }
01983               }
01984               IntersectionObject oc=o[0];
01985               if (o.length==2 && o[1].valid())
01986               {      double d0=o[0].distanceTo(x,y,this),
01987                             d1=o[1].distanceTo(x,y,this);
01988                      if (d1<d0) oc=o[1];
01989               }
01990               oc.setDefaults();
01991               oc.setIndicated(true);
01992               oc.setType(PointObject.CIRCLE);
01993               oc.setColorType(ConstructionObject.THICK);
01994               IndicatePoint=oc;
01995               indicate(w);
01996               oc.validate(x(x),y(y));
01997               return oc;
01998        }
01999 
02000        public void indicateCreatePoint (int x, int y, boolean multiple)
02001        {      Enumeration e=C.elements();
02002               V.removeAllElements();
02003               while (e.hasMoreElements())
02004               {      ConstructionObject o=(ConstructionObject)e.nextElement();
02005                      if (o.isSelectable() && o instanceof PointObject && o.nearto(x,y,this)
02006                             && (multiple || !o.selected()))
02007                      {      V.addElement(o);
02008                      }
02009                      sort(V);
02010               }
02011               if (V.size()>0)
02012               {      IndicatePoint=null;
02013                      filter(V,x,y,false);
02014                      indicate(V);
02015                      return;
02016               }
02017               PointObject oc=(PointObject)indicateTryCreateIntersection(x,y,true);
02018               if (oc!=null) return;
02019               MyVector w=selectPointonObjects(x,y,true,false);
02020               filter(w,x,y,true);
02021               if (w.size()>=1)
02022               {      if (!w.equalsIdentical(Indicated))
02023                      {      oc=new PointObject(C,x(x),y(y),
02024                                    (ConstructionObject)w.elementAt(0));
02025                             if (ShowGrid && !Global.getParameter("grid.leftsnap",false)) 
02026                                    oc.snap(this);
02027                             oc.setUseAlpha(true);
02028                             oc.validate();
02029                             oc.setIndicated(true);
02030                             oc.setType(PointObject.CIRCLE);
02031                             oc.setColorType(ConstructionObject.THICK);
02032                             IndicatePoint=oc;
02033                             indicate(w);
02034                      }
02035                      else if (IndicatePoint!=null)
02036                      {      IndicatePoint.setType(PointObject.CIRCLE);
02037                             IndicatePoint.setColorType(ConstructionObject.THICK);
02038                             IndicatePoint.move(x(x),y(y));
02039                             IndicatePoint.project((ConstructionObject)w.elementAt(0));
02040                             repaint();
02041                      }
02042               }
02043               else
02044               {      clearIndicated();
02045               }
02046        }
02047 
02048        public void indicateCircleLineObjects (int x, int y)
02049        {      MyVector w=selectCircleLineObjects(x,y);
02050               filter(V,x,y);
02051               indicate(w);
02052        }
02053 
02054        public void indicatePointonObjects (int x, int y)
02055        {      MyVector w=selectPointonObjects(x,y);
02056               filter(V,x,y);
02057               indicate(w);
02058        }
02059 
02060        public void indicateIntersectedObjects (int x, int y)
02061        {      MyVector w=selectPointonObjects(x,y);
02062               if (!w.equalsIdentical(Indicated) && w.size()>=2)
02063               {      IntersectionObject o[]=IntersectionConstructor.construct(
02064                             (ConstructionObject)w.elementAt(0),
02065                             (ConstructionObject)w.elementAt(1),C);
02066                      IntersectionObject oc=o[0];
02067                      if (o.length==2)
02068                      {      double d0=o[0].distanceTo(x,y,this),
02069                                    d1=o[1].distanceTo(x,y,this);
02070                             if (d1<d0) oc=o[1];
02071                             oc.autoAway();
02072                      }
02073                      oc.validate();
02074                      oc.setDefaults();
02075                      oc.setIndicated(true);
02076                      oc.setColorType(ConstructionObject.THICK);
02077                      oc.setType(PointObject.CIRCLE);
02078                      IndicatePoint=oc;
02079               }
02080               else
02081               {      IndicatePoint=null;
02082               }
02083               indicate(w);
02084        }
02085 
02086        public void indicateLineObjects (int x, int y)
02087        {      selectLineObjects(x,y,true);
02088               filter(V,x,y);
02089               indicate(V);
02090        }
02091        
02092        public void indicatePointObjects (int x, int y)
02093        {      selectPointObjects(x,y,true);
02094               filter(V,x,y);
02095               indicate(V);
02096        }
02097 
02098        public void indicatePointObjects (int x, int y, ConstructionObject until)
02099        {      selectPointObjects(x,y,true,until);
02100               filter(V,x,y);
02101               indicate(V);
02102        }
02103 
02104        public void indicatePointsOrLines (int x, int y)
02105        {      selectPointsOrLines(x,y,true);
02106               filter(V,x,y);
02107               indicate(V);
02108        }
02109        
02110        public void indicateSegments (int x, int y)
02111        {      selectSegments(x,y,true);
02112               filter(V,x,y);
02113               indicate(V);
02114        }
02115 
02116        public void indicateRays (int x, int y)
02117        {      selectRays(x,y,true);
02118               filter(V,x,y);
02119               indicate(V);
02120        }
02121 
02122        public void indicateTwoPointLines (int x, int y)
02123        {      selectTwoPointLines(x,y,true);
02124               filter(V,x,y);
02125               indicate(V);
02126        }
02127 
02128        public void indicateCircles (int x, int y)
02129        {      selectCircles(x,y,true);
02130               filter(V,x,y);
02131               indicate(V);
02132        }
02133 
02134        public void indicateMoveableObjects (int x, int y, boolean control)
02135        {      selectMoveableObjects(x,y,control);
02136               filter(V,x,y);
02137               indicate(V);
02138        }
02139        public void indicateMoveableObjects (int x, int y)
02140        {      indicateMoveableObjects(x,y,false);
02141        }
02142        
02143        public void indicateWithSelector (int x, int y, Selector sel)
02144        {      selectWithSelector(x,y,sel,false);
02145               filter(V,x,y);
02146               indicate(V);
02147        }
02148 
02149        public void indicateWithSelector (int x, int y, 
02150               Selector sel, ConstructionObject until)
02151        {      selectWithSelector(x,y,sel,until,false);
02152               filter(V,x,y);
02153               indicate(V);
02154        }
02155 
02156        public void indicateConstructableObjects (int x, int y)
02157        {      selectConstructableObjects(x,y);
02158               filter(V,x,y);
02159               indicate(V);
02160        }
02161 
02162        public void indicateObjects (int x, int y, boolean showname)
02163        {      selectObjects(x,y);
02164               filter(V,x,y);
02165               indicate(V,showname);
02166        }
02167 
02168        public void indicateObjects (int x, int y)
02169        {      indicateObjects(x,y,false);
02170        }
02171        
02172        public void setTool (ObjectConstructor oc)
02173        {      if (OC!=null) OC.invalidate(this);
02174               OC=oc;
02175               OC.showStatus(this);
02176               clearIndicated();
02177               clearPreview();
02178        }
02179        
02180        public void setSuddenTool (ObjectConstructor oc)
02181        // called from ZirkelFrame
02182        {      OC=oc;
02183        }
02184 
02185        public void reset ()
02186        {      clearPreview();
02187               clearIndicated();
02188               OC.reset(this);
02189        }
02190        
02191        public void clearSelected ()
02192        // called from ObjectConstructor
02193        {      Enumeration e=C.elements();
02194               while (e.hasMoreElements())
02195               {      ConstructionObject o=(ConstructionObject)e.nextElement();
02196                      o.setSelected(false);
02197               }
02198               repaint();
02199        }
02200 
02201        public synchronized void clear ()
02202        // delete complete construction
02203        {      displayJob(false);
02204               if (OC!=null) OC.invalidate(this);
02205               C.clear(); recompute();
02206               setDefaultColor(0);
02207               setDefaultColorType(0);
02208               setDefaultType(2);
02209               setGrid();
02210               reloadCD();
02211        }
02212 
02217        public synchronized void back ()
02218        {      reset();
02219               ConstructionObject O=C.lastByNumber();
02220               if (O==null) return;
02221               if (O.isKeep()) return;
02222               delete(O);
02223               while (true)
02224               {      O=C.lastByNumber();
02225                      if (O==null) break;
02226                      else if (!O.mustHide(this) || O.isHideBreak() || O.isKeep()) break;
02227                      delete(O);
02228               }
02229               validate();
02230        }
02231        
02232        public synchronized void undo ()
02233        {      reset();
02234               C.undo();
02235        }
02236        
02237        public void delete (ConstructionObject o)
02238        {      if (C.last()==null) return;
02239               if (o.isKeep()) return;
02240               C.clearConstructables();
02241               o.setFlag(true);
02242               C.determineChildren();
02243               C.delete(false);
02244        }
02245        
02250        public void delete (Vector v)
02251        {      if (C.last()==null) return;
02252               C.clearConstructables();
02253               Enumeration e=v.elements();
02254               while (e.hasMoreElements())
02255               {      ConstructionObject o=(ConstructionObject)e.nextElement();
02256                      if (o.isKeep()) return;
02257                      o.setFlag(true);
02258               }
02259               C.determineChildren();
02260               C.delete(false);
02261        }
02262        
02263        public boolean depends (ConstructionObject o, ConstructionObject on)
02264        {      C.clearConstructables();
02265               on.setFlag(true);
02266               C.determineChildren();
02267               return o.isFlag();
02268        }
02269 
02270        public void addStatusListener (StatusListener sl)
02271        {      SL=sl;
02272        }
02273 
02274        public void showStatus (String s)
02275        {      if (SL!=null) SL.showStatus(s);
02276        }
02277 
02278        public void showStatus ()
02279        {      if (OC!=null) OC.showStatus(this);
02280        }
02281 
02282        public boolean showHidden ()
02283        {      return ShowHidden;
02284        }
02285 
02286        public void setDefaultColor (int c)
02287        {      C.DefaultColor=c;
02288        }
02289        public int getDefaultColor ()
02290        {      return C.DefaultColor;
02291        }
02292 
02293        public void setDefaultType (int c)
02294        {      C.DefaultType=c;
02295        }
02296        public int getDefaultType ()
02297        {      return C.DefaultType;
02298        }
02299        public void setPartial (boolean flag)
02300        {      C.Partial=flag;
02301        }
02302        public boolean getPartial ()
02303        {      return C.Partial;
02304        }
02305        public void setRestricted (boolean flag)
02306        {      C.Restricted=flag;
02307        }
02308        public boolean getRestricted ()
02309        {      return C.Restricted;
02310        }
02311        public void setPartialLines (boolean flag)
02312        {      C.PartialLines=flag;
02313        }
02314        public boolean getPartialLines ()
02315        {      return C.PartialLines;
02316        }
02317        public void setVectors (boolean flag)
02318        {      C.Vectors=flag;
02319        }
02320        public boolean getVectors ()
02321        {      return C.Vectors;
02322        }
02323 
02324        public void setLongNames (boolean flag)
02325        {      C.LongNames=flag;
02326        }
02327        public boolean getLongNames ()
02328        {      return C.LongNames;
02329        }
02330 
02331        public void setLargeFont (boolean flag)
02332        {      C.LargeFont=flag;
02333        }
02334        public boolean getLargeFont ()
02335        {      return C.LargeFont;
02336        }
02337 
02338        public void setBoldFont (boolean flag)
02339        {      C.BoldFont=flag;
02340        }
02341        public boolean getBoldFont ()
02342        {      return C.BoldFont;
02343        }
02344 
02345        public void setObtuse (boolean flag)
02346        {      C.Obtuse=flag;
02347        }
02348        public boolean getObtuse ()
02349        {      return C.Obtuse;
02350        }
02351 
02352        public void setSolid (boolean flag)
02353        {      C.Solid=flag;
02354        }
02355        public boolean getSolid ()
02356        {      return C.Solid;
02357        }
02358 
02359        public void setShowNames (boolean flag)
02360        {      C.ShowNames=flag;
02361        }
02362        public boolean getShowNames ()
02363        {      return C.ShowNames;
02364        }
02365 
02366        public void setShowValues (boolean flag)
02367        {      C.ShowValues=flag;
02368        }
02369        public boolean getShowValues ()
02370        {      return C.ShowValues;
02371        }
02372 
02373        public void setDefaultColorType (int c)
02374        {      C.DefaultColorType=c;
02375        }
02376        public int getDefaultColorType ()
02377        {      return C.DefaultColorType;
02378        }
02379 
02380        public void setShowHidden (boolean flag)
02381        {      ShowHidden=flag; repaint();
02382        }
02383        public boolean getShowHidden ()
02384        {      return ShowHidden;
02385        }
02386 
02387        public void setHidden (boolean flag)
02388        {      C.Hidden=flag;
02389        }
02390 
02396        public boolean hides (ConstructionObject o)
02397        {      if (OC instanceof SetTargetsTool) return !o.isFlag();
02398               else return false;
02399        }
02405        public void save (OutputStream o, boolean construction, boolean macros, boolean protectedmacros, Vector Macros, String Restrict)
02406               throws IOException
02407        {      boolean utf=Global.getParameter("options.utf",true);
02408               XmlWriter xml;
02409               if (utf)
02410               {      xml=new XmlWriter(new PrintWriter(
02411                             new OutputStreamWriter(o,"UTF8"),true));
02412                      xml.printEncoding(utf?"utf-8":"iso-8859-1");
02413               }
02414               else
02415               {      xml=new XmlWriter(new PrintWriter(
02416                             new OutputStreamWriter(o),true));
02417                      xml.printXml();
02418               }
02419               //xml.printXls("zirkel.xsl");
02420               //xml.printDoctype("CaR","zirkel.dtd");
02421               xml.startTagNewLine("CaR");
02422               if (macros)
02423               {      Sorter.sort(Macros);
02424                      Enumeration e=Macros.elements();
02425                      while (e.hasMoreElements())
02426                      {      Macro m=((MacroItem)e.nextElement()).M;
02427                             if (protectedmacros || !m.isProtected())
02428                                    m.saveMacro(xml);
02429                      }
02430               }
02431               if (construction)
02432               {      xml.startTagStart("Construction");
02433                      if (isJob())
02434                      {      xml.printArg("job","true");
02435                             xml.printArg("last",Last);
02436                             int i=1;
02437                             Enumeration e=Targets.elements();
02438                             while (e.hasMoreElements())
02439                             {      xml.printArg("target"+i,(String)e.nextElement());
02440                                    i++;
02441                             }
02442                      }
02443                      xml.startTagEndNewLine();
02444                      xml.startTagStart("Window");
02445                      xml.printArg("x",""+C.getX());
02446                      xml.printArg("y",""+C.getY());
02447                      xml.printArg("w",""+C.getW());
02448                      if (ShowGrid) xml.printArg("showgrid","true");
02449                      xml.finishTagNewLine();
02450                      if (ShowGrid)
02451                      {      xml.startTagStart("Grid");
02452                             if (AxesOnly) xml.printArg("axesonly","true");
02453                             xml.printArg("color",""+GridColor);
02454                             xml.printArg("thickness",""+GridThickness);
02455                             if (!GridLabels) xml.printArg("nolabels","true");
02456                             else
02457                             {      if (GridLarge) xml.printArg("large","true");
02458                                    if (GridBold) xml.printArg("bold","true");
02459                             }
02460                             xml.finishTagNewLine();
02461                      }
02462                      if (getConstruction().BackgroundFile!=null &&
02463                                    !getConstruction().BackgroundFile.equals(""))
02464                      {      xml.startTagStart("Background");
02465                             xml.printArg("file",getConstruction().BackgroundFile);
02466                             if (getConstruction().ResizeBackground)
02467                                    xml.printArg("resize","true");
02468                             xml.finishTagNewLine();
02469                      }
02470                      if (!C.getComment().equals(""))
02471                      {      xml.startTagNewLine("Comment");
02472                             xml.printParagraphs(C.getComment(),60);
02473                             xml.endTagNewLine("Comment");
02474                      }
02475                      if (!C.getJobComment().equals(""))
02476                      {      xml.startTagNewLine("Assignment");
02477                             xml.printParagraphs(C.getJobComment(),60);
02478                             xml.endTagNewLine("Assignment");
02479                      }
02480                      if (!Restrict.equals(""))
02481                      {      xml.finishTag("Restrict","icons",Restrict);
02482                      }
02483                      if (OC instanceof ObjectTracker)
02484                      {      ((ObjectTracker)OC).save(xml);
02485                      }
02486                      else if (OC instanceof Tracker)
02487                      {      ((Tracker)OC).save(xml);
02488                      }
02489                      else if (OC instanceof AnimatorTool)
02490                      {      ((AnimatorTool)OC).save(xml);
02491                      }
02492                      else if (OC instanceof BreakpointAnimator)
02493                      {      ((BreakpointAnimator)OC).save(xml);
02494                      }
02495                      saveDrawings(xml);
02496                      xml.startTagNewLine("Objects");
02497                      C.save(xml);
02498                      xml.endTagNewLine("Objects");
02499                      xml.endTagNewLine("Construction");
02500               }
02501               xml.endTagNewLine("CaR");
02502        }
02503 
02504        public void load (InputStream in, boolean construction, boolean macros)
02505               throws Exception
02506        {      // System.out.println("read file");
02507               try
02508               {      if (construction)
02509                      {      C.clear(); All=false;
02510                             paint(getGraphics());
02511                      }
02512                      else All=true;
02513                      XmlReader xml=new XmlReader();
02514                      xml.init(in);
02515                      XmlTree tree=xml.scan();
02516                      if (tree==null)
02517                             throw new ConstructionException("XML file not recognized");
02518                      Enumeration e=tree.getContent();
02519                      while (e.hasMoreElements())
02520                      {      tree=(XmlTree)e.nextElement();
02521                             if (tree.getTag() instanceof XmlTagPI) continue;
02522                             if (!tree.getTag().name().equals("CaR"))
02523                                    throw new ConstructionException("CaR tag not found");
02524                             else break;
02525                      }
02526                      e=tree.getContent();
02527                      boolean all=false;
02528                      while (e.hasMoreElements())
02529                      {      tree=(XmlTree)e.nextElement();
02530                             XmlTag tag=tree.getTag();
02531                             if (tag.name().equals("Macro"))
02532                             {      if (macros)
02533                                    {      try
02534                                           {      Count.setAllAlternate(true);
02535                                                  Macro m=new Macro(this,tree);
02536                                                  int i=0;
02537                                                  for (i=0; i<Macros.size(); i++)
02538                                                  {      if (((MacroItem)Macros.elementAt(i)).M.getName()
02539                                                                .equals(m.getName()))
02540                                                         {      all=replaceMacro(m,i,all);
02541                                                                break;
02542                                                         }
02543                                                  }
02544                                                  if (i>=Macros.size()) appendMacro(m);
02545                                           }
02546                                           catch (ConstructionException ex)
02547                                           {      Count.setAllAlternate(false);
02548                                                  throw ex;     
02549                                           }
02550                                           Count.setAllAlternate(false);
02551                                    }
02552                             }
02553                             else if (tag.name().equals("Construction"))
02554                             {      if (construction)
02555                                    {      boolean job=false;
02556                                           if (tag.hasParam("job"))
02557                                           {      job=true;
02558                                                  Last=tag.getValue("last");
02559                                                  if (Last==null)
02560                                                         throw new ConstructionException(
02561                                                                Zirkel.name("exception.job"));
02562                                                  String Target=tag.getValue("target");
02563                                                  if (Target==null)
02564                                                  {      Targets=new Vector();
02565                                                         int i=1;
02566                                                         while (true)
02567                                                         {      String s=tag.getValue("target"+i);
02568                                                                i++;
02569                                                                if (s==null) break;
02570                                                                Targets.addElement(s);
02571                                                         }
02572                                                  }
02573                                                  else
02574                                                  {      Targets=new Vector();
02575                                                         Targets.addElement(Target);
02576                                                  }
02577                                                  if (Targets.size()==0)
02578                                                         throw new ConstructionException(
02579                                                                Zirkel.name("exception.job"));
02580                                           }
02581                                           C.load(tree,this);
02582                                           if (job)
02583                                           {      if (C.find(Last)==null)
02584                                                         throw new ConstructionException(
02585                                                                Zirkel.name("exception.job"));
02586                                                  Enumeration et=Targets.elements();
02587                                                  while (et.hasMoreElements())
02588                                                  {      String s=(String)et.nextElement();
02589                                                         if (C.find(s)==null
02590                                                                && 
02591                                                                (!s.startsWith("~") ||
02592                                                                C.find(s.substring(1))==null))
02593                                                                throw new ConstructionException(
02594                                                                       Zirkel.name("exception.job"));                                 
02595                                                  }
02596                                                  Job=true;
02597                                           }
02598                                           break;
02599                                    }
02600                             }                    
02601                             else
02602                                    throw new ConstructionException(
02603                                           "Construction not found");
02604                      }
02605                      recompute();
02606                      C.translateOffsets(this);
02607                      resetSum();
02608                      validate();
02609                      repaint();
02610               }
02611               catch (Exception e)
02612               {      throw e;
02613               }
02614               reloadCD();
02615               repaint();
02616               // System.out.println("finished reading file");
02617        }
02618        
02619        public void resetSum ()
02620        {      Enumeration e=C.elements();
02621               while (e.hasMoreElements())
02622               {      ConstructionObject o=(ConstructionObject)e.nextElement();
02623                      if (o instanceof ExpressionObject)
02624                             ((ExpressionObject)o).reset();
02625               }
02626        }
02627        
02628        public void warning (String s, String help)
02629        {      Warning w=new Warning(F,s,
02630                             Zirkel.name("warning"),true,help);
02631               w.center(F);
02632               w.setVisible(true);
02633        }
02634        
02635        public void warning (String s)
02636        {      warning(s,"");
02637        }
02638        
02639        public void load (InputStream in)
02640               throws Exception
02641        {      try
02642               {      C.Loading=true;
02643                      load(in,true,true);
02644                      C.Loading=false;
02645               }
02646               catch (Exception e)
02647               {      C.Loading=false;
02648                      throw e;
02649               }
02650        }
02651 
02652        public String getComment ()
02653        {      return C.getComment();
02654        }
02655        public void setComment (String s)
02656        {      C.setComment(s);
02657        }
02658 
02659        public String getJobComment ()
02660        {      return C.getJobComment();
02661        }
02662        public void setJobComment (String s)
02663        {      C.setJobComment(s);
02664        }
02665 
02670        public void setFrame (Frame f)
02671        {      F=f;
02672        }
02673        public Frame getFrame ()
02674        {      return F;
02675        }
02676 
02680        public void magnify (double f)
02681        {      C.setXYW(C.getX(),C.getY(),C.getW()*f);
02682               recompute(); validate(); repaint();
02683        }
02684 
02688        public void shift (double dx, double dy)
02689        {      C.setXYW(C.getX()+dx*C.getW(),C.getY()+dy*C.getW(),C.getW());
02690               recompute(); validate(); repaint();
02691        }
02692 
02697        public void paintTrack (MyGraphics g)
02698        {      if (!(OC instanceof TrackPainter)) return;
02699               ((TrackPainter)OC).paint(g,this);
02700        }
02701 
02707        public void updateTexts (ConstructionObject o, String oldname)
02708        {      C.updateTexts(o,oldname);
02709        }
02710 
02711        public Construction getConstruction ()
02712        {      return C;
02713        }
02714        
02715        public void setShowGrid (boolean flag)
02716        {      ShowGrid=flag;
02717               repaint(); 
02718        }
02719        public void toggleShowGrid ()
02720        {      if (ShowGrid && !AxesOnly)
02721               {      AxesOnly=true;
02722               }
02723               else if (ShowGrid)
02724               {      ShowGrid=false;
02725               }
02726               else
02727               {      AxesOnly=false;
02728                      ShowGrid=true;
02729               }
02730               Global.setParameter("showgrid",ShowGrid);
02731               Global.setParameter("axesonly",AxesOnly);
02732               repaint(); 
02733        }
02734        public boolean showGrid () { return ShowGrid; }
02735 
02740        public void setJob (ConstructionObject last)
02741        {      Job=true;
02742               Last=last.getName(); Targets=new Vector();
02743        }
02744        public void addJobTarget (ConstructionObject target, boolean visible)
02745        {      if (visible) Targets.addElement("~"+target.getName());
02746               else Targets.addElement(target.getName());
02747        }
02748        public void clearTargets ()
02749        {      Targets=new Vector();
02750        }
02754        public void clearJob ()
02755        {      Job=false;
02756        }
02760        public boolean isJob ()
02761        {      Enumeration e=Targets.elements();
02762               while (e.hasMoreElements())
02763               {      String s=(String)e.nextElement();
02764                      if (C.find(s)==null &&
02765                             (!s.startsWith("~") || C.find(s.substring(1))==null)) return false;
02766               }
02767               return Job && C.find(Last)!=null && Targets.size()>0;
02768        }
02769        
02770        public boolean inTargets (String s)
02771        {      Enumeration e=Targets.elements();
02772               while (e.hasMoreElements())
02773               {      if (((String)e.nextElement()).equals(s))
02774                             return true;
02775               }
02776               return false;
02777        }
02778        
02789        public void displayJob (boolean flag)
02790        {      clearSelected();
02791               if (!(OC instanceof SaveJob)) OC.reset(this);
02792               if (flag) // diplay the job
02793               {      C.setOriginalOrder(true);
02794                      if (displayJob() || !isJob()) return;
02795                      Construction Cnew=new Construction();
02796                      Cnew.setXYW(C.getX(),C.getY(),C.getW());
02797                      Enumeration e=C.elements();
02798                      while (e.hasMoreElements())
02799                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
02800                             o.setJobTarget(true);
02801                             o.setJobTarget(false);
02802                      }
02803                      e=C.elements();
02804                      while (e.hasMoreElements())
02805                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
02806                             Cnew.add(o); o.setKeep(true);
02807                             if (inTargets(o.getName()) || inTargets("~"+o.getName())) 
02808                                    o.setJobTarget(true);
02809                             if (o.getName().equals(Last)) break;
02810                      }
02811                      while (e.hasMoreElements())
02812                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
02813                             if (inTargets(o.getName()) || inTargets("~"+o.getName()))
02814                             {      Cnew.add(o); o.setKeep(true);
02815                                    o.setJobTarget(true);
02816                             }
02817                      }
02818                      int n=0;
02819                      e=Targets.elements();
02820                      while (e.hasMoreElements())
02821                      {      String s=(String)e.nextElement();
02822                             if (!s.startsWith("~")) n++;
02823                      }
02824                      TargetO=new ConstructionObject[n];
02825                      TargetS=new ConstructionObject[n];
02826                      n=0;
02827                      e=Targets.elements();
02828                      while (e.hasMoreElements())
02829                      {      String s=(String)e.nextElement();
02830                             if (!s.startsWith("~"))
02831                             {      TargetO[n]=Cnew.find(s);
02832                                    TargetS[n]=null;
02833                                    n++;
02834                             }
02835                      }
02836                      COriginal=C;
02837                      C=Cnew;
02838                      C.addAddEventListener(this);
02839                      C.setComment(COriginal.getJobComment());
02840                      recompute();
02841                      reloadCD();
02842                      repaint();
02843               }
02844               else // display the orginal construction again
02845               {      if (!displayJob()) return;
02846                      C.removeAddEventListener(this);
02847                      C=COriginal;
02848                      COriginal=null;
02849                      Enumeration e=C.elements();
02850                      while (e.hasMoreElements())
02851                      {      ConstructionObject o=
02852                                    (ConstructionObject)e.nextElement();
02853                             o.setKeep(false);
02854                             o.setJobTarget(false);
02855                      }
02856                      C.setOriginalOrder(false);
02857                      recompute();
02858                      reloadCD();
02859                      repaint();
02860               }
02861        }
02862        
02866        public void freeJob ()
02867        {      Enumeration e=C.elements();
02868               while (e.hasMoreElements())
02869               {      ConstructionObject o=(ConstructionObject)e.nextElement();
02870                      o.setKeep(false);
02871                      o.setJobTarget(false);
02872                      repaint();
02873               }
02874        }
02875 
02879        public boolean displayJob ()
02880        {      return COriginal!=null;
02881        }
02882        
02883        // The following functions change the default values of some objects.
02884        
02885        public void setShowColor (int i)
02886        {      ShowColor=i; 
02887               repaint();
02888        }
02889        public int getShowColor () { return ShowColor; }
02890 
02891        public ObjectConstructor getOC () { return OC; } 
02892        
02893        // Macros:
02894 
02895        Vector Macros=new Vector();
02896        
02897        public Vector getMacros ()
02898        {      return Macros;
02899        }
02900        
02901        public boolean haveMacros ()
02902        {      return Macros.size()>0;
02903        }
02904 
02905        public boolean haveNonprotectedMacros ()
02906        {      Enumeration e=Macros.elements();
02907               while (e.hasMoreElements())
02908               {      MacroItem m=(MacroItem)e.nextElement();
02909                      if (!m.M.isProtected()) return true;
02910               }
02911               return false;
02912        }
02913 
02921        boolean defineMacro ()
02922        {      clearSelected();
02923               // Read the list of Parameters and Targets from the
02924               // construction. This list is filled by the SetParameter and
02925               // SetTargets constructors.
02926               Vector P=C.getParameters();
02927               if (P.size()==0) // no parameters
02928               {      warning(Zirkel.name("definemacro.noparams"));
02929                      return false;
02930               }
02931               // Display the macro creation dialog to the user.
02932               DefineMacro d=new DefineMacro(F,this);
02933               d.center(getFrame());
02934               d.setVisible(true);
02935               // Aborted?
02936               if (d.isAborted() || d.getName().equals("")) return false;
02937               // Define a marco with the name, the comment and the paramters.
02938               Macro m=new Macro(this,d.getName(),d.getComment(),d.getParams());
02939               // If there are no targets, determine everything as
02940               // constructed by the paramaters, else only the things needed
02941               // to get the targets.
02942               try
02943               {      defineMacro(C,m,d.targetsOnly(),d.invisible(),d.getPromptFor(),
02944                             d.hideduplicates());
02945               }
02946               catch (ConstructionException e)
02947               {      warning(e.getDescription());
02948                      OC.reset(this);
02949                      return false;
02950               }
02951               storeMacro(m,false);
02952               OC.reset(this);
02953               return true;
02954        }
02955        
02956        
02960        public Macro copyMacro (Macro m, String name, boolean fixed[])
02961        {      try
02962               {      Macro macro=(Macro)(m.clone());
02963                      macro.Name=name;
02964                      boolean f[]=new boolean[fixed.length];
02965                      for (int i=0; i<f.length; i++) f[i]=fixed[i];
02966                      macro.Fixed=f;
02967                      storeMacro(macro,true);
02968                      return macro;
02969               }
02970               catch (Exception e) { return m; }
02971        }
02972 
02978        public void defineMacro (Construction c, Macro m, 
02979               boolean targetsonly, boolean superhide, String prompt[],
02980                             boolean hideduplicates)
02981                      throws ConstructionException
02982        {      Vector P=c.getParameters(),T=c.getTargets();
02983               c.setTranslation(m); // for construction expressions only (windoww etc.)
02984               c.clearTranslations();
02985               if (T.size()==0) // got no targets 
02986                      c.determineConstructables();
02987               else // got targets
02988               {      c.clearConstructables();
02989                      c.setParameterAsConstructables();
02990                      for (int i=0; i<T.size(); i++)
02991                      {      c.determineConstructables((ConstructionObject)T.elementAt(i));
02992                      }
02993               }
02994               // Make sure the counter for the macro object names starts
02995               // fresh (P1, P2, ...)
02996               Count.setAllAlternate(true);
02997               // Walk through the construction and copy all marked objects
02998               // to the macro definition.
02999               m.clearTranslators();
03000               Enumeration e=c.elements();
03001               while (e.hasMoreElements())
03002               {      ConstructionObject o=(ConstructionObject)e.nextElement();
03003                      if (o instanceof TwoPointLineObject && 
03004                             canConvert(c,(TwoPointLineObject)o) && o.isMainParameter())
03005                      {      ((TwoPointLineObject)o).getP1().setFlag(false);
03006                             ((TwoPointLineObject)o).getP2().setFlag(false);
03007                      }                                  
03008               }
03009               e=c.elements();
03010               while (e.hasMoreElements())
03011               {      ConstructionObject oc,o=(ConstructionObject)e.nextElement();
03012                      if (o.isFlag() &&
03013                             !(o.isParameter() && !o.isMainParameter() && !needed(c,o,null)))
03014                      {      // System.out.println(o.getName()+", parameter: "+o.isParameter()+
03015                             //     ", main: "+o.isMainParameter()+", needed "+needed(c,o,null));
03016                             // Now copy to the macro, but make sure that parameters
03017                             // are simplified to their object type. E.g., an
03018                             // objectpoint becomes a point, if it is a parameter.
03019                             if (o instanceof PointObject && o.isParameter())
03020                             {      PointObject p=(PointObject)o;
03021                                    if (p.isSpecialParameter() && p.dependsOnParametersOnly())
03022                                           oc=(ConstructionObject)p.copy();
03023                                    else
03024                                           oc=new PointObject(c,p.getX(),p.getY());
03025                             }
03026                             else if (o instanceof FunctionObject && o.isParameter())
03027                             {      FunctionObject fo=new FunctionObject(c);
03028                                    fo.setExpressions("x","0","0");
03029                                    fo.setRange("-10","10","0.1");
03030                                    oc=fo;
03031                             }
03032                             else if (o instanceof UserFunctionObject && o.isParameter())
03033                             {      UserFunctionObject fo=new UserFunctionObject(c);
03034                                    fo.setExpressions("x","0");
03035                                    oc=fo;
03036                             }
03037                             else if (o instanceof ExpressionObject && o.isParameter())
03038                             {      oc=new ExpressionObject(c,0,0);
03039                                    ((ExpressionObject)oc).setExpression(o.getValue()+"",
03040                                                  o.getConstruction());
03041                                    ((ExpressionObject)oc).setCurrentValue(o.getValue());
03042                             }
03043                             else if (o instanceof TwoPointLineObject && 
03044                                    canConvert(c,(TwoPointLineObject)o) && o.isParameter())
03045                             {      oc=new PrimitiveLineObject(c);
03046                             }                                  
03047                             else if (o instanceof PrimitiveLineObject && 
03048                                    !(o instanceof TwoPointLineObject) &&
03049                                    !(o instanceof FixedAngleObject) &&
03050                                    o.isParameter())
03051                             {      oc=new PrimitiveLineObject(c);
03052                             }
03053                             else if (o instanceof PrimitiveCircleObject && o.isParameter())
03054                             {      oc=new PrimitiveCircleObject(c,
03055                                           ((PrimitiveCircleObject)o).getP1());
03056                                    oc.translateConditionals();
03057                                    oc.translate();
03058                             }
03059                             else if (o instanceof AreaObject && o.isParameter())
03060                             {      oc=new AreaObject(c,new Vector());
03061                                    oc.translateConditionals();
03062                                    oc.translate();
03063                             }
03064                             else
03065                             {      oc=(ConstructionObject)o.copy();
03066                             }
03067                             if (oc!=null)
03068                             {      m.add(oc);
03069                                    if (o.isMainParameter()) oc.setName(o.getName());
03070                                    if (targetsonly && !o.isTarget() && !o.isParameter())
03071                                    {      if (superhide) oc.setSuperHidden(true);
03072                                           else oc.setHidden(true);
03073                                    }
03074                                    if (o.isParameter() && o.isHidden())
03075                                    {      oc.setHidden(true);
03076                                    }
03077                                    // All parameters in the constructions translate to
03078                                    // the paramters in the macro definition.
03079                                    o.setTranslation(oc);
03080                             }
03081                      }
03082                      else o.setTranslation(null);
03083               }
03084               e=c.elements();
03085               while (e.hasMoreElements())
03086               {      ConstructionObject o=(ConstructionObject)e.nextElement();
03087                      if (o.isFlag() && !o.isParameter())
03088                             o.laterTranslate(c);
03089               }
03090               Count.setAllAlternate(false);
03091               // translate the @... forward declarations in FindObjectExpression.
03092               c.clearErrors();
03093               m.runTranslators(c);
03094               // see if any errors occured (@.. to nonexisting object, generated
03095               // by the FindObjectExpression on translation.
03096               e=c.getErrors();
03097               if (e.hasMoreElements())
03098               {      warning((String)e.nextElement(),"macroerror");
03099               }
03100               // Now set the paramter array and make sure it is translated
03101               // to the objects in the macro definition.
03102               ConstructionObject Params[]=new ConstructionObject[P.size()];
03103               for (int i=0; i<P.size(); i++)
03104               {      Params[i]=((ConstructionObject)P.elementAt(i)).getTranslation();
03105               }
03106               m.setParams(Params);
03107               String p[]=new String[prompt.length];
03108               for (int j=0; j<prompt.length; j++)
03109               {      ConstructionObject o=c.find(prompt[j]);
03110                      if (o==null || o.getTranslation()==null ||
03111                             !(o instanceof FixedCircleObject || 
03112                                    o instanceof FixedAngleObject ||
03113                                    o instanceof ExpressionObject))
03114                             throw new ConstructionException(
03115                                    Zirkel.name("exception.prompt"));
03116                      for (int i=0; i<P.size(); i++)
03117                      {      ConstructionObject op=(ConstructionObject)P.elementAt(i);
03118                             if (op==o)
03119                                    throw new ConstructionException(
03120                                           Zirkel.name("exception.prompt.parameter"));
03121                      }
03122                      p[j]=o.getTranslation().getName();
03123               }
03124               m.setPromptFor(p);
03125               for (int i=0; i<prompt.length; i++)
03126                      m.setPromptName(i,prompt[i]);
03127               m.hideDuplicates(hideduplicates);
03128        }
03129 
03134        public boolean needed (Construction c, ConstructionObject o, 
03135                      ConstructionObject besides)
03136        {      Enumeration e=c.elements();
03137               while (e.hasMoreElements())
03138               {      ConstructionObject u=(ConstructionObject) e.nextElement();
03139                      if (!u.isFlag() || u==besides) continue;
03140                      if (c.dependsDirectlyOn(u,o)) return true;
03141               }
03142               return false;
03143        }
03144        
03148        public boolean canConvert (Construction c, TwoPointLineObject o)
03149        {      PointObject p1=o.getP1(),p2=o.getP2();
03150               if (p1.isMainParameter() || p2.isMainParameter()) return false;
03151               return !(needed(c,p1,o) || needed(c,p2,o));
03152        }
03153        
03158        public void defineMacro (String name, String comment, Construction c)
03159               throws ConstructionException
03160        {      Vector T=c.getTargets();
03161               String Prompts[]=new String[c.Prompts.size()];
03162               for (int i=0; i<Prompts.length; i++)
03163                      Prompts[i]=(String)c.Prompts.elementAt(i);
03164               Macro m=new Macro(this,name,comment,Prompts);
03165               defineMacro(c,m,T.size()>0 && !c.ShowAll,c.SuperHide,c.getPromptFor(),true);
03166               storeMacro(m,true);
03167        }
03168        
03169        /*
03170        Store the macro in the macro list (or replace the old macro
03171        with the same name
03172        @param all Replace the macro without asking.
03173        */
03174        public void storeMacro (Macro m, boolean all)
03175        {      int i=0;
03176               for (i=0; i<Macros.size(); i++)
03177               {      if (((MacroItem)Macros.elementAt(i)).M.getName().equals(m.getName()))
03178                      {      All=replaceMacro(m,i,all); // ask user if All=false
03179                             break;
03180                      }
03181               }
03182               if (i>=Macros.size()) appendMacro(m);
03183        }
03184 
03185        public boolean ProtectMacros=false;
03186 
03187        public MacroMenu MM=null;
03188        
03189        public void appendMacro (Macro m)  
03190        {      if (!ReadOnly)
03191               {      if (ProtectMacros) m.setProtected(true);
03192                      if (MM==null) MM=new MacroMenu(PM,"",null);
03193                      MacroItem mi=MM.add(m,m.getName());
03194                      mi.I.addActionListener(this);
03195                      Macros.addElement(mi);
03196               }
03197               else
03198               {      if (MM==null) MM=new MacroMenu(null,"",null);
03199                      MacroItem mi=MM.add(m,m.getName());
03200                      if (mi.I!=null) mi.I.addActionListener(this);
03201                      Macros.addElement(mi);
03202               }
03203        }
03204        
03209        public boolean replaceMacro (Macro m, int i, boolean all)
03210        {      MacroItem e=(MacroItem)Macros.elementAt(i);
03211               if (all) // don't ask
03212               {      Macros.setElementAt(new MacroItem(m,e.I),i);
03213                      return true;
03214               }
03215               else // ask
03216               {      ReplaceMacroQuestion d=new ReplaceMacroQuestion(getFrame(),m);
03217                      d.center(getFrame());
03218                      d.setVisible(true);
03219                      if (d.isNo()) return false;
03220                      MacroItem newitem=new MacroItem(m,e.I);
03221                      MM.replace((MacroItem)Macros.elementAt(i),newitem);
03222                      Macros.setElementAt(newitem,i);
03223                      return d.isAll();
03224               }
03225        }
03226 
03227        public String MacroCurrentComment;
03228        
03232        public Macro chooseMacro ()
03233        {      if (Macros.size()==0)
03234               {      warning(Zirkel.name("definemacro.nomacro"));
03235                      return null;
03236               }
03237               MacroSelectDialog d=new MacroSelectDialog(getFrame(),MM,false);
03238               d.setVisible(true);
03239               return d.getMacro();
03240        }
03241 
03246        public Vector chooseMacros ()
03247        {      if (Macros.size()==0)
03248               {      warning(Zirkel.name("definemacro.nomacro"));
03249                      return null;
03250               }
03251               MacroSelectDialog d=
03252                      new MacroSelectDialog(getFrame(),MM,true);
03253               d.setVisible(true);
03254               return d.getMacros();
03255        }
03256 
03260        public Macro chooseMacro (String name)
03261        {      Enumeration e=Macros.elements();
03262               while (e.hasMoreElements())
03263               {      Macro m=((MacroItem)e.nextElement()).M;
03264                      if (m.getName().equals(name))
03265                             return m;
03266               }
03267               return null;
03268        }
03269 
03270        public void deleteMacros (Vector v)
03271        {      Enumeration e=v.elements();
03272               while (e.hasMoreElements())
03273               {      MacroItem m=(MacroItem)e.nextElement();
03274                      deleteMacro(m);
03275               }
03276        }
03277        
03278        public void deleteMacro (MacroItem m)
03279        {      Macros.removeElement(m);
03280               if (m.I!=null)
03281               {      m.I.removeActionListener(this);
03282                      MM.remove(m);
03283               }
03284        }
03285 
03286        public void clearMacros ()
03287        {      Enumeration e=Macros.elements();
03288               while (e.hasMoreElements())
03289               {      MacroItem m=(MacroItem)e.nextElement();
03290                      if (m.I!=null)
03291                      {      m.I.removeActionListener(this);
03292                             MM.remove(m);
03293                      }
03294               }
03295               Macros.removeAllElements();
03296        }
03297 
03298        public void clearNonprotectedMacros ()    
03299        {      Vector V=new Vector();      
03300               Enumeration e=Macros.elements();
03301               while (e.hasMoreElements())
03302               {      MacroItem m=(MacroItem)e.nextElement();
03303                      if (!m.M.isProtected()) V.addElement(m);
03304               }
03305               deleteMacros(V);
03306        }
03307 
03308        public void clearProtectedMacros ()       
03309        {      Vector V=new Vector();      
03310               Enumeration e=Macros.elements();
03311               while (e.hasMoreElements())
03312               {      MacroItem m=(MacroItem)e.nextElement();
03313                      if (m.M.isProtected()) V.addElement(m);
03314               }
03315               deleteMacros(V);
03316        }
03317 
03318        public void protectMacros ()
03319        {      Enumeration e=Macros.elements();
03320               while (e.hasMoreElements())
03321               {      MacroItem m=(MacroItem)e.nextElement();
03322                      m.M.setProtected(true);
03323               }
03324        }
03325        
03326        public void renameMacro (Macro macro, String name)
03327        {      Enumeration e=Macros.elements();
03328               while (e.hasMoreElements())
03329               {      MacroItem m=(MacroItem)e.nextElement();
03330                      if (m.I!=null && m.M==macro)
03331                      {      deleteMacro(m);
03332                             break;
03333                      }
03334               }
03335               macro.setName(name);
03336               appendMacro(macro);
03337        }
03338        
03339        MacroBar MBar;
03340        
03341        public void setMacroBar (MacroBar m)
03342        {      MBar=m;
03343        }
03344        
03345        public void updateMacroBar ()
03346        {      if (MBar!=null)
03347               {      MBar.update(Macros);
03348               }
03349        }
03350        
03351        // For the prompt in the status line:
03352        
03353        TextField TF;
03354        public void setTextField (TextField t)
03355        {      TF=t;
03356        }
03357        public void setPrompt (String s)
03358        {      if (TF!=null) TF.setText(s);
03359        }
03360 
03361        // Loading:
03362        
03363        public void loadRun (InputStream is)
03364        {      BufferedReader in=new BufferedReader(
03365                      new InputStreamReader(is));
03366               String s="",comment="";
03367               while (true)
03368               {      try
03369                      {      s=in.readLine();
03370                             if (s==null) break;
03371                             int n;
03372                             if ((n=s.indexOf("//"))>=0)
03373                             {      comment=s.substring(n+2).trim();
03374                                    s=s.substring(0,n);
03375                             }
03376                             else comment="";
03377                             s=s.trim();
03378                             int k=0;
03379                             if ((k=Interpreter.startTest("macro",s))>=0)
03380                             {      loadMacro(in,s.substring(k).trim());
03381                             }
03382                             else if (!s.equals("")) C.interpret(this,s,comment);
03383                      }
03384                      catch (ConstructionException e)
03385                      {      warning(e.getDescription()+" --- "+s);
03386                             break;
03387                      }
03388                      catch (Exception e)
03389                      {      warning(e.toString()+" --- "+s);
03390                             e.printStackTrace();
03391                             break;
03392                      }
03393               }
03394               C.updateCircleDep();
03395        }
03396        
03397        public void loadMacro (BufferedReader in, String name)
03398               throws ConstructionException
03399        {      Construction c=new Construction();
03400               c.clear();
03401               String s="",comment="",macrocomment="";
03402               boolean inComment=true,newLine=true;
03403               while (true)
03404               {      try
03405                      {      s=in.readLine();
03406                             if (s==null)
03407                                    throw new ConstructionException(
03408                                           Zirkel.name("exception.macroend"));
03409                             s=s.trim();
03410                             int n=s.indexOf("//");
03411                             if (inComment && n==0)
03412                             {      String h=s.substring(n+2).trim();
03413                                    if (newLine)
03414                                    {      macrocomment=macrocomment+h;
03415                                           newLine=false;
03416                                    }
03417                                    else
03418                                    {      if (h.equals(""))
03419                                           {      macrocomment=macrocomment+"\n";
03420                                                  newLine=true;
03421                                           }
03422                                           else
03423                                           {      macrocomment=macrocomment+" "+h;
03424                                                  newLine=false;
03425                                           }
03426                                    }
03427                                    continue;
03428                             }
03429                             inComment=false;
03430                             if (n>=0)
03431                             {      comment=s.substring(n+2).trim();
03432                                    s=s.substring(0,n);
03433                             }
03434                             else comment="";
03435                             s=s.trim();
03436                             if (s.equals(Zirkel.name("end"))) break;
03437                             if (s.toLowerCase().equals("end")) break;
03438                             if (!s.equals("")) c.interpret(this,s,comment);
03439                      }
03440                      catch (InvalidException e)
03441                      {
03442                      }
03443                      catch (ConstructionException e)
03444                      {      throw new ConstructionException(e.getDescription()+" --- "+s);
03445                      }
03446                      catch (IOException e)
03447                      {      warning(e.toString());
03448                             return;
03449                      }
03450               }
03451               defineMacro(name,macrocomment,c);
03452        }
03453        
03454        public double getGridSize ()
03455        {      double gridsize=Math.pow(10,Math.floor(
03456                      Math.log(C.getW()*2)/Math.log(10)))/10;
03457               if (C.getW()*2/gridsize>=30) gridsize*=5;
03458               if (C.getW()*2/gridsize<10) gridsize/=2;
03459               return gridsize;
03460        }
03461        
03462        synchronized public void print (Graphics g, int W, int H)
03463        {      if (IW==0 || I==null) return;
03464               startWaiting();
03465               int w=IW,h=IH;
03466               Scale=(double)W/w;
03467               PointSize=PointSize*Scale;
03468               double fontsize=FontSize*Scale;
03469               MyGraphics mg=new MyGraphics11(g);
03470               mg.setSize(w,h);
03471               mg.setDefaultFont((int)(fontsize),
03472                             Global.getParameter("font.large",false),
03473                             Global.getParameter("font.bold",false));
03474               IW=W; IH=H;
03475               recompute();
03476               if (Background!=null)
03477               {      int bw=Background.getWidth(this),
03478                             bh=Background.getHeight(this);
03479                      if (bw==IW && bh==IH)
03480                      {      mg.drawImage(Background,0,0,this);
03481                      }
03482                      else if (Global.getParameter("background.tile",true)
03483                             && bw<IW && bh<IH)
03484                      {      for (int i=(IW%bw)/2-bw; i<IW; i+=bw)
03485                                    for (int j=(IH%bh)/2-bh; j<IH; j+=bh)
03486                                           mg.drawImage(Background,i,j,this);
03487                      }
03488                      else if (Global.getParameter("background.center",true))
03489                      {      mg.drawImage(Background,(IW-bw)/2,(IH-bh)/2,this);
03490                      }
03491                      else
03492                      {      mg.drawImage(Background,0,0,IW,IH,this);
03493                      }
03494               }
03495               dopaint(mg);
03496               Interactive=true;
03497               Scale=1.0;
03498               I=null;
03499               endWaiting();
03500               repaint();
03501        }
03502        
03503        public LatexOutput createBB (String filename, 
03504                      int w, int h, double dpi)
03505        {      try
03506               {      String path="";
03507                      if (Global.getParameter("options.fullpath",true))
03508                             path=FileName.pathAndSeparator(filename);
03509                      PrintWriter out=
03510                             new PrintWriter(new FileOutputStream(
03511                                           path+FileName.purefilename(filename)+".bb"));
03512                      out.println("%%BoundingBox: 0 0 "+w+" "+h);
03513                      out.close();
03514                      out=new PrintWriter(new FileOutputStream(
03515                                    path+FileName.purefilename(filename)+".ztx"));
03516                      LatexOutput lout=new LatexOutput(out);
03517                      lout.open(w,h,dpi,path+FileName.filename(filename));
03518                      return lout;
03519               }
03520               catch (Exception e)
03521               {      warning(e.toString());
03522               }
03523               return null;
03524        }
03525        
03531        synchronized public boolean savePNG (String filename, boolean latex)
03532        {      LatexOutput lout=null;
03533               if (IW==0 || I==null) return false;
03534               if (Global.getParameter("printscale.middle",true))
03535               {      savePreviewAsPNG(filename);
03536                      return true;
03537               }
03538               double dpi=Global.getParameter("printscale.dpi",300);
03539               if (!Global.getParameter("printscale.sizes",false))
03540               {      int w=Global.getParameter("printscale.w",IW);
03541                      int h=Global.getParameter("printscale.h",IH);
03542                      if (latex) lout=createBB(filename,w,h,dpi);
03543                      int IWold=IW;
03544                      IW=w; IH=h;
03545                      Scale=((double)IW)/IWold;
03546                      I=createImage(IW,IH);
03547                      if (!Global.getParameter("simplegraphics",false))
03548                      {      IG=new MyGraphics13(I.getGraphics(),Scale,this,lout);
03549                             IG.setSize(w,h);
03550                      }
03551                      else
03552                      {      IG=new MyGraphics11(I.getGraphics());
03553                             IG.setSize(w,h);
03554                      }
03555                      double pointsize=PointSize*Scale;
03556                      double fontsize=FontSize*Scale;
03557                      if (Scale<1)
03558                      {      if (Global.getParameter("options.minpointsize",false) &&
03559                                    pointsize<MinPointSize) pointsize=MinPointSize;
03560                             if (Global.getParameter("options.minfontsize",false) &&
03561                                    fontsize<MinFontSize) fontsize=MinFontSize;
03562                      }
03563                      IG.setDefaultFont((int)(fontsize),
03564                                    Global.getParameter("font.large",false),
03565                                    Global.getParameter("font.bold",false));
03566                      PointSize=pointsize;
03567               }
03568               else
03569               {      int IWOld=IW;
03570                      dpi=Global.getParameter("printscale.dpi",300.0);
03571                      IW=(int)(Global.getParameter("printscale.width",5.0)/2.54*dpi);
03572                      IH=(int)(Global.getParameter("printscale.height",5.0)/2.54*dpi);
03573                      if (latex) lout=createBB(filename,IW,IH,dpi);
03574                      I=createImage(IW,IH);
03575                      if (!Global.getParameter("simplegraphics",false))
03576                      {      IG=new MyGraphics13(I.getGraphics(),
03577                                    Global.getParameter("printscale.linewidth",0.02)/2.54*dpi,this,lout);
03578                             IG.setSize(IW,IH);
03579                      }
03580                      else
03581                      {      IG=new MyGraphics11(I.getGraphics());
03582                             IG.setSize(IW,IH);
03583                      }
03584                      PointSize=Global.getParameter("printscale.pointsize",0.07)
03585                             /2.54*dpi;
03586                      IG.setDefaultFont((int)(Global.getParameter("printscale.textsize",0.3)
03587                                                  /2.54*dpi),
03588                                    Global.getParameter("font.large",false),
03589                                    Global.getParameter("font.bold",false));
03590                      Scale=(double)IW/IWOld;
03591               }
03592               recompute();
03593               if (Global.getParameter("options.bitmapbackground",false))
03594                      IG.clearRect(0,0,IW,IH,getBackground());
03595               else
03596                      IG.clearRect(0,0,IW,IH,Color.white);
03597               if (Background!=null)
03598               {      int bw=Background.getWidth(this),
03599                             bh=Background.getHeight(this);
03600                      if (bw==IW && bh==IH)
03601                      {      IG.drawImage(Background,0,0,this);
03602                      }
03603                      else if (Global.getParameter("background.tile",true)
03604                             && bw<IW && bh<IH)
03605                      {      for (int i=(IW%bw)/2-bw; i<IW; i+=bw)
03606                                    for (int j=(IH%bh)/2-bh; j<IH; j+=bh)
03607                                           IG.drawImage(Background,i,j,this);
03608                      }
03609                      else if (Global.getParameter("background.center",true))
03610                      {      IG.drawImage(Background,(IW-bw)/2,(IH-bh)/2,this);
03611                      }
03612                      else
03613                      {      IG.drawImage(Background,0,0,IW,IH,this);
03614                      }
03615               }
03616               dopaint(IG);
03617               if (lout!=null) lout.close();
03618               Interactive=true;
03619               if (!filename.equals(""))
03620               {      try
03621                      {      BufferedOutputStream 
03622                                    out=new BufferedOutputStream(new FileOutputStream(filename));
03623                             PngEncoder png=new PngEncoder(I,PngEncoder.NO_ALPHA,0,9);
03624                             png.setDPI(dpi);
03625                             out.write(png.pngEncode());
03626                             out.close();
03627                      }
03628                      catch (Exception e)
03629                      {      warning(e.toString());
03630                      }
03631               }
03632               else
03633               {      try
03634                      {      Clipboard clipboard = getToolkit().getSystemClipboard();
03635                             ImageSelection is=new ImageSelection(I);
03636                             clipboard.setContents(is,null);
03637                      }
03638                      catch (Exception e)
03639                      {      Scale=1;
03640                             I=null;
03641                             repaint();
03642                             return false;
03643                      }
03644               }
03645               Scale=1;
03646               I=null;
03647               repaint();
03648               return true;
03649        }
03650        
03651        public void savePreviewAsPNG (String filename)
03652        {      int PW=Global.getParameter("printscale.w",IW);
03653               int PH=Global.getParameter("printscale.h",IH);
03654               Image i=createImage(PW,PH);
03655               Graphics g=i.getGraphics();
03656               g.setColor(Color.WHITE);
03657               g.fillRect(0,0,PW,PH);
03658               g.drawImage(I,-(IW-PW)/2,-(IH-PH)/2,this);
03659               if (!filename.equals(""))
03660               {      try
03661                      {      FileOutputStream out=new FileOutputStream(filename);
03662                             PngEncoder png=new PngEncoder(i,PngEncoder.NO_ALPHA,0,9);
03663                             out.write(png.pngEncode());
03664                             out.close();
03665                      }
03666                      catch (Exception e)
03667                      {      warning(e.toString());
03668                      }
03669               }             
03670               else
03671               {      try
03672                      {      Clipboard clipboard = getToolkit().getSystemClipboard();
03673                             ImageSelection is=new ImageSelection(I);
03674                             clipboard.setContents(is,null);
03675                      }
03676                      catch (Exception e)
03677                      {}
03678               }
03679        }
03680        
03681        public void saveFIG (String filename)
03682        {      try
03683               {      PrintWriter out=new PrintWriter(
03684                             new FileOutputStream(filename));
03685                      MyGraphicsFig fig=new MyGraphicsFig(out,IW,IH);
03686                      fig.setSize(IW,IH);
03687                      dopaintFig(fig);
03688                      fig.close();
03689                      out.close();
03690               }
03691               catch (Exception e)
03692               {      warning(e.toString());
03693                      e.printStackTrace();
03694               }
03695        }
03696        
03697        public void saveSVG (String filename)
03698        {      try
03699               {      OutputStream o=new FileOutputStream(filename);
03700                      if (ZirkelFrame.isCompressed(filename))
03701                             o=new GZIPOutputStream(o); 
03702                      PrintWriter out=new PrintWriter(new OutputStreamWriter(o,"UTF8"));
03703                      MyGraphicsSvg svg=new MyGraphicsSvg(out,IW,IH);
03704                      svg.setSize(IW,IH);
03705                      dopaint(svg);
03706                      svg.close();
03707                      out.close();
03708               }
03709               catch (Exception e)
03710               {      warning(e.toString());
03711                      e.printStackTrace();
03712               }
03713        }
03714 
03715        public void savePDF (String filename)
03716        {      PrintWriter out=null;
03717               try
03718               {      OutputStream o=new FileOutputStream(filename);
03719                      if (ZirkelFrame.isCompressed(filename))
03720                             o=new GZIPOutputStream(o); 
03721                      out=new PrintWriter(new OutputStreamWriter(o,"CP1252"));
03722               }
03723               catch (Exception e)
03724               {      warning(e.toString());
03725                      e.printStackTrace();
03726               }      
03727               int iw=IW,ih=IH;
03728               IW=(int)(Global.getParameter("printscale.width",IW*2)/2.54*72+0.5);
03729               IH=(int)(Global.getParameter("printscale.height",IH*2)/2.54*72+0.5);
03730               double ps=PointSize; 
03731               Scale=(double)IW/iw;
03732               double pointsize=PointSize*Scale;
03733               double fontsize=FontSize*Scale+1;
03734               double linewidth=Scale;
03735               if (Global.getParameter("printscale.sizes",false))
03736               {      pointsize=Global.getParameter("printscale.pointsize",0.07)/2.54*72;
03737                      fontsize=Global.getParameter("printscale.fontsize",0.3)/2.54*72;
03738                      linewidth=Global.getParameter("printscale.linewidth",0.02)/2.54*72;
03739               }
03740               PointSize=pointsize;
03741               recompute();
03742               MyGraphicsPDF pdf=new MyGraphicsPDF(out,IW,IH,linewidth);
03743               pdf.setSize(IW,IH);
03744               pdf.setDefaultFont((int)(fontsize),
03745                             Global.getParameter("font.large",false),
03746                             Global.getParameter("font.bold",false));
03747               try
03748               {      dopaint(pdf);
03749                      pdf.close();
03750                      out.close();
03751               }
03752               catch (Exception e)
03753               {      warning(e.toString());
03754                      e.printStackTrace();
03755               }
03756               IW=iw; IH=ih; 
03757               Scale=1.0;
03758               PointSize=ps;
03759               I=null;
03760               repaint();
03761        }
03762 
03763        public void saveEPS (String filename)
03764        {      OutputStream o=null;
03765               try
03766               {      o=new FileOutputStream(filename);
03767                      if (ZirkelFrame.isCompressed(filename))
03768                             o=new GZIPOutputStream(o);
03769               }
03770               catch (Exception e)
03771               {      warning(e.toString());
03772                      e.printStackTrace();
03773               }
03774               int iw=IW,ih=IH;
03775               IW=(int)(Global.getParameter("printscale.width",IW*2)/2.54*72+0.5);
03776               IH=(int)(Global.getParameter("printscale.height",IH*2)/2.54*72+0.5);
03777               double ps=PointSize; 
03778               Scale=(double)IW/iw;
03779               double pointsize=PointSize*Scale;
03780               double fontsize=FontSize*Scale+1;
03781               double linewidth=Scale;
03782               if (Global.getParameter("printscale.sizes",false))
03783               {      pointsize=Global.getParameter("printscale.pointsize",0.07)/2.54*72;
03784                      fontsize=Global.getParameter("printscale.fontsize",0.3)/2.54*72;
03785                      linewidth=Global.getParameter("printscale.linewidth",0.02)/2.54*72;
03786               }
03787               PointSize=pointsize;
03788               recompute();
03789               try
03790               {      MyGraphicsEPS eps=new MyGraphicsEPS(o,IW,IH);
03791                      eps.setSize(IW,IH);
03792                      eps.setLineWidth(linewidth);
03793                      eps.setDefaultFont((int)(fontsize),
03794                             Global.getParameter("font.large",false),
03795                             Global.getParameter("font.bold",false));
03796                      dopaint(eps);
03797                      eps.close();
03798                      o.close();
03799               }
03800               catch (Exception e)
03801               {      warning(e.toString());
03802                      e.printStackTrace();
03803               }
03804               IW=iw; IH=ih; 
03805               Scale=1.0;
03806               PointSize=ps;
03807               I=null;
03808               repaint();
03809        }
03810        
03814        public void returnPressed ()
03815        {      if (OC instanceof MacroRunner)
03816               {      ((MacroRunner)OC).returnPressed(this);
03817               }
03818        }
03819        
03820        public void bind (PointObject p)
03821        {      setTool(new BinderTool(this,p,OC));
03822        }
03823        
03824        public void setAway (IntersectionObject p, boolean away)
03825        {      setTool(new SetAwayTool(this,p,away,OC));
03826        }
03827        
03828        public void setCurveCenter (FunctionObject p)
03829        {      setTool(new SetCurveCenterTool(this,p,OC));
03830        }
03831        
03832        public void range (PrimitiveCircleObject c)
03833        {      setTool(new SetRangeTool(this,c,OC));
03834        }
03835        
03836        public void set (FixedAngleObject a)
03837        {      setTool(new SetFixedAngle(this,a,OC));
03838        }
03839        
03840        public void set (FixedCircleObject c)
03841        {      setTool(new SetFixedCircle(this,c,OC));
03842        }
03843        
03844        public boolean enabled (String function)
03845        {      if (ZCI!=null) return ZCI.enabled(function);
03846               else return true;
03847        }
03848        
03849        public void pause (boolean flag)
03850        {      OC.pause(flag);
03851        }
03852        
03853        public void setReadOnly (boolean flag)
03854        {      ReadOnly=flag;
03855        }
03856 
03857        public void allowRightMouse (boolean flag)
03858        {      AllowRightMouse=flag;
03859        }
03860 
03861        public boolean changed ()
03862        {      return C.changed();
03863        }
03864        
03865        Image OldBackground=null;
03866        
03874        public void grab (boolean flag)
03875        {      if (flag)
03876               {      OldBackground=Background;
03877                      Background=createImage(IW,IH);
03878                      Graphics G=Background.getGraphics();
03879                      G.drawImage(I,0,0,this);
03880               }
03881               else
03882               {      Background=OldBackground;
03883                      OldBackground=null;
03884               }
03885               repaint();
03886        }
03887        
03888        public void setBackground (Image i)
03889        {      Background=i;
03890               repaint();
03891        }
03892 
03893        public void setInteractive (boolean flag)
03894        {      Interactive=flag;
03895        }
03896        
03897        public ObjectConstructor getCurrentTool ()
03898        {      return OC;
03899        }
03900 
03901        MyVector Drawings=new MyVector();
03902        
03903        public synchronized void addDrawing (Drawing d)
03904        {      Drawings.addElement(d);
03905        }
03906        
03907        public synchronized void clearDrawings ()
03908        {      Drawings.removeAllElements();
03909               repaint();
03910        }      
03911 
03912        public synchronized void paintDrawings (MyGraphics g)
03913        {      Enumeration e=Drawings.elements();
03914               while (e.hasMoreElements())
03915               {      Drawing d=(Drawing)e.nextElement();
03916                      Enumeration ec=d.elements();
03917                      if (ec.hasMoreElements())
03918                      {      g.setColor(ZirkelFrame.Colors[d.getColor()]);
03919                             CoordinatesXY xy=(CoordinatesXY)ec.nextElement();
03920                             int c=(int)col(xy.X),r=(int)row(xy.Y);
03921                             while (ec.hasMoreElements())
03922                             {      xy=(CoordinatesXY)ec.nextElement();
03923                                    int c1=(int)col(xy.X),r1=(int)row(xy.Y);
03924                                    g.drawLine(c,r,c1,r1);
03925                                    c=c1; r=r1;
03926                             }
03927                      }
03928               }
03929        }
03930 
03931        public void saveDrawings (XmlWriter xml)
03932        {      Enumeration e=Drawings.elements();
03933               while (e.hasMoreElements())
03934               {      Drawing d=(Drawing)e.nextElement();
03935                      Enumeration ec=d.elements();
03936                      if (ec.hasMoreElements())
03937                      {      xml.startTagNewLine("Draw","color",""+d.getColor());
03938                             while (ec.hasMoreElements())
03939                             {      CoordinatesXY xy=(CoordinatesXY)ec.nextElement();
03940                                    xml.startTagStart("Point");
03941                                    xml.printArg("x",""+xy.X);
03942                                    xml.printArg("y",""+xy.Y);
03943                                    xml.finishTagNewLine();
03944                             }
03945                             xml.endTagNewLine("Draw");
03946                      }      
03947               }
03948        }      
03949 
03950        public void loadDrawings (XmlTree tree)
03951               throws ConstructionException
03952        {      XmlTag tag=tree.getTag();
03953               if (!tag.name().equals("Draw")) return;
03954               Drawing d=new Drawing();
03955               try
03956               {      if (tag.hasParam("color"))
03957                      {      d.setColor(
03958                                    Integer.parseInt(tag.getValue("color")));
03959                      }
03960               }
03961               catch (Exception e)
03962               {      throw new ConstructionException("Illegal Draw Parameter");
03963               }
03964               Enumeration e=tree.getContent();
03965               while (e.hasMoreElements())
03966               {      XmlTree t=(XmlTree)e.nextElement();
03967                      tag=t.getTag();
03968                      if (tag.name().equals("Point"))
03969                      {      try
03970                             {      double x=new Double(tag.getValue("x")).doubleValue();
03971                                    double y=new Double(tag.getValue("y")).doubleValue();
03972                                    d.addXY(x,y);
03973                             }
03974                             catch (Exception ex)
03975                             {      throw new ConstructionException("Illegal Draw Parameter");
03976                             }
03977                      }
03978               }
03979               Drawings.addElement(d);
03980        }
03981 
03982        int PointLast,LineLast,AngleLast;
03983 
03984        public void renameABC (ConstructionObject o, boolean enforce, boolean reset)
03985        {      if (!enforce)
03986               {      if (o instanceof PointObject)
03987                      {      for (int i='A'; i<='Z'; i++)
03988                             {      ConstructionObject h=C.find(""+(char)i);
03989                                    if (h==null)
03990                                    {      o.setName(""+(char)i);
03991                                           o.setShowName(true);
03992                                           repaint();
03993                                           break;
03994                                    }
03995                             }
03996                      }
03997                      else if (o instanceof AngleObject || o instanceof FixedAngleObject)
03998                      {      for (int i='a'; i<='z'; i++)
03999                             {      ConstructionObject h=C.find("\\"+(char)i);
04000                                    if (h==null)
04001                                    {      o.setName("\\"+(char)i);
04002                                           o.setShowName(true);
04003                                           repaint();
04004                                           break;
04005                                    }
04006                             }
04007                      }
04008                      else if (o instanceof PrimitiveLineObject)
04009                      {      for (int i='a'; i<='z'; i++)
04010                             {      ConstructionObject h=C.find(""+(char)i);
04011                                    if (h==null)
04012                                    {      o.setName(""+(char)i);
04013                                           o.setShowName(true);
04014                                           repaint();
04015                                           break;
04016                                    }
04017                             }
04018                      }
04019               }
04020               else
04021               {      if (reset)
04022                      {      PointLast=0; LineLast=0; AngleLast=0;
04023                      }
04024                      if (o instanceof PointObject)
04025                      {      String name=""+(char)('A'+PointLast);
04026                             ConstructionObject h=C.find(name);
04027                             if (h!=null && h!=o) 
04028                             {      h.setName("***temp***");
04029                                    String s=o.getName();
04030                                    o.setName(name);
04031                                    h.setName(s);
04032                             }
04033                             else
04034                             {      o.setName(name);
04035                             }
04036                             PointLast++;
04037                      }
04038                      else if (o instanceof AngleObject || o instanceof FixedAngleObject)
04039                      {      String name="\\"+(char)('a'+AngleLast);
04040                             ConstructionObject h=C.find(name);
04041                             if (h!=null && h!=o) 
04042                             {      h.setName("***temp***");
04043                                    String s=o.getName();
04044                                    o.setName(name);
04045                                    h.setName(s);
04046                             }
04047                             else
04048                             {      o.setName(name);
04049                             }
04050                             AngleLast++;
04051                      }
04052                      else if (o instanceof PrimitiveLineObject)
04053                      {      String name=""+(char)('a'+LineLast);
04054                             ConstructionObject h=C.find(name);
04055                             if (h!=null && h!=o) 
04056                             {      h.setName("***temp***");
04057                                    String s=o.getName();
04058                                    o.setName(name);
04059                                    h.setName(s);
04060                             }
04061                             else
04062                             {      o.setName(name);
04063                             }
04064                             LineLast++;
04065                      }
04066               }
04067        }
04068        
04069        public void selectAllMoveableVisibleObjects ()
04070        {      Enumeration e=C.elements();
04071               while (e.hasMoreElements())
04072               {      ConstructionObject o=(ConstructionObject)e.nextElement();
04073                      if (o instanceof MoveableObject && ((MoveableObject)o).moveable()
04074                             && !o.mustHide(this))
04075                      {      o.setStrongSelected(true);
04076                      }
04077               }
04078        }
04079        
04080        public void hideDuplicates (ConstructionObject from)
04081        {      Enumeration e=C.elements();
04082               if (from!=null)
04083               {      while (e.hasMoreElements())
04084                      {      ConstructionObject o=(ConstructionObject)e.nextElement();
04085                             if (o==from) break;
04086                      }
04087               }
04088               while (e.hasMoreElements())
04089               {      ConstructionObject o=(ConstructionObject)e.nextElement();
04090                      if (o.mustHide(this) || o.isKeep()) continue;
04091                      Enumeration ex=C.elements();
04092                      while (ex.hasMoreElements())
04093                      {      ConstructionObject o1=(ConstructionObject)ex.nextElement();
04094                             if (o1==o) break;
04095                             if (o1.mustHide(this) || o1.isKeep()) continue;
04096                             if (o.equals(o1))
04097                             {      o.setHidden(true);
04098                                    break;
04099                             }
04100                      }
04101               }
04102        }
04103        
04104        public void hideDuplicates ()
04105        {      hideDuplicates(null);
04106        }
04107        
04108        public void createCurve ()
04109        {      FunctionObject f=new FunctionObject(C);
04110               f.setDefaults();
04111               C.add(f);
04112               f.setExpressions("x","x","0");
04113               f.edit(this);
04114               if (f.EditAborted) delete(f);
04115               repaint();
04116               reloadCD();
04117        }
04118        
04119        public void createFunction ()
04120        {      UserFunctionObject f=new UserFunctionObject(C);
04121               f.setDefaults();
04122               f.setShowName(true);
04123               f.setShowValue(true);
04124               C.add(f);
04125               f.setExpressions("x","0");
04126               f.edit(this);
04127               if (f.EditAborted) delete(f);
04128               repaint();
04129               reloadCD();
04130        }
04131        
04132        public void editLast ()
04133        {      if (C.last()==null) return;
04134               C.last().edit(this);
04135        }
04136        
04137        public void breakpointLast (boolean flag, boolean hiding)
04138        {      ConstructionObject o=C.last();
04139               if (o==null) return;
04140               if (hiding) o.setHideBreak(flag);
04141               else o.setBreak(flag);
04142        }
04143        
04144        public void notifyChanged ()
04145        {      if (!C.Loading) reloadCD();
04146        }
04147 
04148        public void startWaiting ()
04149        {      Interactive=false;
04150               showMessage(Zirkel.name("message.saving"));
04151        }
04152 
04153        public void endWaiting ()
04154        {      Interactive=true;
04155               hideMessage();
04156        }
04157        
04158        public void showMessage (String s)
04159        {      hideMessage();
04160               MW=new MessageWindow(F,s);
04161               MW.setVisible(true);
04162        } 
04163        
04164        public void hideMessage ()
04165        {      if (MW!=null)
04166               {      MW.setVisible(false); MW.dispose();
04167                      MW=null;
04168               }
04169        }
04170        
04171        // HotEqn stuff, requires the HotEqn classes:
04172        
04173        sHotEqn HE=null;
04174        
04175        public void setHotEqn (String s)
04176        {      if (HE==null)
04177               {      HE=new sHotEqn(this);
04178               }
04179               HE.setEquation(s);
04180        }
04181        
04182        public int paintHotEqn (int c, int r, Graphics g)
04183        {      if (HE==null) return 0;
04184               return HE.paint(c,r,g);
04185        }
04186        
04187        // Stuff for the permanent construction display
04188        
04189        public ConstructionDisplayPanel CDP=null;
04190        
04191        public void reloadCD ()
04192        {      if (CDP!=null && C!=null)
04193               {      CDP.reload();
04194               }
04195        }
04196        
04197        public void repaintCD ()
04198        {      if (CDP!=null && C!=null) CDP.updateDisplay();   
04199        }
04200        
04201        public void callCDAction (String action)
04202        {      if (CDP!=null && C!=null) CDP.doAction(action);
04203        }
04204        
04205        public void callCDItem (String action, boolean flag)
04206        {      if (CDP!=null && C!=null) CDP.itemAction(action,flag);
04207        }
04208        
04209        public void callCDToggleItem (String action)
04210        {      if (CDP!=null && C!=null) CDP.itemToggleAction(action);
04211        }
04212        
04213        public void mouseWheelMoved (MouseWheelEvent e) 
04214        {      if (Global.getParameter("options.nomousezoom",false)) return;
04215               if (e.getScrollType()==MouseWheelEvent.WHEEL_BLOCK_SCROLL)
04216               {      if (e.getWheelRotation()<0)
04217                      {      magnify(1/Math.sqrt(Math.sqrt(2)));
04218                      }
04219                      else
04220                      {      magnify(Math.sqrt(Math.sqrt(2)));
04221                      }
04222               }
04223               else
04224               {      int n=e.getScrollAmount();
04225                      if (e.getWheelRotation()<0)
04226                      {      magnify(1/Math.pow(2,n/12.));
04227                      }
04228                      else
04229                      {      magnify(Math.pow(2,n/12.));
04230                      }
04231               }
04232        }
04233 }