Logo Search packages:      
Sourcecode: latexdraw version File versions  Download package

FramedBox.java

package latexDraw.figures;


import java.awt.Graphics2D;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Vector;

import latexDraw.figures.Text.TextPosition;
import latexDraw.psTricks.PSTricksConstants;
import latexDraw.util.LaTeXDrawPoint2D;



/**
 * This class defines a box which can frame a (part of a) text.<br>
 * <br>
 * This file is part of LaTeXDraw<br>
 * Copyright (c) 2005-2008 Arnaud BLOUIN<br>
 * <br>
 * LaTeXDraw is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.<br>
 * <br>
 * LaTeXDraw is distributed without any warranty; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.<br>
 * <br>
 * 05/08/06<br>
 * @author Arnaud BLOUIN<br>
 * @since 1.7
 */
00037 public class FramedBox implements Cloneable, Serializable
{
      private static final long serialVersionUID = 1L;

      /** The text of the box. */
00042       protected Text text;

      /** Define the separation between the text and the box (in pixels). */
00045       protected double frameSep;

      /** The box. */
00048       protected Figure box;

      /** Define if the box can be drawn of the text before and after the framed text. */
00051       protected boolean boxSep;

      /** The position of the beginning of the box in the string text of the class Text. */
00054       protected int start;

      /** The type of the box: rectangle, circle, ellipse, triangle or rhombus. */
00057       protected int boxType;

      /** The position of the end of the box in the string text of the class Text. */
00060       protected int end;

      protected transient Vector<TextPosition> textPosition;
      
      /** The box will be a rectangle. */
00065       public static final short BOX_RECTANGLE = 0;

      /** The box will be a circle. */
00068       public static final short BOX_CIRCLE = 1;

      /** The box will be an ellipse. */
00071       public static final short BOX_ELLIPSE = 2;

      /** The box will be a triangle. */
00074       public static final short BOX_TRIANGLE = 3;

      /** The box will be a diamond. */
00077       public static final short BOX_DIAMOND = 4;




      public FramedBox(Text text)
      {
            this(text, PSTricksConstants.DEFAULT_FRAME_SEP*Figure.PPC, BOX_RECTANGLE, PSTricksConstants.DEFAULT_BOX_SEP, -1, -1);
      }




      /**
       * The constructor.
       * @param frameSep The size of the separation between the text and the borders (in pixels).
       */
00094       public FramedBox(Text text, double frameSep, short type, boolean boxSep, int start, int end)
      {
            super();
            
            this.text = text;
            this.frameSep = frameSep;
            this.boxSep = boxSep;
            this.start = start;
            this.end = end;
            textPosition = new Vector<TextPosition>();
            setBoxType(type);
      }


      
      /**
       * Allows to know if the argument type is a valid kind of box.
       * @param type The type to check.
       * @return True if type is a valid kind of box.
       */
00114       public static boolean isValidBoxType(short type)
      {
            return type==BOX_CIRCLE || type==BOX_ELLIPSE || type==BOX_RECTANGLE || type==BOX_TRIANGLE || type==BOX_DIAMOND;
      }




      /**
       * Allows to update the size of the box.
       */
00125       public synchronized void updateBoxSize()
      {
            double x1;
            double x2;
            double y1;
            double y2;

            if(text.text.length()==0)
                  return;

            text.updateFontsBorders();
            LaTeXDrawPoint2D position = text.getPosition();
            TextLayout tl = new TextLayout(text.text, text.currentFont, text.fontRenderContext);
            Rectangle2D bounds = tl.getBounds();

            x1 = position.x+bounds.getX()-frameSep;
            x2 = position.x+bounds.getWidth()+bounds.getX()+frameSep;
            y1 = bounds.getY()+position.y-frameSep;
            y2 = position.y+bounds.getHeight()+bounds.getY()+frameSep;

            if(start>=0 && end>0 && end<=text.text.length())
            {
                  if(start>0)
                        x1 += text.fontMetrics.stringWidth(text.text.substring(0, start));
                  x2 -= text.fontMetrics.stringWidth(text.text.substring(end));
            }

            LaTeXDrawRectangle r = box.getBorders();

            if(boxType==BOX_CIRCLE)
            {
                  double cgX = (x1+x2)/2., cgY = (y1+y2)/2.;
                  double radius = Math.max(Math.abs(x1-x2), Math.abs(y1-y2))/2.;

                  r.getPoint(0).setLocation(cgX-radius, cgY-radius);
                  r.getPoint(-1).setLocation(cgX+radius, cgY+radius);
                  r.getPoint(1).setLocation(cgX+radius, cgY-radius);
                  r.getPoint(2).setLocation(cgX-radius, cgY+radius);
                  ((Square)r).setWidth(radius*2);
            }
            else
            {
                  r.setFirstPoint(x1, y1);
                  r.setLastPoint(x2, y2);
                  r.updateGravityCenter();

                  if(boxType==BOX_ELLIPSE)
                  {
                        double gap = (bounds.getMaxX() - bounds.getMinX())*0.5;
                        r.setFirstPoint(r.getTheNWPoint().x-gap/2., r.getTheNWPoint().y);
                        r.setLastPoint(r.getTheSEPoint().x+gap/2., r.getTheSEPoint().y);
                  }
                  else
                  {
                        LaTeXDrawPoint2D cg = r.getGravityCenter();
                        double height = y2-y1, width = x2-x1;
                        
                        if(boxType==BOX_DIAMOND)
                        {
                              double g = box.getThickness()*0.707;
                              double g2 = frameSep/2.;
                              box.setBordersPosition(PSTricksConstants.BORDERS_INSIDE);
                              r.setFirstPoint(cg.x-width-g*2+g2, cg.y-height-g*2.+g2);
                              r.setLastPoint(cg.x+width+g*2-g2, cg.y+height+g*2.-g2);
                        }
                        else
                              if(boxType==BOX_TRIANGLE)
                              {
                                    double g = box.getThickness()*0.85;
                                    box.setBordersPosition(PSTricksConstants.BORDERS_INSIDE);
                                    r.setFirstPoint(cg.x-width-g*2, cg.y-(height*3.)/2.-box.getThickness()*2+frameSep);
                                    r.setLastPoint(cg.x+width+g*2, cg.y+height/2.+box.getThickness());
                              }
                  }
            }
            
            box.updateShape();
      }




      /**
       * @return the box
       */
00210       public synchronized Figure getBox()
      {
            return box;
      }




      /**
       * @param box the box to set (must be a circle, an ellipse, a rectangle, a rhombus or a triangle).
       */
00221       public synchronized void setBox(Figure box)
      {
            if(box==null)
                  return ;
            
            this.box = box;
            
            if(box instanceof LaTeXDrawRectangle)
                  setBoxType(BOX_RECTANGLE);
            else if(box instanceof Rhombus)
                  setBoxType(BOX_DIAMOND);
            else if(box instanceof Triangle)
                  setBoxType(BOX_TRIANGLE);
            else if(box instanceof Ellipse)
                  setBoxType(BOX_ELLIPSE);
            else if(box instanceof Circle)
                  setBoxType(BOX_CIRCLE);
      }




      /**
       * @return the boxSep
       */
00246       public synchronized boolean isBoxSep()
      {
            return boxSep;
      }




      /**
       * @param boxSep the boxSep to set
       */
00257       public synchronized void setBoxSep(boolean boxSep)
      {
            this.boxSep = boxSep;
            text.hasChanged = true;
      }




      /**
       * @return the frameSep
       */
00269       public synchronized double getFrameSep()
      {
            return frameSep;
      }




      /**
       * @param frameSep the frameSep to set
       */
00280       public synchronized void setFrameSep(double frameSep)
      {
            this.frameSep = frameSep;
            text.hasChanged = true;
      }




      /**
       * @return the text
       */
00292       public synchronized Text getText()
      {
            return text;
      }




      /**
       * @param text the text to set
       */
00303       public synchronized void setText(Text text)
      {
            this.text = text;
            text.hasChanged = true;
      }




      /**
       * @return the end
       */
00315       public synchronized int getEnd()
      {
            return end;
      }




      /**
       * @param end the end to set
       */
00326       public synchronized void setEnd(int end)
      {
            this.end = end;
            text.hasChanged = true;
      }




      /**
       * @return the start
       */
00338       public synchronized int getStart()
      {
            return start;
      }




      /**
       * @param start the start to set
       */
00349       public synchronized void setStart(int start)
      {
            this.start = start;
            text.hasChanged = true;
      }




      /**
       * @return the boxType
       */
00361       public synchronized int getBoxType()
      {
            return boxType;
      }




      /**
       * @param type the boxType to set.
       */
00372       public synchronized void setBoxType(short type)
      {
            if(!isValidBoxType(type))
                  return;

            if(type!=boxType||box==null)
            {
                  boxType = type;

                  if(box==null)
                        switch(boxType)
                        {
                              case BOX_CIRCLE:
                                    box = new Circle(true);
                                    break;

                              case BOX_ELLIPSE:
                                    box = new Ellipse(true);
                                    break;

                              case BOX_RECTANGLE:
                                    box = new LaTeXDrawRectangle(true);
                                    break;

                              case BOX_TRIANGLE:
                                    box = new Triangle(true);
                                    break;

                              case BOX_DIAMOND:
                                    box = new Rhombus(true);
                                    break;

                              default:
                                    throw new IllegalArgumentException("Invalid kind of box.");//$NON-NLS-1$
                        }
                  else
                        switch(boxType)
                        {
                              case BOX_CIRCLE:
                                    box = new Circle(box, true);
                                    break;

                              case BOX_ELLIPSE:
                                    box = new Ellipse(box, true);
                                    break;

                              case BOX_RECTANGLE:
                                    box = new LaTeXDrawRectangle(box, true);
                                    break;

                              case BOX_TRIANGLE:
                                    box = new Triangle(box, true);
                                    break;

                              case BOX_DIAMOND:
                                    box = new Rhombus(box, true);
                                    break;

                              default:
                                    throw new IllegalArgumentException("Invalid kind of box.");//$NON-NLS-1$
                        }

                  box.setBordersPosition(PSTricksConstants.BORDERS_OUTSIDE);
                  
                  if(text.hasSeveralBoxes())
                        text.updateFramedBoxes();
                  else updateBoxSize();
            }

            text.hasChanged = true;
      }




      /**
       * Draw the framed box.
       */
00450       public void draw(Graphics2D g, Object antiAlias, Object rendering, Object alphaInter, Object colorRendering)
      {
            if(getBox()!=null)
                  getBox().draw(g, antiAlias, rendering, alphaInter, colorRendering);
      }




      /**
       * @return The PSTricks code of the framed box.
       */
00462       public synchronized String getCodePSTricks(DrawBorders drawBorders, float ppc)
      {
            String cmdName = getCodeHeadPSTricks(drawBorders, ppc);
            cmdName += '{'+getBoxedText()+'}';

            return cmdName;
      }




      /**
       * @return The boxed text.
       */
00476       public synchronized String getBoxedText()
      {
            int e, s;
            if(end<0||start<0||end==start||end>text.text.length())
            {
                  e = text.text.length();
                  s = 0;
            }
            else
            {
                  s = start;
                  e = end;
            }

            return text.getText().substring(s, e);
      }




      /**
       * @return The beginning of the code (ex. \psframe[....] instead of psframe[...]{...} of the method getCode.
       */
00499       public synchronized String getCodeHeadPSTricks(DrawBorders drawBorders, float ppc)
      {
            if(box==null)
                  return "";//$NON-NLS-1$

            String boxCode = box.getCodePSTricks(drawBorders, ppc);
            String boxParams = "";//$NON-NLS-1$

            int i = boxCode.indexOf('[');
            if(i!=-1)
            {
                  int j = boxCode.indexOf(']', i);
                  if(j==-1)
                        throw new IndexOutOfBoundsException();
                  boxParams = boxCode.substring(i+1, j);
                  boxParams = boxParams.replace(",dimen=inner", "");//$NON-NLS-1$//$NON-NLS-2$
                  boxParams = boxParams.replace(",dimen=middle", "");//$NON-NLS-1$//$NON-NLS-2$
                  boxParams = boxParams.replace(",dimen=outer", "");//$NON-NLS-1$//$NON-NLS-2$
            }

            String cmdName;

            switch(boxType)
            {
                  case BOX_RECTANGLE:
                        cmdName = "\\psframebox";//$NON-NLS-1$
                        break;

                  case BOX_ELLIPSE:
                        cmdName = "\\psovalbox";//$NON-NLS-1$
                        break;

                  case BOX_CIRCLE:
                        cmdName = "\\pscirclebox";//$NON-NLS-1$
                        break;

                  case BOX_DIAMOND:
                        cmdName = "\\psdiabox";//$NON-NLS-1$
                        break;

                  case BOX_TRIANGLE:
                        cmdName = "\\pstribox";//$NON-NLS-1$
                        break;

                  default:
                        return null;
            }

            if(((float)(frameSep/ppc))!=(float)PSTricksConstants.DEFAULT_FRAME_SEP)
                  boxParams += (boxParams.length()>0 ? "," : "")//$NON-NLS-1$//$NON-NLS-2$
                              +"framesep="+(float)frameSep/ppc;//$NON-NLS-1$

            if(boxSep!=PSTricksConstants.DEFAULT_BOX_SEP)
                  boxParams += (boxParams.length()>0 ? "," : "")+"boxsep=" //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
                              +boxSep;

            if(boxParams.length()>0)
                  cmdName += '['+boxParams+']';

            return cmdName;
      }




      @Override
      public Object clone() throws CloneNotSupportedException
      {
            FramedBox fb = (FramedBox)super.clone();

            fb.boxSep = boxSep;
            fb.boxType = boxType;
            fb.box = (Figure)box.clone();
            fb.end = end;
            fb.frameSep = frameSep;
            fb.start = start;
            fb.text = text;// We cannot clone the text because the text clones the fb.
            fb.textPosition = new Vector<TextPosition>();
            for(TextPosition tp : textPosition)
                  fb.textPosition.add(tp);
            
            return fb;
      }




      private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException
      {
            text = null;
            boxSep = ois.readBoolean();
            boxType = ois.readInt();
            frameSep = ois.readDouble();
            start = ois.readInt();
            end = ois.readInt();
            box = (Figure)ois.readObject();
            textPosition = new Vector<TextPosition>();
      }



      /**
       * @return The borders of the framed box.
       */
00603       public synchronized LaTeXDrawRectangle getBorders()
      {
            return box.getBoundBorders();
      }



      /**
       * Allows to know if the framed box overlap another framed box.
       * @return True if the framed box overlap another framed box.
       */
00614       public synchronized boolean overlap(Vector<FramedBox> fbs)
      {
            if(fbs==null)
                  return false;

            boolean ok = true;
            int i = 0, size = fbs.size();

            while(ok&&i<size)
                  if(fbs.elementAt(i)!=this&&overlap(fbs.elementAt(i)))
                        ok = false;
                  else
                        i++;

            return !ok;
      }




      /**
       * Allows to know if the framed box overlap another framed box.
       * @return True if the framed box overlap another framed box.
       */
00638       public synchronized boolean overlap(FramedBox b)
      {
            return overlap(b.start, b.end);
      }




      /**
       * Allows to know if the framed box overlap another framed box.
       * @return True if the framed box overlap another framed box.
       */
00650       public synchronized boolean overlap(int fbStart, int fbEnd)
      {
            if(start<0||end<0)
                  return false;

            return (start<fbStart&&fbStart<end&&end<fbEnd)
                        ||(start>fbStart&&start<fbEnd&&fbEnd<end);
      }




      /**
       * Allows to know if the current FrameBox contains (frames) the given FramedBox.
       * @param b The FramedBox we want to know if it is boxed by the current  FramedBox
       * @return 0 if 'this' does not contain b, 1 if 'this' contains b and -1 if they are equals.
       */
00667       public synchronized int contains(FramedBox b)
      {
            if(box==null||b==null)
                  return 0;

            if(start==b.start&&end==b.end)
                  return -1;

            if(start<=b.start&&end>=b.end)
                  return 1;
            return 0;
      }




      @Override
      public String toString()
      {
            if(text==null||text.text==null||text.text.length()==0)
                  return super.toString();

            if(start<0||end>text.text.length())
                  return super.toString();

            return text.text.substring(start, end);
      }





      /**
       * @return The PSTricks code of the framed boxes.
       */
      @SuppressWarnings("unchecked")
00703       private static String getCode(Vector<FramedBox> boxes, FramedBox parent, DrawBorders drawBorders, float ppc) 
      {
            if(boxes==null||boxes.isEmpty())
            {
                  if(parent==null)
                        return "";//$NON-NLS-1$
                  return parent.getBoxedText();
            }

            boolean valid = true;
            String code = "";//$NON-NLS-1$
            int i = 0, j, size = boxes.size(), k, size2;
            boolean ok;
            Vector<FramedBox> mainBoxes = new Vector<FramedBox>();

            for(i = 1; i<size; i++)
                  if(!boxes.elementAt(i).getText().text.equals(boxes.elementAt(i-1).getText().text))
                        valid = false;

            if(!valid)
                  return "";//$NON-NLS-1$

            i = 0;
            if(size>1)
                  while(i<size)
                  {
                        FramedBox fb = boxes.elementAt(i);
                        ok = true;
                        for(j = 0; ok && j<i; j++)
                              if(boxes.elementAt(j).contains(fb)==1)
                                    ok = false;

                        for(j = i+1; ok && j<size; j++)
                              if(boxes.elementAt(j).contains(fb)!=0)
                                    ok = false;

                        for(FramedBox b : mainBoxes)
                              if(b.contains(fb)==1)
                                    ok = false;
                        
                        if(parent!=null && parent.contains(fb)==0)
                              ok = false;

                        if(ok)
                        {
                              FramedBox fBox = boxes.remove(i);
                              k = 0;
                              size2 = mainBoxes.size();
                              while(k<size2 && fBox.start>mainBoxes.elementAt(k).start)
                                    k++;

                              if(k>=size2)
                                    mainBoxes.add(fBox);
                              else
                                    mainBoxes.add(k, fBox);

                              size = boxes.size();
                        }
                        else i++;
                  }//while
            else
            {
                  FramedBox fb = boxes.remove(0);
                  if((parent!=null && parent.contains(fb)!=0) || parent==null)
                        mainBoxes.add(fb);
            }

            if(!mainBoxes.isEmpty())
            {
                  int s = parent==null ? 0 : parent.start;
                  
                  for(FramedBox b : mainBoxes)
                  {
                        if(b.start>s && (parent==null || parent.start!=b.start))
                              code += b.getText().text.substring(s, b.start);
                        
                        code += b.getCodeHeadPSTricks(drawBorders, ppc)+"{" +//$NON-NLS-1$
                         getCode((Vector<FramedBox>)boxes.clone(), b, drawBorders, ppc)+'}';
                        s = b.end;
                  }

                  FramedBox b = mainBoxes.firstElement();

                  if(parent!=null && parent.end!=b.end && s-1<b.getText().text.length())
                        code += b.getText().text.substring(Math.max(0, s), parent.end);
                  else
                        if(!(parent!=null && parent.end==b.end) && s-1<b.getText().text.length())
                              code += b.getText().text.substring(Math.max(0, s), b.getText().text.length());
            }
            else
                  return parent==null ? "" : parent.getBoxedText(); //$NON-NLS-1$

            return code;
      }





      /**
       * @return The PSTricks code of several boxes.
       */
00805       public static String getCode(Vector<FramedBox> multipleBox, DrawBorders drawBorders, float ppc)
      {
            Vector<FramedBox> boxes = new Vector<FramedBox>();

            for(FramedBox fb : multipleBox)
                  boxes.add(fb);

            return getCode(boxes, null, drawBorders, ppc);
      }




      /**
       * Allows to update the dimensions of several boxes with taking account of
       * each box to others. The method updateTextPosition of the class text must be called before.
       * @param boxes The boxes to update.
       */
00823       protected static void updateDimensions(Vector<FramedBox> boxes, Text text)
      {
            text.updateTextPosition();
            
            if(boxes==null || boxes.isEmpty())
            {
                  text.updateBorders();
                  return ;
            }
            
            Vector<FramedBox> bx    = new Vector<FramedBox>();
            Vector<FramedBox> done  = new Vector<FramedBox>();
            FramedBox fb;
            boolean found, ok;
            int size, i, j;
            double x1, x2, y1, y2, dec=0;
            Vector<TextPosition> tps;
            Rectangle2D bounds;
            TextPosition first, last;
            LaTeXDrawPoint2D[] NWs = new LaTeXDrawPoint2D[boxes.firstElement().text.text.length()];
            LaTeXDrawPoint2D[] SEs = new LaTeXDrawPoint2D[boxes.firstElement().text.text.length()];
            Vector<LaTeXDrawPoint2D> nwNotBoxSep = new Vector<LaTeXDrawPoint2D>();
            Vector<LaTeXDrawPoint2D> seNotBoxSep = new Vector<LaTeXDrawPoint2D>();
            
            for(FramedBox fb2 : boxes)
                  bx.add(fb2);
            
            while(!bx.isEmpty())
            {
                  found = false;
                  i = 0;
                  size = bx.size();
                  
                  // Looking for a box to update.
                  while(!found && i<size)
                  {
                        fb = bx.elementAt(i);
                        j = 0;
                        ok = true;
                        
                        while(j<i && ok)
                              if(fb.contains(bx.elementAt(j))==1)
                                    ok = false;
                              else j++;
                        
                        j= i+1;
                        while(j<size && ok)
                              if(fb.contains(bx.elementAt(j))==1)
                                    ok = false;
                              else j++;
                        
                        if(ok)
                              found = true;
                        else i++;
                  }
                  
                  fb = bx.remove(i);
                  
                  do
                  {
                        if(fb==null) return ;
                        
                        // Looking for the TextPositions of the current FrameBox
                        tps = new Vector<TextPosition>();
                        for(TextPosition tp2 : text.textPos)
                              if(tp2.start>=fb.start && (tp2.end+1)<=fb.end)
                                    tps.add(tp2);

                        TextLayout tl = new TextLayout(text.text.substring(fb.start, fb.end), 
                                    text.currentFont, text.fontRenderContext);
                        bounds = tl.getBounds();
                        first = tps.firstElement();
                        last  = first;
                        
                        for(j=1; j<tps.size(); j++)
                              if(tps.elementAt(j).start<first.start)
                                    first = tps.elementAt(j);
                              else if(tps.elementAt(j).end>last.end)
                                    last = tps.elementAt(j);
                        
                        LaTeXDrawPoint2D SE = null;
                        LaTeXDrawPoint2D NW = null;
                        
                        for(i=fb.start; i<fb.end; i++)
                        {
                              if(NWs[i]!=null)
                                    if(NW==null)
                                          NW = NWs[i];
                                    else if(NW.y>NWs[i].y) NW.y = NWs[i].y;
                              
                              if(SEs[i]!=null)
                                    if(SE==null)
                                          SE = SEs[i];
                                    else if(SE.y<SEs[i].y) SE.y = SEs[i].y;
                        }
                        
                        if(NW!=null && NWs[fb.start]!=null)
                              NW.x = NWs[fb.start].x;
                        else if(NW!=null) NW.x = Double.NaN;
                        
                        if(SE!=null && SEs[fb.end-1]!=null)
                              SE.x = SEs[fb.end-1].x;
                        else if(SE!=null) SE.x = Double.NaN;
                        
                        x1 = NW==null || Double.isNaN(NW.x) ? first.pos.x-fb.frameSep : NW.x-fb.frameSep;
                        x2 = SE==null || Double.isNaN(SE.x) ? last.pos.x+text.fontMetrics.stringWidth(
                                    text.text.substring(last.start, last.end+1))+fb.frameSep : SE.x+fb.frameSep;
                        y1 = NW==null ? bounds.getY()+first.pos.y-fb.frameSep : NW.y-fb.frameSep;
                        y2 = SE==null ? first.pos.y+bounds.getHeight()+bounds.getY()+fb.frameSep : SE.y+fb.frameSep;
                        
                        LaTeXDrawRectangle r = fb.box.getBorders();
                        
                        if(fb.boxType==BOX_CIRCLE)
                        {
                              double cgX = (x1+x2)/2., cgY = bounds.getCenterY()+text.position.y;
                              double radius = Math.max(Math.abs(x1-x2), Math.abs(y1-y2))/2.;

                              r.getPoint(0).setLocation(cgX-radius, cgY-radius);
                              r.getPoint(-1).setLocation(cgX+radius, cgY+radius);
                              r.getPoint(1).setLocation(cgX+radius, cgY-radius);
                              r.getPoint(2).setLocation(cgX-radius, cgY+radius);
                              ((Square)r).setWidth(radius*2);
                        }
                        else
                        {
                              r.setFirstPoint(x1, y1);
                              r.setLastPoint(x2, y2);
                              r.updateGravityCenter();

                              if(fb.boxType==BOX_ELLIPSE)
                              {
                                    LaTeXDrawPoint2D nw = r.getTheNWPoint();
                                    LaTeXDrawPoint2D cg = r.getGravityCenter();
                                    double c = Math.abs(cg.x-nw.x)*3./2.25;
                                    double a = (Math.sqrt((cg.x-nw.x+c)*(cg.x-nw.x+c)
                                                +((cg.y-nw.y)*(cg.y-nw.y)))+Math.sqrt((cg.x-nw.x-c)
                                                *(cg.x-nw.x-c)+((cg.y-nw.y)*(cg.y-nw.y))))/2.;
                                    double b = Math.sqrt(a*a-c*c);

                                    r.setFirstPoint(cg.x-a, cg.y-b);
                                    r.setLastPoint(cg.x+a, cg.y+b);
                              }
                              else
                              {
                                    LaTeXDrawPoint2D NW2 = r.getTheNWBoundPoint();
                                    LaTeXDrawPoint2D SE2 = r.getTheSEBoundPoint();
                                    LaTeXDrawPoint2D cg = r.getGravityCenter();
                                    double height = SE2.y-NW2.y, width = SE2.x-NW2.x;

                                    if(fb.boxType==BOX_DIAMOND)
                                    {
                                          double g = fb.box.getThickness()*0.707;
                                          double g2 = fb.frameSep/2.;
                                          
                                          fb.box.setBordersPosition(PSTricksConstants.BORDERS_INSIDE);
                                          r.setFirstPoint(cg.x-width-g*2+g2, cg.y-height-g*2.+g2);
                                          r.setLastPoint(cg.x+width+g*2-g2, cg.y+height+g*2.-g2);
                                    }
                                    else
                                          if(fb.boxType==BOX_TRIANGLE)
                                          {
                                                double g = fb.box.getThickness()*0.85;
                                                fb.box.setBordersPosition(PSTricksConstants.BORDERS_INSIDE);
                                                r.setFirstPoint(cg.x-width-g*2, cg.y-(height*3.)/2.-
                                                                                          fb.box.getThickness()*2+fb.frameSep);
                                                r.setLastPoint(cg.x+width+g*2, cg.y+height/2.+fb.box.getThickness());
                                          }
                              }
                        }
                        
                        fb.box.updateShape();
                        double oldNWx = NW==null ? Double.NaN : NW.x;
                        LaTeXDrawPoint2D n = fb.box.getTheNWBoundPoint(), s = fb.box.getTheSEBoundPoint();
                        
                        if(fb.isBoxSep())
                        {
                              if(NWs[fb.start]==null)
                                    NWs[fb.start]= n;
                              else 
                              {
                                    if(NWs[fb.start].x>n.x) NWs[fb.start].x = n.x;
                                    if(NWs[fb.start].y>n.y) NWs[fb.start].y = n.y;
                              }
                              
                              if(SEs[fb.end-1]==null)
                                    SEs[fb.end-1]= s;
                              else 
                              {
                                    if(SEs[fb.end-1].x<s.x) SEs[fb.end-1].x = s.x;
                                    if(SEs[fb.end-1].y<s.y) SEs[fb.end-1].y = s.y;
                              }
                        
                              if(NW==null || Double.isNaN(NW.x))
                                     dec = first.pos.x-fb.box.getTheNWBoundPoint().x;
                              else dec = oldNWx-fb.box.getTheNWBoundPoint().x;
                              
                              for(TextPosition tp2 : text.textPos)
                              {
                                    ok = true;
                                    j=0;
                                    while(ok && j<tps.size())
                                          if(tps.elementAt(j)==tp2)
                                                ok = false;
                                          else j++;
                                    
                                    if(ok)
                                          if(tp2.start<first.start)
                                                 tp2.pos.x-= dec;
                                          else tp2.pos.x+= dec;
                              }
                              
                              for(i=0; i<fb.start; i++)
                              {
                                    if(NWs[i]!=null && !Double.isNaN(NWs[i].x))
                                          NWs[i].x-=dec;
                                    if(SEs[i]!=null && !Double.isNaN(SEs[i].x))
                                          SEs[i].x-=dec;
                              }
                              
                              for(i=fb.end; i<NWs.length; i++)
                              {
                                    if(NWs[i]!=null && !Double.isNaN(NWs[i].x))
                                          NWs[i].x+=dec;
                                    if(SEs[i]!=null && !Double.isNaN(SEs[i].x))
                                          SEs[i].x+=dec;
                              }
                              
                              // we push the others boxes
                              for(FramedBox fb2 : done)
                                    if(fb.contains(fb2)!=1)
                                    {
                                          if(fb2.start<fb.start)
                                          {
                                                if(fb2.end<fb.end)
                                                      fb2.box.shift(-dec, 0);
                                          }
                                          else
                                                if(fb2.end>fb.end)
                                                      fb2.box.shift(dec, 0);
                                          fb2.box.updateShape();
                                    }
                        }//if(fb.isBoxSep())
                        else
                        {
                              nwNotBoxSep.add(n);
                              seNotBoxSep.add(s);
                        }
                        
                        done.add(fb);
                        fb = null;

                        boolean found2 = false;
                        i = 0;
                        size = bx.size();
                        while(!found2 && i<size)
                        {
                              fb = bx.elementAt(i);
                              j = 0;
                              ok = true;
                              
                              while(j<i && ok)
                                    if(fb.contains(bx.elementAt(j))==1)
                                          ok = false;
                                    else j++;
                              
                              j= i+1;
                              while(j<size && ok)
                                    if(fb.contains(bx.elementAt(j))==1)
                                          ok = false;
                                    else j++;
                              
                              if(ok)
                                    found2 = true;
                              else i++;
                        }
                        
                        if(fb==null)
                              found = false;
                        else
                              bx.remove(fb);
                  }while(found);
            }//while
            
            // We update the borders of the text.
            LaTeXDrawPoint2D NW = null, SE = null;
            size = text.text.length();
            
            for(i=0; i<size; i++)
            {
                  if(NWs[i]!=null)
                        if(NW==null)
                              NW = NWs[i];
                        else if(NW.y>NWs[i].y) NW.y = NWs[i].y;
                  
                  if(SEs[i]!=null)
                        if(SE==null)
                              SE = SEs[i];
                        else if(SE.y<SEs[i].y) SE.y = SEs[i].y;
            }
            
            if(NW!=null && NWs[0]!=null)
                  NW.x = NWs[0].x;
            else if(NW!=null) NW.x = Double.NaN;
            
            if(SE!=null && SEs[size-1]!=null)
                  SE.x = SEs[size-1].x;
            else if(SE!=null) SE.x = Double.NaN;
            
            if(!nwNotBoxSep.isEmpty())
            {
                  if(NW==null)
                        NW = new LaTeXDrawPoint2D(Double.MAX_VALUE, Double.MAX_VALUE);
                  for(LaTeXDrawPoint2D pt : nwNotBoxSep)
                  {
                        if(pt.x<NW.x)
                              NW.x = pt.x;
                        if(pt.y<NW.y)
                              NW.y = pt.y;
                  }
            }
            
            if(!seNotBoxSep.isEmpty())
            {
                  if(SE==null)
                        SE = new LaTeXDrawPoint2D(Double.MIN_VALUE, Double.MIN_VALUE);
                  for(LaTeXDrawPoint2D pt : seNotBoxSep)
                  {
                        if(pt.x>SE.x)
                              SE.x = pt.x;
                        if(pt.y>SE.y)
                              SE.y = pt.y;
                  }
            }
            
            TextLayout tl = new TextLayout(text.text, text.currentFont, text.fontRenderContext);
            bounds = tl.getBounds();
            first = text.getFirstTextPosition();
            last = text.getLastTextPosition();
            
            if(NW==null)
                  text.borders.setFirstPoint(first.pos.x, bounds.getY()+first.pos.y);
            else
                  if(Double.isNaN(NW.x))
                        text.borders.setFirstPoint(first.pos.x, NW.y);
                  else
                        text.borders.setFirstPoint(NW);
            
            if(SE==null)
                  text.borders.setLastPoint(last.pos.x+text.fontMetrics.stringWidth(
                                    text.text.substring(last.start, last.end+1)), first.pos.y+bounds.getHeight()+bounds.getY());
            else
                  if(Double.isNaN(SE.x))
                        text.borders.setLastPoint(last.pos.x+text.fontMetrics.stringWidth(
                                                      text.text.substring(last.start, last.end+1)), SE.y);
                  else
                        text.borders.setLastPoint(SE);
            
            text.gravityCenter = text.borders.getGravityCenter();
            text.updateShape();
      }




      /**
       * @return the textPosition.
       */
01190       public synchronized Vector<TextPosition> getTextPosition()
      {
            return textPosition;
      }




      /**
       * @param tp the textPosition to add.
       */
01201       public synchronized void addTextPosition(TextPosition tp)
      {
            
            textPosition.add(tp);
      }
      
      
      
      public synchronized void removeAllTextPosition()
      {
            textPosition.removeAllElements();
      }



      public boolean contains(TextPosition tp)
      {
            boolean again = true;
            int i=0, size = textPosition.size();
            
            while(again && i<size)
                  if(textPosition.elementAt(i)==tp)
                        again = false;
                  else i++;
            
            return !again;
      }
      
      
      
      public synchronized void mirrorHorizontal(LaTeXDrawPoint2D origin)
      {
            box.mirrorHorizontal(origin);
      }




      public synchronized void mirrorVertical(LaTeXDrawPoint2D origin)
      {
            box.mirrorVertical(origin);
      }
}

Generated by  Doxygen 1.6.0   Back to index