diff options
Diffstat (limited to 'libjava/classpath/javax/swing/text/PlainView.java')
-rw-r--r-- | libjava/classpath/javax/swing/text/PlainView.java | 724 |
1 files changed, 0 insertions, 724 deletions
diff --git a/libjava/classpath/javax/swing/text/PlainView.java b/libjava/classpath/javax/swing/text/PlainView.java deleted file mode 100644 index 16112fd..0000000 --- a/libjava/classpath/javax/swing/text/PlainView.java +++ /dev/null @@ -1,724 +0,0 @@ -/* 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; - - /** - * The base offset for tab calculations. - */ - private int tabBase; - - /** - * The tab size. - */ - private int tabSize; - - 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); - tabSize = getTabSize() * metrics.charWidth('m'); - } - } - - /** - * @since 1.4 - */ - protected Rectangle lineToRect(Shape a, int line) - { - // Ensure metrics are up-to-date. - updateMetrics(); - - Rectangle rect = a instanceof Rectangle ? (Rectangle) a : 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); - tabBase = rect.x; - - // 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, tabBase, - 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 instanceof Rectangle ? (Rectangle) s : s.getBounds(); - tabBase = rect.x; - - // FIXME: Text may be scrolled. - Document document = textComponent.getDocument(); - Element root = getElement(); - int height = metrics.getHeight(); - - // For layered highlighters we need to paint the layered highlights - // before painting any text. - LayeredHighlighter hl = null; - Highlighter h = textComponent.getHighlighter(); - if (h instanceof LayeredHighlighter) - hl = (LayeredHighlighter) h; - - int count = root.getElementCount(); - - // Determine first and last line inside the clip. - Rectangle clip = g.getClipBounds(); - SwingUtilities.computeIntersection(rect.x, rect.y, rect.width, rect.height, - clip); - int line0 = (clip.y - rect.y) / height; - line0 = Math.max(0, Math.min(line0, count - 1)); - int line1 = (clip.y + clip.height - rect.y) / height; - line1 = Math.max(0, Math.min(line1, count - 1)); - int y = rect.y + metrics.getAscent() + height * line0; - for (int i = line0; i <= line1; i++) - { - if (hl != null) - { - Element lineEl = root.getElement(i); - // Exclude the trailing newline from beeing highlighted. - if (i == count) - hl.paintLayeredHighlights(g, lineEl.getStartOffset(), - lineEl.getEndOffset(), s, textComponent, - this); - else - hl.paintLayeredHighlights(g, lineEl.getStartOffset(), - lineEl.getEndOffset() - 1, s, - textComponent, this); - } - 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 next = x; - if (tabSize != 0) - { - int numTabs = (((int) x) - tabBase) / tabSize; - next = tabBase + (numTabs + 1) * tabSize; - } - return next; - } - - /** - * 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 instanceof Rectangle ? (Rectangle) a : a.getBounds(); - tabBase = rec.x; - - int pos; - if ((int) y < rec.y) - // Above our area vertically. Return start offset. - pos = getStartOffset(); - else if ((int) y > rec.y + rec.height) - // Below our area vertically. Return end offset. - pos = getEndOffset() - 1; - else - { - // Inside the allocation vertically. Determine line and X offset. - Document doc = getDocument(); - Element root = doc.getDefaultRootElement(); - int line = Math.abs(((int) y - rec.y) / metrics.getHeight()); - if (line >= root.getElementCount()) - pos = getEndOffset() - 1; - else - { - Element lineEl = root.getElement(line); - if (x < rec.x) - // To the left of the allocation area. - pos = lineEl.getStartOffset(); - else if (x > rec.x + rec.width) - // To the right of the allocation area. - pos = lineEl.getEndOffset() - 1; - else - { - try - { - int p0 = lineEl.getStartOffset(); - int p1 = lineEl.getEndOffset(); - Segment s = new Segment(); - doc.getText(p0, p1 - p0, s); - tabBase = rec.x; - pos = p0 + Utilities.getTabbedTextOffset(s, metrics, - tabBase, (int) x, - this, p0); - } - catch (BadLocationException ex) - { - // Should not happen. - pos = -1; - } - } - - } - } - // Bias is always forward. - b[0] = Position.Bias.Forward; - return 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, tabBase, this, - lineEl.getStartOffset()); - } -} |