/* PlainView.java -- 
   Copyright (C) 2004, 2005, 2006  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.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;

import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentEvent.ElementChange;

public class PlainView extends View implements TabExpander
{
  Color selectedColor;
  Color unselectedColor;

  /**
   * The color that is used to draw disabled text fields.
   */
  Color disabledColor;
  
  /**
   * While painting this is the textcomponent's current start index
   * of the selection.
   */
  int selectionStart;

  /**
   * While painting this is the textcomponent's current end index
   * of the selection.
   */
  int selectionEnd;

  Font font;
  
  /** The length of the longest line in the Document **/
  float maxLineLength = -1;
  
  /** The longest line in the Document **/
  Element longestLine = null;
  
  protected FontMetrics metrics;

  /**
   * The instance returned by {@link #getLineBuffer()}.
   */
  private transient Segment lineBuffer;

  public PlainView(Element elem)
  {
    super(elem);
  }

  /**
   * @since 1.4
   */
  protected void updateMetrics()
  {
    Component component = getContainer();
    Font font = component.getFont();

    if (this.font != font)
      {
	this.font = font;
	metrics = component.getFontMetrics(font);
      }
  }
  
  /**
   * @since 1.4
   */
  protected Rectangle lineToRect(Shape a, int line)
  {
    // Ensure metrics are up-to-date.
    updateMetrics();
    
    Rectangle rect = a.getBounds();
    int fontHeight = metrics.getHeight();
    return new Rectangle(rect.x, rect.y + (line * fontHeight),
			 rect.width, fontHeight);
  }

  public Shape modelToView(int position, Shape a, Position.Bias b)
    throws BadLocationException
  {
    // Ensure metrics are up-to-date.
    updateMetrics();
    
    Document document = getDocument();

    // Get rectangle of the line containing position.
    int lineIndex = getElement().getElementIndex(position);
    Rectangle rect = lineToRect(a, lineIndex);

    // Get the rectangle for position.
    Element line = getElement().getElement(lineIndex);
    int lineStart = line.getStartOffset();
    Segment segment = getLineBuffer();
    document.getText(lineStart, position - lineStart, segment);
    int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
					       this, lineStart);

    // Calc the real rectangle.
    rect.x += xoffset;
    rect.width = 1;
    rect.height = metrics.getHeight();

    return rect;
  }
  
  /**
   * Draws a line of text. The X and Y coordinates specify the start of
   * the <em>baseline</em> of the line.
   *
   * @param lineIndex the index of the line
   * @param g the graphics to use for drawing the text
   * @param x the X coordinate of the baseline
   * @param y the Y coordinate of the baseline
   */
  protected void drawLine(int lineIndex, Graphics g, int x, int y)
  {
    try
      {
        Element line = getElement().getElement(lineIndex);
        int startOffset = line.getStartOffset();
        int endOffset = line.getEndOffset() - 1;
        
        if (selectionStart <= startOffset)
          // Selection starts before the line ...
          if (selectionEnd <= startOffset)
            {
              // end ends before the line: Draw completely unselected text.
              drawUnselectedText(g, x, y, startOffset, endOffset);
            }
          else if (selectionEnd <= endOffset)
            {
              // and ends within the line: First part is selected,
              // second is not.
              x = drawSelectedText(g, x, y, startOffset, selectionEnd);
              drawUnselectedText(g, x, y, selectionEnd, endOffset);
            }
          else
            // and ends behind the line: Draw completely selected text.
            drawSelectedText(g, x, y, startOffset, endOffset);
        else if (selectionStart < endOffset)
          // Selection starts within the line ..
          if (selectionEnd < endOffset)
            {
              // and ends within it: First part unselected, second part
              // selected, third part unselected.
              x = drawUnselectedText(g, x, y, startOffset, selectionStart);
              x = drawSelectedText(g, x, y, selectionStart, selectionEnd);
              drawUnselectedText(g, x, y, selectionEnd, endOffset);
            }
          else
            {
              // and ends behind the line: First part unselected, second
              // part selected.
              x = drawUnselectedText(g, x, y, startOffset, selectionStart);
              drawSelectedText(g, x, y, selectionStart, endOffset);
            }
        else
          // Selection is behind this line: Draw completely unselected text.
          drawUnselectedText(g, x, y, startOffset, endOffset);
      }
    catch (BadLocationException e)
    {
      AssertionError ae = new AssertionError("Unexpected bad location");
      ae.initCause(e);
      throw ae;
    }
  }

  protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
    throws BadLocationException
  {
    g.setColor(selectedColor);
    Segment segment = getLineBuffer();
    getDocument().getText(p0, p1 - p0, segment);
    return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
  }

  /**
   * Draws a chunk of unselected text.
   *
   * @param g the graphics to use for drawing the text
   * @param x the X coordinate of the baseline
   * @param y the Y coordinate of the baseline
   * @param p0 the start position in the text model
   * @param p1 the end position in the text model
   *
   * @return the X location of the end of the range
   *
   * @throws BadLocationException if <code>p0</code> or <code>p1</code> are
   *         invalid
   */
  protected int drawUnselectedText(Graphics g, int x, int y, int p0, int p1)
    throws BadLocationException
  {
    JTextComponent textComponent = (JTextComponent) getContainer();
    if (textComponent.isEnabled())
      g.setColor(unselectedColor);
    else
      g.setColor(disabledColor);

    Segment segment = getLineBuffer();
    getDocument().getText(p0, p1 - p0, segment);
    return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
  }

  public void paint(Graphics g, Shape s)
  {
    // Ensure metrics are up-to-date.
    updateMetrics();
    
    JTextComponent textComponent = (JTextComponent) getContainer();

    selectedColor = textComponent.getSelectedTextColor();
    unselectedColor = textComponent.getForeground();
    disabledColor = textComponent.getDisabledTextColor();
    selectionStart = textComponent.getSelectionStart();
    selectionEnd = textComponent.getSelectionEnd();

    Rectangle rect = s.getBounds();

    // FIXME: Text may be scrolled.
    Document document = textComponent.getDocument();
    Element root = document.getDefaultRootElement();
    int y = rect.y + metrics.getAscent();
    int height = metrics.getHeight();
    
    int count = root.getElementCount();
    for (int i = 0; i < count; i++)
      {
        drawLine(i, g, rect.x, y);
        y += height;
      }
  }

  /**
   * Returns the tab size of a tab.  Checks the Document's
   * properties for PlainDocument.tabSizeAttribute and returns it if it is
   * defined, otherwise returns 8.
   * 
   * @return the tab size.
   */
  protected int getTabSize()
  {
    Object tabSize = getDocument().getProperty(PlainDocument.tabSizeAttribute);
    if (tabSize == null)
      return 8;
    return ((Integer)tabSize).intValue();
  }

  /**
   * Returns the next tab stop position after a given reference position.
   *
   * This implementation ignores the <code>tabStop</code> argument.
   * 
   * @param x the current x position in pixels
   * @param tabStop the position within the text stream that the tab occured at
   */
  public float nextTabStop(float x, int tabStop)
  {
    float tabSizePixels = getTabSize() * metrics.charWidth('m');
    return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
  }

  /**
   * Returns the length of the longest line, used for getting the span
   * @return the length of the longest line
   */
  float determineMaxLineLength()
  {
    // if the longest line is cached, return the cached value
    if (maxLineLength != -1)
      return maxLineLength;
    
    // otherwise we have to go through all the lines and find it
    Element el = getElement();
    Segment seg = getLineBuffer();
    float span = 0;
    for (int i = 0; i < el.getElementCount(); i++)
      {
        Element child = el.getElement(i);
        int start = child.getStartOffset();
        int end = child.getEndOffset() - 1;
        try
          {
            el.getDocument().getText(start, end - start, seg);
          }
        catch (BadLocationException ex)
          {
            AssertionError ae = new AssertionError("Unexpected bad location");
	    ae.initCause(ex);
	    throw ae;
          }
        
        if (seg == null || seg.array == null || seg.count == 0)
          continue;
        
        int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
        if (width > span)
          {
            longestLine = child;
            span = width;
          }
      }
    maxLineLength = span;
    return maxLineLength;
  }
  
  public float getPreferredSpan(int axis)
  {
    if (axis != X_AXIS && axis != Y_AXIS)
      throw new IllegalArgumentException();

    // make sure we have the metrics
    updateMetrics();

    Element el = getElement();
    float span;

    switch (axis)
      {
      case X_AXIS:
        span = determineMaxLineLength();
        break;
      case Y_AXIS:
      default:
        span = metrics.getHeight() * el.getElementCount();
        break;
      }
    
    return span;
  }

  /**
   * Maps coordinates from the <code>View</code>'s space into a position
   * in the document model.
   *
   * @param x the x coordinate in the view space
   * @param y the y coordinate in the view space
   * @param a the allocation of this <code>View</code>
   * @param b the bias to use
   *
   * @return the position in the document that corresponds to the screen
   *         coordinates <code>x, y</code>
   */
  public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
  {
    Rectangle rec = a.getBounds();
    Document doc = getDocument();
    Element root = doc.getDefaultRootElement();
    
    // PlainView doesn't support line-wrapping so we can find out which
    // Element was clicked on just by the y-position.    
    // Since the coordinates may be outside of the coordinate space
    // of the allocation area (e.g. user dragged mouse outside
    // the component) we have to limit the values.
    // This has the nice effect that the user can drag the
    // mouse above or below the component and it will still
    // react to the x values (e.g. when selecting).
    int lineClicked
      = Math.min(Math.max((int) (y - rec.y) / metrics.getHeight(), 0),
                          root.getElementCount() - 1);
    
    Element line = root.getElement(lineClicked);
    
    Segment s = getLineBuffer();
    int start = line.getStartOffset();
    // We don't want the \n at the end of the line.
    int end = line.getEndOffset() - 1;
    try
      {
        doc.getText(start, end - start, s);
      }
    catch (BadLocationException ble)
      {
        AssertionError ae = new AssertionError("Unexpected bad location");
        ae.initCause(ble);
        throw ae;
      }
    
    int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start);
    return Math.max (0, pos);
  }     
  
  /**
   * Since insertUpdate and removeUpdate each deal with children
   * Elements being both added and removed, they both have to perform
   * the same checks.  So they both simply call this method.
   * @param changes the DocumentEvent for the changes to the Document.
   * @param a the allocation of the View.
   * @param f the ViewFactory to use for rebuilding.
   */
  protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f)
  {
    // This happens during initialization.
    if (metrics == null)
      {
        updateMetrics();
        preferenceChanged(null, true, true);
        return;
      }

    Element element = getElement();

    // Find longest line if it hasn't been initialized yet.
    if (longestLine == null)
      findLongestLine(0, element.getElementCount() - 1);

    ElementChange change = changes.getChange(element);
    if (changes.getType() == DocumentEvent.EventType.INSERT)
      {
        // Handles character/line insertion.

        // Determine if lines have been added. In this case we repaint
        // differently.
        boolean linesAdded = true;
        if (change == null)
          linesAdded = false;

        // Determine the start line.
        int start;
        if (linesAdded)
          start = change.getIndex();
        else
          start = element.getElementIndex(changes.getOffset());

        // Determine the length of the updated region.
        int length = 0;
        if (linesAdded)
          length = change.getChildrenAdded().length - 1;

        // Update the longest line and length.
        int oldMaxLength = (int) maxLineLength;
        if (longestLine.getEndOffset() < changes.getOffset()
            || longestLine.getStartOffset() > changes.getOffset()
                                             + changes.getLength())
          {
            findLongestLine(start, start + length);
          }
        else
          {
            findLongestLine(0, element.getElementCount() - 1);
          }

        // Trigger a preference change so that the layout gets updated
        // correctly.
        preferenceChanged(null, maxLineLength != oldMaxLength, linesAdded);

        // Damage the updated line range.
        int endLine = start;
        if (linesAdded)
          endLine = element.getElementCount() - 1;
        damageLineRange(start, endLine, a, getContainer());

      }
    else
      {
        // Handles character/lines removals.

        // Update the longest line and length and trigger preference changed.
        int oldMaxLength = (int) maxLineLength;
        if (change != null)
          {
            // Line(s) have been removed.
            findLongestLine(0, element.getElementCount() - 1);
            preferenceChanged(null, maxLineLength != oldMaxLength, true);
          }
        else
          {
            // No line has been removed.
            int lineNo = getElement().getElementIndex(changes.getOffset());
            Element line = getElement().getElement(lineNo);
            if (longestLine == line)
              {
                findLongestLine(0, element.getElementCount() - 1);
                preferenceChanged(null, maxLineLength != oldMaxLength, false);
            }
            damageLineRange(lineNo, lineNo, a, getContainer());
        }
      }
  }

  /**
   * This method is called when something is inserted into the Document
   * that this View is displaying.
   * 
   * @param changes the DocumentEvent for the changes.
   * @param a the allocation of the View
   * @param f the ViewFactory used to rebuild
   */
  public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f)
  {
    updateDamage(changes, a, f);
  }

  /**
   * This method is called when something is removed from the Document
   * that this View is displaying.
   * 
   * @param changes the DocumentEvent for the changes.
   * @param a the allocation of the View
   * @param f the ViewFactory used to rebuild
   */
  public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f)
  {
    updateDamage(changes, a, f);
  }
  
  /**
   * This method is called when attributes were changed in the 
   * Document in a location that this view is responsible for.
   */
  public void changedUpdate (DocumentEvent changes, Shape a, ViewFactory f)
  {
    updateDamage(changes, a, f);
  }
  
  /**
   * Repaint the given line range.  This is called from insertUpdate,
   * changedUpdate, and removeUpdate when no new lines were added 
   * and no lines were removed, to repaint the line that was 
   * modified.
   * 
   * @param line0 the start of the range
   * @param line1 the end of the range
   * @param a the rendering region of the host
   * @param host the Component that uses this View (used to call repaint
   * on that Component)
   * 
   * @since 1.4
   */
  protected void damageLineRange (int line0, int line1, Shape a, Component host)
  {
    if (a == null)
      return;

    Rectangle rec0 = lineToRect(a, line0);
    Rectangle rec1 = lineToRect(a, line1);

    if (rec0 == null || rec1 == null)
      // something went wrong, repaint the entire host to be safe
      host.repaint();
    else
      {
        Rectangle repaintRec = SwingUtilities.computeUnion(rec0.x, rec0.y,
                                                           rec0.width,
                                                           rec0.height, rec1);
        host.repaint(repaintRec.x, repaintRec.y, repaintRec.width,
                     repaintRec.height);
      }    
  }

  /**
   * Provides a {@link Segment} object, that can be used to fetch text from
   * the document.
   *
   * @returna {@link Segment} object, that can be used to fetch text from
   *          the document
   */
  protected final Segment getLineBuffer()
  {
    if (lineBuffer == null)
      lineBuffer = new Segment();
    return lineBuffer;
  }

  /**
   * Finds and updates the longest line in the view inside an interval of
   * lines.
   *
   * @param start the start of the search interval
   * @param end the end of the search interval
   */
  private void findLongestLine(int start, int end)
  {
    for (int i = start; i <= end; i++)
      {
        int w = getLineLength(i);
        if (w > maxLineLength)
          {
            maxLineLength = w;
            longestLine = getElement().getElement(i);
          }
      }
  }

  /**
   * Determines the length of the specified line.
   *
   * @param line the number of the line
   *
   * @return the length of the line in pixels
   */
  private int getLineLength(int line)
  {
    Element lineEl = getElement().getElement(line);
    Segment buffer = getLineBuffer();
    try
      {
        Document doc = getDocument();
        doc.getText(lineEl.getStartOffset(),
                    lineEl.getEndOffset() - lineEl.getStartOffset() - 1,
                    buffer);
      }
    catch (BadLocationException ex)
      {
        AssertionError err = new AssertionError("Unexpected bad location");
        err.initCause(ex);
        throw err;
      }

    return Utilities.getTabbedTextWidth(buffer, metrics, 0, this,
                                        lineEl.getStartOffset());
  }
}

