2 * (C) Copyright IBM Corp. 1998-2004. All Rights Reserved.
\r
4 * The program is provided "as is" without any warranty express or
\r
5 * implied, including the warranty of non-infringement and the implied
\r
6 * warranties of merchantibility and fitness for a particular purpose.
\r
7 * IBM will not be liable for any damages suffered by you as a result
\r
8 * of using the Program. In no event will IBM be liable for any
\r
9 * special, indirect or consequential damages or lost profits even if
\r
10 * IBM has been advised of the possibility of their occurrence. IBM
\r
11 * will not be liable for any third party claims against you.
\r
14 package com.ibm.richtext.textformat;
\r
16 import java.awt.Color;
\r
17 import java.awt.Graphics;
\r
18 import java.awt.Point;
\r
19 import java.awt.Rectangle;
\r
21 import com.ibm.richtext.styledtext.MConstText;
\r
22 import com.ibm.richtext.textlayout.attributes.AttributeMap;
\r
26 * This class formats lines of text to a given length.
\r
27 * It provides services needed for static text display,
\r
28 * and also editable text, including: displaying text,
\r
29 * reformatting text after an edit, converting between
\r
30 * screen locations and offsets into the text, calculating
\r
31 * areas of the screen for "highlighting," and computing
\r
32 * offsets into the text resulting from arrow keys.
\r
34 * Text clients instantiate this class with an
\r
35 * <tt>MConstText</tt> object and a format width. Text
\r
36 * can be formatted such that all lines fit within the
\r
37 * format length. Alternatively, text can be formatted
\r
38 * such that lines end only at the end of paragraphs.
\r
40 * The format length is specified with the <tt>setLineBound()</tt>
\r
43 * Methods in the formatter which interact with the graphics
\r
44 * system generally take as a paramter a <tt>Point</tt> object
\r
45 * which represents the "origin" of the text display. The
\r
46 * origin represents the location, in the graphics system used to display the text, of
\r
47 * the top-left corner of the text.
\r
49 * To display the text, call <tt>draw()</tt>, passing the
\r
50 * a rectangle in which to draw as a parameter. Only lines
\r
51 * of text in the draw rectangle will be drawn.
\r
53 * When the formatter's text changes, it is important to first call
\r
54 * <tt>stopBackgroundFormatting()</tt> to prevent the Formatter from
\r
55 * accessing the text from a background thread. After modifications are
\r
57 * call the <tt>updateFormat()</tt> method before invoking any other
\r
58 * methods of the formatter. <tt>updateFormat()</tt> reformats the
\r
59 * new text, formatting no more text than is necessary.
\r
61 * The formatter provides services for responding to user input from the
\r
62 * mouse and keyboard. The method <tt>pointToTextOffset()</tt> converts
\r
63 * a screen location to an offset in the text. The method <tt>textOffsetToPoint</tt>
\r
64 * converts an offset in the text to an array of two <tt>Point</tt> objects, which can be
\r
65 * used to draw a verticle caret, denoting an insertion point. <tt>highlightArea</tt>
\r
66 * accepts two offsets into the text as paramters, and returns an array of <tt>Polygon</tt>
\r
67 * objects representing areas where visual highlighting should be applied.
\r
70 * keyboard handling, the <tt>findNewInsertionOffset()</tt> method accepts an "initial"
\r
71 * offset, a "previous" offset, as well as a direction, and returns a new offset. The direction
\r
72 * can be up, down, left, or right. The previous offset is the insertion point location, before
\r
73 * the arrow key is processed. The initial offset is the offset where an up or down arrow
\r
74 * key sequence began. Using the initial offset allows for "intelligent" handling of up and down
\r
77 * Examples of using the MFormatter class
\r
78 * are given in the <tt>AsyncFormatter</tt> class
\r
81 * @author John Raley
\r
83 * @see com.ibm.richtext.styledtext.MText
\r
86 public abstract class MFormatter {
\r
87 static final String COPYRIGHT =
\r
88 "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
\r
90 public abstract AttributeMap getDefaultValues();
\r
93 * Display text in drawArea, with highlighting.
\r
94 * Does not reformat text
\r
95 * @param g the Graphics object in which to draw
\r
96 * @param drawArea the rectangle, in g's coordinate system, in which to draw
\r
97 * @param origin the top-left corner of the text, in g's coordinate system
\r
98 * @param selStart the offset where the current selection begins; pass <tt>null</tt> if no selection
\r
99 * @param selStop the offset where the current selection ends
\r
100 * @param highlight the color of the highlighting
\r
102 public abstract void draw(Graphics g, Rectangle drawArea, Point origin,
\r
103 TextOffset selStart, TextOffset selStop, Color highlight);
\r
105 public abstract void draw(Graphics g, Rectangle drawArea, Point origin);
\r
108 * Specify whether to wrap line at the edge of the destination area.
\r
109 * <tt>true</tt> means wrap lines; <tt>false</tt> means to break lines
\r
110 * only when an end-of-line character is reached.
\r
111 * @param wrap <tt>true</tt> to break lines at the edge of the destination
\r
112 * area; <tt>false</tt> otherwise.
\r
115 public abstract void setWrap(boolean wrap);
\r
118 * Return whether text is wrapped at the edge of the destination area.
\r
121 public abstract boolean wrap();
\r
124 * Specify the number of pixels along the "line dimension".
\r
125 * Lines are formatted to fit within the line dimension. The
\r
126 * line dimension in Roman script is horizontal.
\r
127 * @param lineBound the length, in pixels, to which lines will be formatted
\r
129 public abstract void setLineBound(int lineBound);
\r
132 * Return the number of pixels along the line dimension.
\r
133 * @return the number of pixels along the line dimension.
\r
135 public abstract int lineBound();
\r
138 * Format text down to given height.
\r
139 * @param height the height to which text will be formatted
\r
141 public abstract void formatToHeight(int height);
\r
144 * Reformat text after a change.
\r
145 * After the formatter's text changes, call this method to reformat. Does
\r
147 * @param afStart the offset into the text where modification began; ie, the
\r
148 * first character in the text which is "different" in some way. Does not
\r
149 * have to be nonnegative.
\r
150 * @param afLength the number of new or changed characters in the text. Should never
\r
152 * @param viewRect the Rectangle in which the text will be displayed. This is needed for
\r
153 * returning the "damaged" area - the area of the screen in which the text must be redrawn.
\r
154 * @param origin the top-left corner of the text, in the display's coordinate system
\r
155 * @return a <tt>Rectangle</tt> which specifies the area in which text must be
\r
156 * redrawn to reflect the change to the text.
\r
158 public abstract Rectangle updateFormat(int afStart,
\r
160 Rectangle viewRect,
\r
164 public abstract int minY();
\r
167 * Return the maximum vertical coordinate of the document area.
\r
169 public abstract int maxY();
\r
171 public abstract int minX();
\r
174 * Return the maximum horizontal coordinate of the document area.
\r
176 public abstract int maxX();
\r
179 * Return the actual pixel length of the text which has been formatted.
\r
181 public abstract int formattedHeight();
\r
183 public static final short eUp = -10, eDown = 10, eLeft = -1, eRight = 1;
\r
186 * Given a screen location p, return the offset of the character in the text nearest to p.
\r
188 * The offset may or may not include a newline at the end of a line, determined by anchor and infiniteMode.
\r
189 * The newline is not included if infiniteMode is true and the anchor is the position before the newline.
\r
191 * @param result TextOffset to modify and return. If null, one will be allocated, modified, and returned.
\r
192 * @param px the x component of the point.
\r
193 * @param py the y component of the point.
\r
194 * @param origin the top-left corner of the text, in the display's coordinate system
\r
195 * @param anchor the previous offset. May be null. Used to determine whether newlines are included.
\r
196 * @param infiniteMode if true, treat newlines at end of line as having infinite width.
\r
198 public abstract TextOffset pointToTextOffset(TextOffset result, int px, int py, Point origin, TextOffset anchor, boolean infiniteMode);
\r
201 * Given an offset, return the Rectangle bounding the caret at the offset.
\r
202 * @param offset an offset into the text
\r
203 * @param origin the top-left corner of the text, in the display's coordinate system
\r
204 * @return a Rectangle bounding the caret.
\r
206 public abstract Rectangle getCaretRect(TextOffset offset, Point origin);
\r
209 * Draw the caret(s) associated with the given offset into the given Graphics.
\r
210 * @param g the Graphics to draw into
\r
211 * @param offset the offset in the text for which the caret is drawn
\r
212 * @param origin the top-left corner of the text, in the display's coordinate system
\r
213 * @param strongCaretColor the color of the strong caret
\r
214 * @param weakCaretColor the color of the weak caret (if any)
\r
216 public abstract void drawCaret(Graphics g,
\r
219 Color strongCaretColor,
\r
220 Color weakCaretColor);
\r
223 * @see #getBoundingRect
\r
225 public static final boolean LOOSE = false;
\r
227 * @see #getBoundingRect
\r
229 public static final boolean TIGHT = true;
\r
232 * Given two offsets in the text, return a rectangle which encloses the lines containing the offsets.
\r
233 * Offsets do not need to be ordered or nonnegative.
\r
234 * @param offset1 an offset into the text
\r
235 * @param offset2 the other offset into the text
\r
236 * @param origin the top-left corner of the text, in the display's coordinate system
\r
237 * @param tight if equal to TIGHT, the bounds is as small as possible. If LOOSE, the width
\r
238 * of the bounds is allowed to be wider than necesary. Loose bounds are easier to compute.
\r
239 * @return a <tt>Rectangle</tt>, relative to <tt>origin</tt>, which encloses the lines containing the offsets
\r
241 public abstract Rectangle getBoundingRect(TextOffset offset1,
\r
242 TextOffset offset2,
\r
246 public abstract void getBoundingRect(Rectangle boundingRect,
\r
247 TextOffset offset1,
\r
248 TextOffset offset2,
\r
253 * Compute the offset resulting from moving from a previous offset in direction dir.
\r
255 * @param previousOffset the insertion offset prior to the arrow key press
\r
256 * @param direction the direction of the arrow key (eUp, eDown, eLeft, or eRight)
\r
257 * @return new offset based on direction and previous offset.
\r
259 public abstract TextOffset findInsertionOffset(TextOffset result,
\r
260 TextOffset previousOffset,
\r
264 * Compute the offset resulting from moving from a previous offset, starting at an original offset, in direction dir.
\r
265 * For arrow keys. Use this for "smart" up/down keys.
\r
266 * @param result TextOffset to modify and return. If null, a new TextOffset is created, modified, and returned.
\r
267 * @param initialOffset The offset at which an up-down arrow key sequence began.
\r
268 * @param previousOffset The insertion offset prior to the arrow key press.
\r
269 * @param direction The direction of the arrow key (eUp, eDown, eLeft, or eRight)
\r
270 * @return new offset based on direction and previous offset(s).
\r
272 public abstract TextOffset findNewInsertionOffset(TextOffset result,
\r
273 TextOffset initialOffset,
\r
274 TextOffset previousOffset,
\r
278 * Return the index of the line containing the given character index.
\r
279 * This method has complicated semantics, arising from not knowing
\r
280 * which side of the index to check. The index will be given an
\r
281 * implicit AFTER bias, unless the index is the last index in the text,
\r
282 * the text length is non-zero, and there is not a paragraph separator
\r
283 * at the end of the text.
\r
285 public abstract int lineContaining(int index);
\r
288 * Return the index of the line containing the given offset.
\r
290 public abstract int lineContaining(TextOffset offset);
\r
293 * Return the number of lines.
\r
295 public abstract int getLineCount();
\r
298 * Return the index of the first character on the given line.
\r
300 public abstract int lineRangeLow(int lineNumber);
\r
303 * Return the index of the first character following the given line.
\r
305 public abstract int lineRangeLimit(int lineNumber);
\r
308 * Tells the formatter to stop accessing the text until updateFormat is called.
\r
310 public abstract void stopBackgroundFormatting();
\r
313 * Return the line number at the given graphic height. If height is greater than
\r
314 * the text height, maxLineNumber + 1 is returned.
\r
316 public abstract int lineAtHeight(int height);
\r
319 * Return the graphic height where the given line begins. If the lineNumber is
\r
320 * maxLineNumber the entire text height is returned.
\r
322 public abstract int lineGraphicStart(int lineNumber);
\r
325 * Return true if the given line is left-to-right.
\r
326 * @param lineNumber a valid line
\r
327 * @return true if lineNumber is left-to-right
\r
329 public abstract boolean lineIsLeftToRight(int lineNumber);
\r
332 * Return a new <tt>MFormatter</tt>.
\r
333 * @param text the text to format
\r
334 * @param defaultValues values to use when certain attributes are not specified.
\r
335 * <tt>defaultValues</tt> must contain values for the following attributes:
\r
336 * <tt>FAMILY</tt>, <tt>WEIGHT</tt>, <tt>POSTURE</tt>, <tt>SIZE</tt>, <tt>SUPERSCRIPT</tt>,
\r
337 * <tt>FOREGROUND</tt>, <tt>UNDERLINE</tt>, <tt>STRIKETHROUGH</tt>,
\r
338 * <tt>EXTRA_LINE_SPACING</tt>, <tt>FIRST_LINE_INDENT</tt>,<tt>MIN_LINE_SPACING</tt>,
\r
339 * <tt>LINE_FLUSH</tt>, <tt>LEADING_MARGIN</tt>, <tt>TRAILING_MARGIN</tt>, <tt>TAB_RULER</tt>
\r
340 * @param lineBound length to which lines are formatted
\r
341 * @param wrap <tt>true</tt> if text should be "line wrapped" (formatted to fit destination area)
\r
343 public static MFormatter createFormatter(MConstText text,
\r
344 AttributeMap defaultValues,
\r
349 return new AsyncFormatter(text, defaultValues, lineBound, wrap, g);
\r