/*
 * @(#)$RCSfile: MFormatter.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:50:03 $
 *
 * (C) Copyright IBM Corp. 1998-1999.  All Rights Reserved.
 *
 * The program is provided "as is" without any warranty express or
 * implied, including the warranty of non-infringement and the implied
 * warranties of merchantibility and fitness for a particular purpose.
 * IBM will not be liable for any damages suffered by you as a result
 * of using the Program. In no event will IBM be liable for any
 * special, indirect or consequential damages or lost profits even if
 * IBM has been advised of the possibility of their occurrence. IBM
 * will not be liable for any third party claims against you.
 */

package com.ibm.richtext.textformat;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;

import com.ibm.richtext.styledtext.MConstText;
import com.ibm.textlayout.attributes.AttributeMap;

/**
*
* This class formats lines of text to a given length.
* It provides services needed for static text display,
* and also editable text, including:  displaying text,
* reformatting text after an edit, converting between
* screen locations and offsets into the text, calculating
* areas of the screen for "highlighting,"  and computing
* offsets into the text resulting from arrow keys.
* <p>
* Text clients instantiate this class with an
* <tt>MConstText</tt> object and a format width.  Text
* can be formatted such that all lines fit within the
* format length.  Alternatively, text can be formatted
* such that lines end only at the end of paragraphs.
* <p>
* The format length is specified with the <tt>setLineBound()</tt>
* method.
* <p>
* Methods in the formatter which interact with the graphics
* system generally take as a paramter a <tt>Point</tt> object
* which represents the "origin" of the text display.  The
* origin represents the location, in the graphics system used to display the text, of
* the top-left corner of the text.
* <p>
* To display the text, call <tt>draw()</tt>, passing the
* a rectangle in which to draw as a parameter.  Only lines
* of text in the draw rectangle will be drawn.
* <p>
* When the formatter's text changes, it is important to first call
* <tt>stopBackgroundFormatting()</tt> to prevent the Formatter from
* accessing the text from a background thread.  After modifications are
* complete,
* call the <tt>updateFormat()</tt> method before invoking any other
* methods of the formatter.  <tt>updateFormat()</tt> reformats the
* new text, formatting no more text than is necessary.
* <p>
* The formatter provides services for responding to user input from the
* mouse and keyboard.  The method <tt>pointToTextOffset()</tt> converts
* a screen location to an offset in the text.  The method <tt>textOffsetToPoint</tt>
* converts an offset in the text to an array of two <tt>Point</tt> objects, which can be
* used to draw a verticle caret, denoting an insertion point.  <tt>highlightArea</tt>
* accepts two offsets into the text as paramters, and returns an array of <tt>Polygon</tt>
* objects representing areas where visual highlighting should be applied.
* <p>
* Finally, for
* keyboard handling, the <tt>findNewInsertionOffset()</tt> method accepts an "initial"
* offset, a "previous" offset, as well as a direction, and returns a new offset.  The direction
* can be up, down, left, or right.  The previous offset is the insertion point location, before
* the arrow key is processed.  The initial offset is the offset where an up or down arrow
* key sequence began.  Using the initial offset allows for "intelligent" handling of up and down
* arrow keys.
* <p>
* Examples of using the MFormatter class
* are given in the <tt>AsyncFormatter</tt> class
* documentation.
* <p>
* @author John Raley
*
* @see MText
*/

public abstract class MFormatter {
    static final String COPYRIGHT =
                "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";

    public abstract AttributeMap getDefaultValues();

/**
* Display text in drawArea, with highlighting.
* Does not reformat text
* @param g the Graphics object in which to draw
* @param drawArea the rectangle, in g's coordinate system, in which to draw
* @param origin the top-left corner of the text, in g's coordinate system
* @param selStart the offset where the current selection begins;  pass <tt>null</tt> if no selection
* @param selStop the offset where the current selection ends
* @param highlight the color of the highlighting
*/
    public abstract void draw(Graphics g, Rectangle drawArea, Point origin,
            TextOffset selStart, TextOffset selStop, Color highlight);

    public abstract void draw(Graphics g, Rectangle drawArea, Point origin);

/**
* Specify whether to wrap line at the edge of the destination area.
* <tt>true</tt> means wrap lines;  <tt>false</tt> means to break lines
* only when an end-of-line character is reached.
* @param wrap <tt>true</tt> to break lines at the edge of the destination
* area;  <tt>false</tt> otherwise.
*/

    public abstract void setWrap(boolean wrap);

/**
* Return whether text is wrapped at the edge of the destination area.
* @see #setWrap
*/
    public abstract boolean wrap();

/**
* Specify the number of pixels along the "line dimension".
* Lines are formatted to fit within the line dimension.  The
* line dimension in Roman script is horizontal.
* @param lineWidth the length, in pixels, to which lines will be formatted
*/
    public abstract void setLineBound(int lineBound);

/**
* Return the number of pixels along the line dimension.
*/
    public abstract int lineBound();
    
/**
* Format text down to given height.
* @param height the height to which text will be formatted
*/
    public abstract void formatToHeight(int height);

/**
* Reformat text after a change.
* After the formatter's text changes, call this method to reformat.  Does
* not redraw.
* @param afStart the offset into the text where modification began;  ie, the
* first character in the text which is "different" in some way.  Does not
* have to be nonnegative.
* @param afLength the number of new or changed characters in the text.  Should never
* be less than 0.
* @param viewRect the Rectangle in which the text will be displayed.  This is needed for
* returning the "damaged" area - the area of the screen in which the text must be redrawn.
* @param origin the top-left corner of the text, in the display's coordinate system
* @returns a <tt>Rectangle</tt> which specifies the area in which text must be
* redrawn to reflect the change to the text.
*/
    public abstract Rectangle updateFormat(int afStart,
                                  int afLength,
                                  Rectangle viewRect,
                                  Point origin);


    public abstract int minY();
    
/**
 * Return the maximum vertical coordinate of the document area.
 */
    public abstract int maxY();

    public abstract int minX();

/**
 * Return the maximum horizontal coordinate of the document area.
 */
    public abstract int maxX();

/**
* Return the actual pixel length of the text which has been formatted.
*/
    public abstract int formattedHeight();

    public static final short eUp = -10, eDown = 10, eLeft = -1, eRight = 1;

/**
* Given a screen location p, return the offset of the character in the text nearest to p.
*
* The offset may or may not include a newline at the end of a line, determined by anchor and infiniteMode.
* The newline is not included if infiniteMode is true and the anchor is the position before the newline.
*
* @param result TextOffset to modify and return.  If null, one will be allocated, modified, and returned.
* @param px the x component of the point.
* @param py the y component of the point.
* @param origin the top-left corner of the text, in the display's coordinate system
* @param anchor the previous offset.  May be null.  Used to determine whether newlines are included.
* @param infiniteMode if true, treat newlines at end of line as having infinite width.
*/
    public abstract TextOffset pointToTextOffset(TextOffset result, int px, int py, Point origin, TextOffset anchor, boolean infiniteMode);

/**
* Given an offset, return the Rectangle bounding the caret at the offset.
* @param offset an offset into the text
* @param origin the top-left corner of the text, in the display's coordinate system
* @return a Rectangle bounding the caret.
*/
    public abstract Rectangle getCaretRect(TextOffset offset, Point origin);

/**
* Draw the caret(s) associated with the given offset into the given Graphics.
* @param g the Graphics to draw into
* @param offset the offset in the text for which the caret is drawn
* @param origin the top-left corner of the text, in the display's coordinate system
* @param strongCaretColor the color of the strong caret
* @param weakCaretColor the color of the weak caret (if any)
*/
    public abstract void drawCaret(Graphics g,
                                   TextOffset offset,
                                   Point origin,
                                   Color strongCaretColor,
                                   Color weakCaretColor);

    /**
     * @see #getBoundingRect
     */
    public static final boolean LOOSE = false;
    /**
     * @see #getBoundingRect
     */
    public static final boolean TIGHT = true;

/**
* Given two offsets in the text, return a rectangle which encloses the lines containing the offsets.
* Offsets do not need to be ordered or nonnegative.
* @param offset1,offset2 offsets into the text
* @param origin the top-left corner of the text, in the display's coordinate system
* @param tight if equal to TIGHT, the bounds is as small as possible.  If LOOSE, the width
* of the bounds is allowed to be wider than necesary.  Loose bounds are easier to compute.
* @returns a <tt>Rectangle</tt>, relative to <tt>origin</tt>, which encloses the lines containing the offsets
*/
    public abstract Rectangle getBoundingRect(TextOffset offset1,
                                              TextOffset offset2, 
                                              Point origin,
                                              boolean tight);

    public abstract void getBoundingRect(Rectangle boundingRect,
                                         TextOffset offset1,
                                         TextOffset offset2,
                                         Point origin,
                                         boolean tight);

/**
* Compute the offset resulting from moving from a previous offset in direction dir.
* For arrow keys.
* @param previousOffset the insertion offset prior to the arrow key press
* @param direction the direction of the arrow key (eUp, eDown, eLeft, or eRight)
* @returns new offset based on direction and previous offset.
*/
    public abstract TextOffset findInsertionOffset(TextOffset result,
                                          TextOffset previousOffset,
                                          short direction);

/**
* Compute the offset resulting from moving from a previous offset, starting at an original offset, in direction dir.
* For arrow keys.  Use this for "smart" up/down keys.
* @param result TextOffset to modify and return.  If null, a new TextOffset is created, modified, and returned.
* @param initialOffset The offset at which an up-down arrow key sequence began.
* @param previousOffset The insertion offset prior to the arrow key press.
* @param direction The direction of the arrow key (eUp, eDown, eLeft, or eRight)
* @returns new offset based on direction and previous offset(s).
*/
    public abstract TextOffset findNewInsertionOffset(TextOffset result,
                                             TextOffset initialOffset,
                                             TextOffset previousOffset,
                                             short direction);

/**
* Return the index of the line containing the given character index.
* This method has complicated semantics, arising from not knowing 
* which side of the index to check.  The index will be given an
* implicit AFTER bias, unless the index is the last index in the text,
* the text length is non-zero, and there is not a paragraph separator
* at the end of the text.
*/
    public abstract int lineContaining(int index);
    
/**
* Return the index of the line containing the given offset.
*/
    public abstract int lineContaining(TextOffset offset);

/**
* Return the number of lines.
*/
    public abstract int getLineCount();

/**
* Return the index of the first character on the given line.
*/
    public abstract int lineRangeLow(int lineNumber);

/**
* Return the index of the first character following the given line.
*/
    public abstract int lineRangeLimit(int lineNumber);

/**
* Tells the formatter to stop accessing the text until updateFormat is called.
*/
    public abstract void stopBackgroundFormatting();

/**
* Return the line number at the given graphic height.  If height is greater than
* the text height, maxLineNumber + 1 is returned.
*/
    public abstract int lineAtHeight(int height);

/**
* Return the graphic height where the given line begins.  If the lineNumber is
* maxLineNumber the entire text height is returned.
*/
    public abstract int lineGraphicStart(int lineNumber);

/**
* Return true if the given line is left-to-right.
* @param lineNumber a valid line
* @return true if lineNumber is left-to-right
*/
    public abstract boolean lineIsLeftToRight(int lineNumber);

/**
* Return a new <tt>MFormatter</tt>.
* @param text the text to format
* @param defaultValues values to use when certain attributes are not specified. 
*    <tt>defaultValues</tt> must contain values for the following attributes:
*    <tt>FAMILY</tt>, <tt>WEIGHT</tt>, <tt>POSTURE</tt>, <tt>SIZE</tt>, <tt>SUPERSCRIPT</tt>, 
*    <tt>FOREGROUND</tt>, <tt>UNDERLINE</tt>, <tt>STRIKETHROUGH</tt>,
*    <tt>EXTRA_LINE_SPACING</tt>, <tt>FIRST_LINE_INDENT</tt>,<tt>MIN_LINE_SPACING</tt>,
*    <tt>LINE_FLUSH</tt>, <tt>LEADING_MARGIN</tt>, <tt>TRAILING_MARGIN</tt>, <tt>TAB_RULER</tt>
* @param lineBound length to which lines are formatted
* @param wrap <tt>true</tt> if text should be "line wrapped" (formatted to fit destination area)
*/
    public static MFormatter createFormatter(MConstText text,
                                             AttributeMap defaultValues,
                                             int lineBound, 
                                             boolean wrap, 
                                             Graphics g) {
                                                
        return new AsyncFormatter(text, defaultValues, lineBound, wrap, g);
    }
}
