mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			529 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			529 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* ParagraphView.java -- A composite View
 | |
|    Copyright (C) 2005  Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath 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, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| 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.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| 
 | |
| package javax.swing.text;
 | |
| 
 | |
| import java.awt.Shape;
 | |
| 
 | |
| import javax.swing.SizeRequirements;
 | |
| import javax.swing.event.DocumentEvent;
 | |
| 
 | |
| /**
 | |
|  * A {@link FlowView} that flows it's children horizontally and boxes the rows
 | |
|  * vertically.
 | |
|  *
 | |
|  * @author Roman Kennke (roman@kennke.org)
 | |
|  */
 | |
| public class ParagraphView extends FlowView implements TabExpander
 | |
| {
 | |
|   /**
 | |
|    * A specialized horizontal <code>BoxView</code> that represents exactly
 | |
|    * one row in a <code>ParagraphView</code>.
 | |
|    */
 | |
|   class Row extends BoxView
 | |
|   {
 | |
|     /**
 | |
|      * Creates a new instance of <code>Row</code>.
 | |
|      */
 | |
|     Row(Element el)
 | |
|     {
 | |
|       super(el, X_AXIS);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Overridden to adjust when we are the first line, and firstLineIndent
 | |
|      * is not 0.
 | |
|      */
 | |
|     public short getLeftInset()
 | |
|     {
 | |
|       short leftInset = super.getLeftInset();
 | |
|       View parent = getParent();
 | |
|       if (parent != null)
 | |
|         {
 | |
|           if (parent.getView(0) == this)
 | |
|             leftInset += firstLineIndent;
 | |
|         }
 | |
|       return leftInset;
 | |
|     }
 | |
| 
 | |
|     public float getAlignment(int axis)
 | |
|     {
 | |
|       float align;
 | |
|       if (axis == X_AXIS)
 | |
|         switch (justification)
 | |
|           {
 | |
|           case StyleConstants.ALIGN_RIGHT:
 | |
|             align = 1.0F;
 | |
|             break;
 | |
|           case StyleConstants.ALIGN_CENTER:
 | |
|           case StyleConstants.ALIGN_JUSTIFIED:
 | |
|             align = 0.5F;
 | |
|             break;
 | |
|           case StyleConstants.ALIGN_LEFT:
 | |
|           default:
 | |
|             align = 0.0F;
 | |
|           }
 | |
|       else
 | |
|         align = super.getAlignment(axis);
 | |
|       return align;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Overridden because child views are not necessarily laid out in model
 | |
|      * order.
 | |
|      */
 | |
|     protected int getViewIndexAtPosition(int pos)
 | |
|     {
 | |
|       int index = -1;
 | |
|       if (pos >= getStartOffset() && pos < getEndOffset())
 | |
|         {
 | |
|           int nviews = getViewCount();
 | |
|           for (int i = 0; i < nviews && index == -1; i++)
 | |
|             {
 | |
|               View child = getView(i);
 | |
|               if (pos >= child.getStartOffset() && pos < child.getEndOffset())
 | |
|                 index = i;
 | |
|             }
 | |
|         }
 | |
|       return index;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * Overridden to perform a baseline layout. The normal BoxView layout
 | |
|      * isn't completely suitable for rows.
 | |
|      */
 | |
|     protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
 | |
|                                    int[] spans)
 | |
|     {
 | |
|       baselineLayout(targetSpan, axis, offsets, spans);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Overridden to perform a baseline layout. The normal BoxView layout
 | |
|      * isn't completely suitable for rows.
 | |
|      */
 | |
|     protected SizeRequirements calculateMinorAxisRequirements(int axis,
 | |
|                                                             SizeRequirements r)
 | |
|     {
 | |
|       return baselineRequirements(axis, r);
 | |
|     }
 | |
| 
 | |
|     protected void loadChildren(ViewFactory vf)
 | |
|     {
 | |
|       // Do nothing here. The children are added while layouting.
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Overridden to determine the minimum start offset of the row's children.
 | |
|      */
 | |
|     public int getStartOffset()
 | |
|     {
 | |
|       // Determine minimum start offset of the children.
 | |
|       int offset = Integer.MAX_VALUE;
 | |
|       int n = getViewCount();
 | |
|       for (int i = 0; i < n; i++)
 | |
|         {
 | |
|           View v = getView(i);
 | |
|           offset = Math.min(offset, v.getStartOffset());
 | |
|         }
 | |
|       return offset;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Overridden to determine the maximum end offset of the row's children.
 | |
|      */
 | |
|     public int getEndOffset()
 | |
|     {
 | |
|       // Determine minimum start offset of the children.
 | |
|       int offset = 0;
 | |
|       int n = getViewCount();
 | |
|       for (int i = 0; i < n; i++)
 | |
|         {
 | |
|           View v = getView(i);
 | |
|           offset = Math.max(offset, v.getEndOffset());
 | |
|         }
 | |
|       return offset;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * The indentation of the first line of the paragraph.
 | |
|    */
 | |
|   protected int firstLineIndent;
 | |
| 
 | |
|   /**
 | |
|    * The justification of the paragraph.
 | |
|    */
 | |
|   private int justification;
 | |
| 
 | |
|   /**
 | |
|    * The line spacing of this paragraph.
 | |
|    */
 | |
|   private float lineSpacing;
 | |
| 
 | |
|   /**
 | |
|    * The TabSet of this paragraph.
 | |
|    */
 | |
|   private TabSet tabSet;
 | |
| 
 | |
|   /**
 | |
|    * Creates a new <code>ParagraphView</code> for the given
 | |
|    * <code>Element</code>.
 | |
|    *
 | |
|    * @param element the element that is rendered by this ParagraphView
 | |
|    */
 | |
|   public ParagraphView(Element element)
 | |
|   {
 | |
|     super(element, Y_AXIS);
 | |
|   }
 | |
| 
 | |
|   public float nextTabStop(float x, int tabOffset)
 | |
|   {
 | |
|     throw new InternalError("Not implemented yet");
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Creates a new view that represents a row within a flow.
 | |
|    *
 | |
|    * @return a view for a new row
 | |
|    */
 | |
|   protected View createRow()
 | |
|   {
 | |
|     return new Row(getElement());
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the alignment for this paragraph view for the specified axis.
 | |
|    * For the X_AXIS the paragraph view will be aligned at it's left edge
 | |
|    * (0.0F). For the Y_AXIS the paragraph view will be aligned at the
 | |
|    * center of it's first row.
 | |
|    *
 | |
|    * @param axis the axis which is examined
 | |
|    *
 | |
|    * @return the alignment for this paragraph view for the specified axis
 | |
|    */
 | |
|   public float getAlignment(int axis)
 | |
|   {
 | |
|     float align;
 | |
|     if (axis == X_AXIS)
 | |
|       align = 0.5F;
 | |
|     else if (getViewCount() > 0)
 | |
|       {
 | |
|         float prefHeight = getPreferredSpan(Y_AXIS);
 | |
|         float firstRowHeight = getView(0).getPreferredSpan(Y_AXIS);
 | |
|         align = (firstRowHeight / 2.F) / prefHeight;
 | |
|       }
 | |
|     else
 | |
|       align = 0.5F;
 | |
|     return align;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Receives notification when some attributes of the displayed element
 | |
|    * changes. This triggers a refresh of the cached attributes of this
 | |
|    * paragraph.
 | |
|    *
 | |
|    * @param ev the document event
 | |
|    * @param a the allocation of this view
 | |
|    * @param vf the view factory to use for creating new child views
 | |
|    */
 | |
|   public void changedUpdate(DocumentEvent ev, Shape a, ViewFactory vf)
 | |
|   {
 | |
|     setPropertiesFromAttributes();
 | |
|     layoutChanged(X_AXIS);
 | |
|     layoutChanged(Y_AXIS);
 | |
|     super.changedUpdate(ev, a, vf);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Fetches the cached properties from the element's attributes.
 | |
|    */
 | |
|   protected void setPropertiesFromAttributes()
 | |
|   {
 | |
|     Element el = getElement();
 | |
|     AttributeSet atts = el.getAttributes();
 | |
|     setFirstLineIndent(StyleConstants.getFirstLineIndent(atts));
 | |
|     setLineSpacing(StyleConstants.getLineSpacing(atts));
 | |
|     setJustification(StyleConstants.getAlignment(atts));
 | |
|     tabSet = StyleConstants.getTabSet(atts);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the indentation of the first line of the paragraph.
 | |
|    *
 | |
|    * @param i the indentation to set
 | |
|    */
 | |
|   protected void setFirstLineIndent(float i)
 | |
|   {
 | |
|     firstLineIndent = (int) i;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the justification of the paragraph.
 | |
|    *
 | |
|    * @param j the justification to set
 | |
|    */
 | |
|   protected void setJustification(int j)
 | |
|   {
 | |
|     justification = j;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Sets the line spacing for this paragraph.
 | |
|    *
 | |
|    * @param s the line spacing to set
 | |
|    */
 | |
|   protected void setLineSpacing(float s)
 | |
|   {
 | |
|     lineSpacing = s;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the i-th view from the logical views, before breaking into rows.
 | |
|    *
 | |
|    * @param i the index of the logical view to return
 | |
|    *
 | |
|    * @return the i-th view from the logical views, before breaking into rows
 | |
|    */
 | |
|   protected View getLayoutView(int i)
 | |
|   {
 | |
|     return layoutPool.getView(i);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the number of logical child views.
 | |
|    *
 | |
|    * @return the number of logical child views
 | |
|    */
 | |
|   protected int getLayoutViewCount()
 | |
|   {
 | |
|     return layoutPool.getViewCount();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the TabSet used by this ParagraphView.
 | |
|    *
 | |
|    * @return the TabSet used by this ParagraphView
 | |
|    */
 | |
|   protected TabSet getTabSet()
 | |
|   {
 | |
|     return tabSet;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Finds the next offset in the document that has one of the characters
 | |
|    * specified in <code>string</code>. If there is no such character found,
 | |
|    * this returns -1.
 | |
|    *
 | |
|    * @param string the characters to search for
 | |
|    * @param start the start offset
 | |
|    *
 | |
|    * @return the next offset in the document that has one of the characters
 | |
|    *         specified in <code>string</code>
 | |
|    */
 | |
|   protected int findOffsetToCharactersInString(char[] string, int start)
 | |
|   {
 | |
|     int offset = -1;
 | |
|     Document doc = getDocument();
 | |
|     Segment text = new Segment();
 | |
|     try
 | |
|       {
 | |
|         doc.getText(start, doc.getLength() - start, text);
 | |
|         int index = start;
 | |
| 
 | |
|         searchLoop:
 | |
|         while (true)
 | |
|           {
 | |
|             char ch = text.next();
 | |
|             if (ch == Segment.DONE)
 | |
|               break;
 | |
| 
 | |
|             for (int j = 0; j < string.length; ++j)
 | |
|               {
 | |
|                 if (string[j] == ch)
 | |
|                   {
 | |
|                     offset = index;
 | |
|                     break searchLoop;
 | |
|                   }
 | |
|               }
 | |
|             index++;
 | |
|           }
 | |
|       }
 | |
|     catch (BadLocationException ex)
 | |
|       {
 | |
|         // Ignore this and return -1.
 | |
|       }
 | |
|     return offset;
 | |
|   }
 | |
| 
 | |
|   protected int getClosestPositionTo(int pos, Position.Bias bias, Shape a,
 | |
|                                      int direction, Position.Bias[] biasRet,
 | |
|                                      int rowIndex, int x)
 | |
|     throws BadLocationException
 | |
|   {
 | |
|     // FIXME: Implement this properly. However, this looks like it might
 | |
|     // have been replaced by viewToModel.
 | |
|     return pos;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the size that is used by this view (or it's child views) between
 | |
|    * <code>startOffset</code> and <code>endOffset</code>. If the child views
 | |
|    * implement the {@link TabableView} interface, then this is used to
 | |
|    * determine the span, otherwise we use the preferred span of the child
 | |
|    * views.
 | |
|    *
 | |
|    * @param startOffset the start offset
 | |
|    * @param endOffset the end offset
 | |
|    *
 | |
|    * @return the span used by the view between <code>startOffset</code> and
 | |
|    *         <code>endOffset</cod>
 | |
|    */
 | |
|   protected float getPartialSize(int startOffset, int endOffset)
 | |
|   {
 | |
|     int startIndex = getViewIndex(startOffset, Position.Bias.Backward);
 | |
|     int endIndex = getViewIndex(endOffset, Position.Bias.Forward);
 | |
|     float span;
 | |
|     if (startIndex == endIndex)
 | |
|       {
 | |
|         View child = getView(startIndex);
 | |
|         if (child instanceof TabableView)
 | |
|           {
 | |
|             TabableView tabable = (TabableView) child;
 | |
|             span = tabable.getPartialSpan(startOffset, endOffset);
 | |
|           }
 | |
|         else
 | |
|           span = child.getPreferredSpan(X_AXIS);
 | |
|       }
 | |
|     else if (endIndex - startIndex == 1)
 | |
|       {
 | |
|         View child1 = getView(startIndex);
 | |
|         if (child1 instanceof TabableView)
 | |
|           {
 | |
|             TabableView tabable = (TabableView) child1;
 | |
|             span = tabable.getPartialSpan(startOffset, child1.getEndOffset());
 | |
|           }
 | |
|         else
 | |
|           span = child1.getPreferredSpan(X_AXIS);
 | |
|         View child2 = getView(endIndex);
 | |
|         if (child2 instanceof TabableView)
 | |
|           {
 | |
|             TabableView tabable = (TabableView) child2;
 | |
|             span += tabable.getPartialSpan(child2.getStartOffset(), endOffset);
 | |
|           }
 | |
|         else
 | |
|           span += child2.getPreferredSpan(X_AXIS);
 | |
|       }
 | |
|     else
 | |
|       {
 | |
|         // Start with the first view.
 | |
|         View child1 = getView(startIndex);
 | |
|         if (child1 instanceof TabableView)
 | |
|           {
 | |
|             TabableView tabable = (TabableView) child1;
 | |
|             span = tabable.getPartialSpan(startOffset, child1.getEndOffset());
 | |
|           }
 | |
|         else
 | |
|           span = child1.getPreferredSpan(X_AXIS);
 | |
| 
 | |
|         // Add up the view spans between the start and the end view.
 | |
|         for (int i = startIndex + 1; i < endIndex; i++)
 | |
|           {
 | |
|             View child = getView(i);
 | |
|             span += child.getPreferredSpan(X_AXIS);
 | |
|           }
 | |
| 
 | |
|         // Add the span of the last view.
 | |
|         View child2 = getView(endIndex);
 | |
|         if (child2 instanceof TabableView)
 | |
|           {
 | |
|             TabableView tabable = (TabableView) child2;
 | |
|             span += tabable.getPartialSpan(child2.getStartOffset(), endOffset);
 | |
|           }
 | |
|         else
 | |
|           span += child2.getPreferredSpan(X_AXIS);
 | |
|       }
 | |
|     return span;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the location where the tabs are calculated from. This returns
 | |
|    * <code>0.0F</code> by default.
 | |
|    *
 | |
|    * @return the location where the tabs are calculated from
 | |
|    */
 | |
|   protected float getTabBase()
 | |
|   {
 | |
|     return 0.0F;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @specnote This method is specified to take a Row parameter, which is a
 | |
|    *           private inner class of that class, which makes it unusable from
 | |
|    *           application code. Also, this method seems to be replaced by
 | |
|    *           {@link FlowStrategy#adjustRow(FlowView, int, int, int)}.
 | |
|    *
 | |
|    */
 | |
|   protected void adjustRow(Row r, int desiredSpan, int x)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @specnote This method's signature differs from the one defined in
 | |
|    *           {@link View} and is therefore never called. It is probably there
 | |
|    *           for historical reasons.
 | |
|    */
 | |
|   public View breakView(int axis, float len, Shape a)
 | |
|   {
 | |
|     // This method is not used.
 | |
|     return null;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * @specnote This method's signature differs from the one defined in
 | |
|    *           {@link View} and is therefore never called. It is probably there
 | |
|    *           for historical reasons.
 | |
|    */
 | |
|   public int getBreakWeight(int axis, float len)
 | |
|   {
 | |
|     // This method is not used.
 | |
|     return 0;
 | |
|   }
 | |
| }
 |