blob: 77c35930e75111cfafc6ab8452a03e1ee4b6ac7c [file] [log] [blame]
/*
* @(#)$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);
}
}