2 * (C) Copyright IBM Corp. 1998-2007. 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
13 package com.ibm.richtext.textpanel;
\r
15 import java.awt.Color;
\r
16 import java.awt.Component;
\r
17 import java.awt.Graphics;
\r
18 import java.awt.Image;
\r
19 import java.awt.Point;
\r
20 import java.awt.Rectangle;
\r
22 import java.awt.event.ComponentAdapter;
\r
23 import java.awt.event.FocusListener;
\r
24 import java.awt.event.KeyListener;
\r
25 import java.awt.event.MouseListener;
\r
26 import java.awt.event.MouseMotionListener;
\r
28 import java.awt.event.ComponentEvent;
\r
29 import java.awt.event.FocusEvent;
\r
30 import java.awt.event.KeyEvent;
\r
31 import java.awt.event.MouseEvent;
\r
33 import com.ibm.richtext.styledtext.MConstText;
\r
34 import com.ibm.richtext.styledtext.MText;
\r
35 import com.ibm.richtext.textformat.TextOffset;
\r
37 import com.ibm.richtext.textformat.MFormatter;
\r
39 import com.ibm.richtext.textlayout.attributes.AttributeMap;
\r
41 class TextComponent extends FakeComponent
\r
42 implements BehaviorOwner,
\r
46 MouseMotionListener,
\r
49 static final String COPYRIGHT =
\r
50 "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
\r
52 public static final int WINDOW_WIDTH = -10;
\r
53 public static final int DEFAULT_INSET = 10;
\r
55 private static final Color STRONG_CARET_COLOR = Color.black;
\r
56 private static final Color WEAK_CARET_COLOR = Color.darkGray;
\r
58 private Behavior fBehavior;
\r
59 private MText fText;
\r
60 private StyledTextClipboard fClipboard;
\r
61 private boolean fScrolls;
\r
62 private Scroller fScroller;
\r
64 private DocumentView fDocumentView = null;
\r
66 // sigh - can't create DocumentView until addNotify() is called.
\r
67 // These values hold DocumentView ctor args
\r
68 private AttributeMap fDefaultValues;
\r
69 private boolean fViewWraps;
\r
70 private int fViewWrapWidth;
\r
71 private int fViewInsetAmount;
\r
73 private PanelEventBroadcaster fListener;
\r
76 * Create a new TextComponent.
\r
77 * @param text the text model. This model will be used for
\r
78 * the life of the component, even if setText is called
\r
79 * @param wraps if true, the text is wrapped to the specified
\r
80 * wrapping width. If false, the text wraps only at paragraph breaks.
\r
81 * @param wrapWidth ignored if wraps is false. Text wraps to this width
\r
82 * unless the width is WINDOW_WIDTH, in which case text wraps to width
\r
83 * of this component. Should not be negative (unless it is WINDOW_WIDTH).
\r
84 * @param insetAmount the size of the margins around the text
\r
85 * @param clipboard the clipboard to use for cut/copy/paste operations.
\r
86 * If null, the component will use its own clipboard.
\r
88 public TextComponent(MText text,
\r
89 AttributeMap defaultValues,
\r
93 StyledTextClipboard clipboard,
\r
96 PanelEventBroadcaster listener) {
\r
100 if (text == null) {
\r
101 throw new IllegalArgumentException("Text is null.");
\r
105 fDefaultValues = defaultValues;
\r
107 if (clipboard == null) {
\r
108 throw new IllegalArgumentException("Clipboard is null.");
\r
110 fClipboard = clipboard;
\r
112 fScrolls = scrolls;
\r
114 fScroller = scroller;
\r
116 fDocumentView = null;
\r
118 fViewWrapWidth = wrapWidth;
\r
119 fViewWraps = wraps;
\r
120 fViewInsetAmount = insetAmount;
\r
121 fListener = listener;
\r
124 AttributeMap getDefaultValues() {
\r
126 return fDefaultValues;
\r
129 void setHost(Component component) {
\r
131 super.setHost(component);
\r
133 component.addFocusListener(this);
\r
134 component.addKeyListener(this);
\r
135 component.addMouseListener(this);
\r
136 component.addMouseMotionListener(this);
\r
138 component.addComponentListener(new ComponentAdapter() {
\r
139 public void componentResized(ComponentEvent e) {
\r
140 if (fDocumentView != null) {
\r
141 fDocumentView.hostSizeChanged();
\r
142 scrollToShow(fDocumentView.getDocumentBounds());
\r
149 * ATextPanelImpl's use only!
\r
151 Component getHost() {
\r
156 // Create document view here. TextComponent isn't fully constructed
\r
157 // until this is called.
\r
158 // This must be called by host component!
\r
161 Graphics g = getGraphics();
\r
163 throw new Error("Graphics should be valid here but isn't.");
\r
166 fDocumentView = new DocumentView(this,
\r
173 documentSizeChanged();
\r
174 fListener.textStateChanged(TextPanelEvent.FORMAT_WIDTH_CHANGED);
\r
177 public Rectangle getBounds() {
\r
179 if (fHost != null) {
\r
180 return fHost.getBounds();
\r
182 return new Rectangle(0, 0, 0, 0);
\r
185 Graphics getGraphics() {
\r
187 return (fHost==null)? null : fHost.getGraphics();
\r
190 void requestFocus() {
\r
192 if (fHost != null) {
\r
193 fHost.requestFocus();
\r
197 // *** Behavior management ***
\r
198 public Behavior getBehavior() {
\r
202 public void setBehavior(Behavior b) {
\r
207 // *** Events - just forward to behavior ***
\r
208 public void focusGained(FocusEvent event) {
\r
209 if (fBehavior != null)
\r
210 fBehavior.focusGained(event);
\r
213 public void focusLost(FocusEvent event) {
\r
214 if (fBehavior != null)
\r
215 fBehavior.focusLost(event);
\r
218 public void keyPressed(KeyEvent event) {
\r
219 if (fBehavior != null)
\r
220 fBehavior.keyPressed(event);
\r
223 public void keyTyped(KeyEvent event) {
\r
225 if (fBehavior != null) {
\r
226 fBehavior.keyTyped(event);
\r
230 public void keyReleased(KeyEvent event) {
\r
231 if (fBehavior != null)
\r
232 fBehavior.keyReleased(event);
\r
235 public void mouseClicked(MouseEvent event) {
\r
236 // no behavior method for this
\r
239 public void mouseDragged(MouseEvent event) {
\r
240 if (fBehavior != null)
\r
241 fBehavior.mouseDragged(event);
\r
244 public void mouseEntered(MouseEvent event) {
\r
245 if (fBehavior != null)
\r
246 fBehavior.mouseEntered(event);
\r
249 public void mouseExited(MouseEvent event) {
\r
250 if (fBehavior != null)
\r
251 fBehavior.mouseExited(event);
\r
254 public void mouseMoved(MouseEvent event) {
\r
255 if (fBehavior != null)
\r
256 fBehavior.mouseMoved(event);
\r
259 public void mousePressed(MouseEvent event) {
\r
260 if (fBehavior != null)
\r
261 fBehavior.mousePressed(event);
\r
264 public void mouseReleased(MouseEvent event) {
\r
265 if (fBehavior != null)
\r
266 fBehavior.mouseReleased(event);
\r
269 public boolean textControlEventOccurred(Behavior.EventType event, Object what) {
\r
271 boolean handled = false;
\r
273 if (fBehavior != null) {
\r
274 handled = fBehavior.textControlEventOccurred(event, what);
\r
280 // *** Scroll methods - called by Behaviors
\r
282 // viewStart, viewLimit is visible bounds of window
\r
283 // targetStart, targetLimit is the region to scroll into view
\r
284 private static int getScrollDifference(int viewStart,
\r
289 if (viewStart <= targetStart) {
\r
290 if (viewLimit >= targetLimit) {
\r
293 return Math.max(viewStart-targetStart, viewLimit-targetLimit);
\r
295 else if (viewLimit > targetLimit) {
\r
297 return viewLimit - targetLimit;
\r
304 void scrollToShow(Rectangle showRect) {
\r
306 if (fDocumentView != null) {
\r
307 Rectangle bounds = getBounds();
\r
309 int dx = getScrollDifference(showRect.x, showRect.x + showRect.width,
\r
310 bounds.x, bounds.x + bounds.width);
\r
311 int dy = getScrollDifference(showRect.y, showRect.y + showRect.height,
\r
312 bounds.y, bounds.y + bounds.height);
\r
314 scrollSelf(dx, dy);
\r
318 void scrollToShow(int showX, int showY) {
\r
320 if (fDocumentView != null) {
\r
321 int dx = 0, dy = 0;
\r
323 Rectangle bounds = getBounds();
\r
324 if (showX < bounds.x) {
\r
325 dx = showX - bounds.x;
\r
327 else if (showX > bounds.x + bounds.width) {
\r
328 dx = showX - (bounds.x + bounds.width);
\r
331 if (showY < bounds.y) {
\r
332 dy = showY - bounds.y;
\r
334 else if (showY > bounds.y + bounds.height) {
\r
335 dy = showY - (bounds.y + bounds.height);
\r
338 scrollSelf(dx, dy);
\r
342 private int pinScrollOffset(int delta,
\r
349 int viewLimit = viewStart + viewLength;
\r
350 int contentLimit = contentStart + contentLength;
\r
352 if (viewLimit + delta > contentLimit) {
\r
353 delta = Math.max(0, contentLimit-viewLimit);
\r
357 if (viewStart + delta < contentStart) {
\r
358 delta = Math.min(0, contentStart-viewStart);
\r
365 private void scrollSelf(int dx, int dy) {
\r
367 boolean scrolled = scrollBy(dx, dy);
\r
369 if (scrolled && fScroller != null) {
\r
370 Rectangle documentBounds = fDocumentView.getDocumentBounds();
\r
371 fScroller.setPosition(-documentBounds.x,
\r
372 -documentBounds.y);
\r
376 private synchronized boolean scrollBy(int dx, int dy) {
\r
378 boolean scrolled = false;
\r
381 Rectangle documentBounds = fDocumentView.getDocumentBounds();
\r
382 Rectangle viewBounds = getBounds();
\r
384 // variable not used int oldDx = dx;
\r
385 dx = pinScrollOffset(dx,
\r
387 documentBounds.width,
\r
390 dy = pinScrollOffset(dy,
\r
392 documentBounds.height,
\r
394 viewBounds.height);
\r
396 if (dx != 0 || dy != 0) {
\r
398 fDocumentView.moveBy(-dx, -dy);
\r
405 // implementation of Scroller.Client - called by Scroller
\r
406 // they have to be public since they're in an interface
\r
407 // no one else should call these methods
\r
408 public Rectangle getScrollSize() {
\r
410 if (fDocumentView != null) {
\r
411 return fDocumentView.getScrollableArea();
\r
413 return new Rectangle(0, 0, 0, 0);
\r
416 public void scrollTo(int x, int y) {
\r
418 if (fDocumentView != null) {
\r
419 scrollBy(x + fDocumentView.getDocX(), y + fDocumentView.getDocY());
\r
423 // *** Text access ***
\r
424 MConstText getText() {
\r
428 MText getModifiableText() {
\r
432 StyledTextClipboard getClipboard() {
\r
436 public synchronized void paint(Graphics g) {
\r
438 if (fDocumentView != null) {
\r
439 fDocumentView.paint(g);
\r
444 // *** Metric info - used by Behaviors
\r
445 Rectangle getCaretRect(TextOffset offset) {
\r
447 if (fDocumentView != null) {
\r
448 return fDocumentView.getCaretRect(offset);
\r
450 return new Rectangle(0, 0);
\r
453 TextOffset pointToTextOffset(TextOffset result,
\r
457 boolean infiniteMode) {
\r
459 if (fDocumentView != null) {
\r
460 return fDocumentView.pointToTextOffset(result, x, y, anchor, infiniteMode);
\r
462 return new TextOffset();
\r
465 // *** Other stuff used by Behaviors - mostly formatter exports
\r
466 int lineContaining(TextOffset offset) {
\r
468 if (fDocumentView != null) {
\r
469 return fDocumentView.lineContaining(offset);
\r
474 int lineRangeLow(int lineNumber) {
\r
476 if (fDocumentView != null) {
\r
477 return fDocumentView.lineRangeLow(lineNumber);
\r
482 int lineRangeLimit(int lineNumber) {
\r
484 if (fDocumentView != null) {
\r
485 return fDocumentView.lineRangeLimit(lineNumber);
\r
490 void stopBackgroundFormatting() {
\r
492 if (fDocumentView != null) {
\r
493 fDocumentView.stopBackgroundFormatting();
\r
497 Rectangle getBoundingRect(TextOffset offset1, TextOffset offset2) {
\r
499 if (fDocumentView != null) {
\r
500 return fDocumentView.getBoundingRect(offset1, offset2);
\r
502 return new Rectangle(0, 0, 0, 0);
\r
505 synchronized void reformatAndDrawText(int reformatStart,
\r
506 int reformatLength,
\r
507 TextOffset selStart,
\r
509 Rectangle additionalUpdateRect,
\r
510 Color hiliteColor) {
\r
512 if (fDocumentView != null) {
\r
513 fDocumentView.reformatAndDrawText(reformatStart,
\r
517 additionalUpdateRect,
\r
522 TextOffset findNewInsertionOffset(TextOffset result,
\r
523 TextOffset initialOffset,
\r
524 TextOffset previousOffset,
\r
527 if (fDocumentView != null) {
\r
528 return fDocumentView.findNewInsertionOffset(result, initialOffset, previousOffset, direction);
\r
530 return new TextOffset(initialOffset);
\r
533 synchronized void drawText(Graphics g,
\r
534 Rectangle damagedRect,
\r
535 boolean selectionVisible,
\r
536 TextOffset selStart,
\r
538 Color hiliteColor) {
\r
540 if (fDocumentView != null) {
\r
541 fDocumentView.drawText(g, damagedRect, selectionVisible, selStart, selEnd, hiliteColor);
\r
545 private void documentSizeChanged() {
\r
547 if (fScroller != null) {
\r
548 fScroller.clientScrollSizeChanged();
\r
552 int getFormatWidth() {
\r
554 if (fDocumentView != null) {
\r
555 return fDocumentView.getFormatWidth();
\r
561 * Return true if the paragraph at the given offset is left-to-right.
\r
562 * @param offset an offset in the text
\r
563 * @return true if the paragraph at the given offset is left-to-right
\r
565 boolean paragraphIsLeftToRight(int offset) {
\r
567 if (fDocumentView != null) {
\r
568 return fDocumentView.paragraphIsLeftToRight(offset);
\r
573 private static final class DocumentView {
\r
575 private TextComponent fHost;
\r
576 private boolean fWrapToWindowWidth;
\r
577 private int fInsetAmount;
\r
578 private PanelEventBroadcaster fListener;
\r
580 // fBounds is the total scrollable area of the document (including insets)
\r
581 private Rectangle fBounds = new Rectangle();
\r
583 private Point fOrigin;
\r
585 private MFormatter fFormatter;
\r
587 private OffscreenBufferCache fBufferCache;
\r
589 // Note, when this is true the caret won't blink in 1.1. Looks like an AWT bug.
\r
590 private static boolean fNoOffscreenBuffer =
\r
591 Boolean.getBoolean("TextComponent.NoOffscreenBuffer");
\r
593 // Amount by which to reduce the format width to allow for right-aligned carets.
\r
594 private final int CARET_SLOP = 1;
\r
596 DocumentView(TextComponent host,
\r
598 AttributeMap defaultValues,
\r
602 PanelEventBroadcaster listener) {
\r
605 fWrapToWindowWidth = wrapWidth == WINDOW_WIDTH;
\r
606 fInsetAmount = insetAmount;
\r
607 fListener = listener;
\r
609 initFormatterAndSize(text, defaultValues, wraps, wrapWidth);
\r
611 fBufferCache = new OffscreenBufferCache(host.fHost);
\r
615 * Note: this computes the bounds rectangle relative to fOrigin
\r
617 private void calcBoundsRect() {
\r
619 final int insetDim = 2 * fInsetAmount;
\r
621 final int minX = fFormatter.minX();
\r
622 final int minY = fFormatter.minY();
\r
624 fBounds.setBounds(fOrigin.x + minX - fInsetAmount,
\r
625 fOrigin.y + minY - fInsetAmount,
\r
626 fFormatter.maxX() - minX + insetDim,
\r
627 fFormatter.maxY() - minY + insetDim);
\r
629 // System.out.println("calcBoundsRect: minX="+minX+
\r
630 // "; bounds.x="+fBounds.x+"; width="+fBounds.width);
\r
634 private void initFormatterAndSize(MConstText text,
\r
635 AttributeMap defaultValues,
\r
639 Rectangle hostBounds = fHost.getBounds();
\r
642 if (!wraps || fWrapToWindowWidth) {
\r
643 formatWidth = hostBounds.width - 2 * fInsetAmount;
\r
644 if (formatWidth <= CARET_SLOP) {
\r
645 formatWidth = CARET_SLOP+1;
\r
649 formatWidth = wrapWidth;
\r
652 fFormatter = MFormatter.createFormatter(text,
\r
654 formatWidth-CARET_SLOP,
\r
656 fHost.getGraphics());
\r
658 fFormatter.formatToHeight(hostBounds.height * 2);
\r
659 fOrigin = new Point(fInsetAmount, fInsetAmount);
\r
663 // notification method called by TextComponent
\r
664 void hostSizeChanged() {
\r
666 final boolean wrap = fFormatter.wrap();
\r
667 if (fWrapToWindowWidth || !wrap) {
\r
669 Rectangle hostBounds = fHost.getBounds();
\r
670 // variable not used final int insetDim = 2 * fInsetAmount;
\r
672 int formatWidth = hostBounds.width - 2*fInsetAmount;
\r
673 if (formatWidth <= CARET_SLOP) {
\r
674 formatWidth = CARET_SLOP+1;
\r
676 fFormatter.setLineBound(formatWidth-CARET_SLOP);
\r
678 fFormatter.formatToHeight(hostBounds.y + (hostBounds.height*2) - fOrigin.y);
\r
682 //System.out.println("Window bounds="+hostBounds+"; document bounds="+fBounds);
\r
684 fHost.documentSizeChanged();
\r
685 fListener.textStateChanged(TextPanelEvent.FORMAT_WIDTH_CHANGED);
\r
686 //System.out.println("formatWidth="+formatWidth);
\r
687 //System.out.println("document bounds="+fBounds);
\r
688 //System.out.println();
\r
693 int getFormatWidth() {
\r
695 return fFormatter.lineBound();
\r
698 boolean paragraphIsLeftToRight(int offset) {
\r
700 int lineNumber = fFormatter.lineContaining(offset);
\r
701 return fFormatter.lineIsLeftToRight(lineNumber);
\r
704 private void textSizeMightHaveChanged() {
\r
706 boolean changed = false;
\r
707 final int insetDim = 2 * fInsetAmount;
\r
709 int textHeight = fFormatter.maxY() - fFormatter.minY() + insetDim;
\r
710 if (textHeight != fBounds.height) {
\r
711 fBounds.height = textHeight;
\r
715 if (!fFormatter.wrap()) {
\r
716 int textWidth = fFormatter.maxX() - fFormatter.minX() + insetDim;
\r
717 if (textWidth != fBounds.width) {
\r
718 fBounds.width = textWidth;
\r
724 //System.out.println("Text size changed. fBounds: " + fBounds);
\r
726 fHost.documentSizeChanged();
\r
727 fHost.scrollToShow(getDocumentBounds());
\r
731 private void doDrawText(Graphics g,
\r
732 Rectangle drawRect,
\r
733 boolean selectionVisible,
\r
734 TextOffset selStart,
\r
736 Color hiliteColor) {
\r
738 Color oldColor = g.getColor();
\r
739 g.setColor(fHost.getHost().getBackground());
\r
740 g.fillRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
\r
741 g.setColor(oldColor);
\r
743 // g.clearRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
\r
745 if (selectionVisible) {
\r
746 fFormatter.draw(g, drawRect, fOrigin, selStart, selEnd, hiliteColor);
\r
749 fFormatter.draw(g, drawRect, fOrigin, null, null, null);
\r
752 if (selStart != null && selStart.equals(selEnd) && selectionVisible) {
\r
754 fFormatter.drawCaret(g, selStart, fOrigin,
\r
755 STRONG_CARET_COLOR, WEAK_CARET_COLOR);
\r
759 void drawText(Graphics g,
\r
760 Rectangle drawRect,
\r
761 boolean selectionVisible,
\r
762 TextOffset selStart,
\r
764 Color hiliteColor) {
\r
767 drawRect = drawRect.intersection(fHost.getBounds());
\r
768 //System.out.println("drawText:drawRect: " + drawRect);
\r
769 g.clipRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height);
\r
770 if (fNoOffscreenBuffer) {
\r
771 doDrawText(g, drawRect, selectionVisible, selStart, selEnd, hiliteColor);
\r
774 Image offscreenBuffer = fBufferCache.getBuffer(drawRect.width, drawRect.height);
\r
775 Graphics offscreenGraphics = offscreenBuffer.getGraphics();
\r
776 offscreenGraphics.translate(-drawRect.x, -drawRect.y);
\r
778 doDrawText(offscreenGraphics, drawRect, selectionVisible, selStart, selEnd, hiliteColor);
\r
780 g.drawImage(offscreenBuffer, drawRect.x, drawRect.y, fHost.fHost);
\r
783 textSizeMightHaveChanged();
\r
786 void reformatAndDrawText(int reformatStart,
\r
787 int reformatLength,
\r
788 TextOffset selStart,
\r
790 Rectangle additionalUpdateRect,
\r
791 Color hiliteColor) {
\r
793 Rectangle visibleBounds = fHost.getBounds();
\r
794 Rectangle redrawRect = fFormatter.updateFormat(reformatStart,
\r
798 //System.out.println("[1] redrawRect: " + redrawRect);
\r
800 if (additionalUpdateRect != null) {
\r
801 redrawRect.add(additionalUpdateRect);
\r
802 //System.out.println("[2] redrawRect: " + redrawRect);
\r
805 boolean haveSelection;
\r
807 if (selStart != null && selEnd != null) {
\r
808 haveSelection = true;
\r
809 redrawRect.add(fFormatter.getBoundingRect(selStart, selEnd, fOrigin, MFormatter.LOOSE));
\r
810 //System.out.println("[3] redrawRect: " + redrawRect);
\r
813 haveSelection = false;
\r
816 drawText(fHost.getGraphics(), redrawRect, haveSelection, selStart, selEnd, hiliteColor);
\r
819 private void letBehaviorDraw(Graphics g, Rectangle drawRect) {
\r
821 boolean result = false;
\r
823 if (fHost.fBehavior != null) {
\r
824 result = fHost.fBehavior.paint(g, drawRect);
\r
828 drawText(g, drawRect, false, null, null, null);
\r
832 void moveBy(int dx, int dy) {
\r
834 Rectangle visibleBounds = fHost.getBounds();
\r
835 Graphics g = fHost.getGraphics();
\r
842 Rectangle refreshRect = new Rectangle(visibleBounds);
\r
846 g.copyArea(visibleBounds.x, visibleBounds.y, visibleBounds.width, visibleBounds.height, dx, dy);
\r
849 refreshRect.y = visibleBounds.y + visibleBounds.height + dy;
\r
851 refreshRect.height = Math.abs(dy);
\r
852 //System.out.println("refreshRect=" + refreshRect);
\r
855 letBehaviorDraw(g, refreshRect);
\r
858 private Rectangle getInsetBounds() {
\r
860 int insetDim = 2 * fInsetAmount;
\r
861 return new Rectangle(fBounds.x-fInsetAmount,
\r
862 fBounds.y-fInsetAmount,
\r
863 fBounds.width+insetDim,
\r
864 fBounds.height+insetDim);
\r
867 void paint(Graphics g) {
\r
869 Rectangle hostBounds = fHost.getBounds();
\r
870 Rectangle textRefreshRect = hostBounds.intersection(getInsetBounds());
\r
871 letBehaviorDraw(g, textRefreshRect);
\r
874 Rectangle getCaretRect(TextOffset offset) {
\r
876 return fFormatter.getCaretRect(offset, fOrigin);
\r
879 TextOffset pointToTextOffset(TextOffset result,
\r
883 boolean infiniteMode) {
\r
885 return fFormatter.pointToTextOffset(result, x, y, fOrigin, anchor, infiniteMode);
\r
888 Rectangle getScrollableArea() {
\r
890 Rectangle area = new Rectangle(fBounds);
\r
891 area.x += fInsetAmount - fOrigin.x;
\r
892 area.y += fInsetAmount - fOrigin.y;
\r
897 * Doesn't clone so TextComponent needs to be nice. TextComponent
\r
898 * is the only class which can access this anyway.
\r
900 Rectangle getDocumentBounds() {
\r
907 return fOrigin.x - fInsetAmount;
\r
912 return fOrigin.y - fInsetAmount;
\r
915 int lineContaining(TextOffset offset) {
\r
917 return fFormatter.lineContaining(offset);
\r
920 int lineRangeLow(int lineNumber) {
\r
922 return fFormatter.lineRangeLow(lineNumber);
\r
925 int lineRangeLimit(int lineNumber) {
\r
927 return fFormatter.lineRangeLimit(lineNumber);
\r
930 void stopBackgroundFormatting() {
\r
932 fFormatter.stopBackgroundFormatting();
\r
935 Rectangle getBoundingRect(TextOffset offset1, TextOffset offset2) {
\r
937 Rectangle r = fFormatter.getBoundingRect(offset1, offset2, fOrigin, MFormatter.TIGHT);
\r
938 //r.width += CARET_SLOP;
\r
939 //System.out.println("offset1="+offset1+"; offset2="+offset2);
\r
940 //System.out.println("bounds width="+r.width+"; host width="+(fHost.getBounds().width));
\r
944 TextOffset findNewInsertionOffset(TextOffset result,
\r
945 TextOffset initialOffset,
\r
946 TextOffset previousOffset,
\r
949 return fFormatter.findNewInsertionOffset(
\r
950 result, initialOffset, previousOffset, direction);
\r