📄 wrappedplainview.java
字号:
getContainer().repaint(); } /** * Called when the portion of the Document that this View is responsible * for changes. Overridden so that the view factory creates * WrappedLine views. */ public void changedUpdate (DocumentEvent e, Shape a, ViewFactory f) { super.changedUpdate(e, a, viewFactory); // FIXME: could improve performance by repainting only the necessary area getContainer().repaint(); } class WrappedLineCreator implements ViewFactory { // Creates a new WrappedLine public View create(Element elem) { return new WrappedLine(elem); } } /** * Renders the <code>Element</code> that is associated with this * <code>View</code>. Caches the metrics and then calls * super.paint to paint all the child views. * * @param g the <code>Graphics</code> context to render to * @param a the allocated region for the <code>Element</code> */ public void paint(Graphics g, Shape a) { JTextComponent comp = (JTextComponent)getContainer(); selectionStart = comp.getSelectionStart(); selectionEnd = comp.getSelectionEnd(); updateMetrics(); super.paint(g, a); } /** * Sets the size of the View. Implemented to update the metrics * and then call super method. */ public void setSize (float width, float height) { updateMetrics(); if (width != getWidth()) preferenceChanged(null, true, true); super.setSize(width, height); } class WrappedLine extends View { /** Used to cache the number of lines for this View **/ int numLines; public WrappedLine(Element elem) { super(elem); determineNumLines(); } /** * Renders this (possibly wrapped) line using the given Graphics object * and on the given rendering surface. */ public void paint(Graphics g, Shape s) { // Ensure metrics are up-to-date. updateMetrics(); JTextComponent textComponent = (JTextComponent) getContainer(); g.setFont(textComponent.getFont()); selectedColor = textComponent.getSelectedTextColor(); unselectedColor = textComponent.getForeground(); disabledColor = textComponent.getDisabledTextColor(); // FIXME: this is a hack, for some reason textComponent.getSelectedColor // was returning black, which is not visible against a black background selectedColor = Color.WHITE; Rectangle rect = s.getBounds(); int lineHeight = metrics.getHeight(); int end = getEndOffset(); int currStart = getStartOffset(); int currEnd; while (currStart < end) { currEnd = calculateBreakPosition(currStart, end); drawLine(currStart, currEnd, g, rect.x, rect.y); rect.y += lineHeight; if (currEnd == currStart) currStart ++; else currStart = currEnd; } } /** * Determines the number of logical lines that the Element * needs to be displayed * @return the number of lines needed to display the Element */ int determineNumLines() { numLines = 0; int end = getEndOffset(); if (end == 0) return 0; int breakPoint; for (int i = getStartOffset(); i < end;) { numLines ++; // careful: check that there's no off-by-one problem here // depending on which position calculateBreakPosition returns breakPoint = calculateBreakPosition(i, end); if (breakPoint == i) i ++; else i = breakPoint; } return numLines; } /** * Determines the preferred span for this view along the given axis. * * @param axis the axis (either X_AXIS or Y_AXIS) * * @return the preferred span along the given axis. * @throws IllegalArgumentException if axis is not X_AXIS or Y_AXIS */ public float getPreferredSpan(int axis) { if (axis == X_AXIS) return getWidth(); else if (axis == Y_AXIS) return numLines * metrics.getHeight(); throw new IllegalArgumentException("Invalid axis for getPreferredSpan: " + axis); } /** * Provides a mapping from model space to view space. * * @param pos the position in the model * @param a the region into which the view is rendered * @param b the position bias (forward or backward) * * @return a box in view space that represents the given position * in model space * @throws BadLocationException if the given model position is invalid */ public Shape modelToView(int pos, Shape a, Bias b) throws BadLocationException { Segment s = getLineBuffer(); int lineHeight = metrics.getHeight(); Rectangle rect = a.getBounds(); // Return a rectangle with width 1 and height equal to the height // of the text rect.height = lineHeight; rect.width = 1; int currLineStart = getStartOffset(); int end = getEndOffset(); if (pos < currLineStart || pos >= end) throw new BadLocationException("invalid offset", pos); while (true) { int currLineEnd = calculateBreakPosition(currLineStart, end); // If pos is between currLineStart and currLineEnd then just find // the width of the text from currLineStart to pos and add that // to rect.x if (pos >= currLineStart && pos < currLineEnd || pos == end - 1) { try { getDocument().getText(currLineStart, pos - currLineStart, s); } catch (BadLocationException ble) { // Shouldn't happen } rect.x += Utilities.getTabbedTextWidth(s, metrics, rect.x, WrappedPlainView.this, currLineStart); return rect; } // Increment rect.y so we're checking the next logical line rect.y += lineHeight; // Increment currLineStart to the model position of the start // of the next logical line if (currLineEnd == currLineStart) currLineStart = end; else currLineStart = currLineEnd; } } /** * Provides a mapping from view space to model space. * * @param x the x coordinate in view space * @param y the y coordinate in view space * @param a the region into which the view is rendered * @param b the position bias (forward or backward) * * @return the location in the model that best represents the * given point in view space */ public int viewToModel(float x, float y, Shape a, Bias[] b) { Segment s = getLineBuffer(); Rectangle rect = a.getBounds(); int currLineStart = getStartOffset(); int end = getEndOffset(); int lineHeight = metrics.getHeight(); if (y < rect.y) return currLineStart; if (y > rect.y + rect.height) return end - 1; while (true) { int currLineEnd = calculateBreakPosition(currLineStart, end); // If we're at the right y-position that means we're on the right // logical line and we should look for the character if (y >= rect.y && y < rect.y + lineHeight) { // Check if the x position is to the left or right of the text if (x < rect.x) return currLineStart; if (x > rect.x + rect.width) return currLineEnd - 1; try { getDocument().getText(currLineStart, end - currLineStart, s); } catch (BadLocationException ble) { // Shouldn't happen } int mark = Utilities.getTabbedTextOffset(s, metrics, rect.x, (int) x, WrappedPlainView.this, currLineStart); return currLineStart + mark; } // Increment rect.y so we're checking the next logical line rect.y += lineHeight; // Increment currLineStart to the model position of the start // of the next logical line if (currLineEnd == currLineStart) currLineStart = end; else currLineStart = currLineEnd; } } /** * Returns the document position that is (visually) nearest to the given * document position <code>pos</code> in the given direction <code>d</code>. * * @param c the text component * @param pos the document position * @param b the bias for <code>pos</code> * @param d the direction, must be either {@link SwingConstants#NORTH}, * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or * {@link SwingConstants#EAST} * @param biasRet an array of {@link Position.Bias} that can hold at least * one element, which is filled with the bias of the return position * on method exit * * @return the document position that is (visually) nearest to the given * document position <code>pos</code> in the given direction * <code>d</code> * * @throws BadLocationException if <code>pos</code> is not a valid offset * in the document model */ public int getNextVisualPositionFrom(JTextComponent c, int pos, Position.Bias b, int d, Position.Bias[] biasRet) throws BadLocationException { // TODO: Implement this properly. throw new AssertionError("Not implemented yet."); } /** * This method is called from insertUpdate and removeUpdate. * If the number of lines in the document has changed, just repaint * the whole thing (note, could improve performance by not repainting * anything above the changes). If the number of lines hasn't changed, * just repaint the given Rectangle. * @param a the Rectangle to repaint if the number of lines hasn't changed */ void updateDamage (Rectangle a) { int newNumLines = determineNumLines(); if (numLines != newNumLines) { numLines = newNumLines; getContainer().repaint(); } else getContainer().repaint(a.x, a.y, a.width, a.height); } /** * 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((Rectangle)a); } /** * 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((Rectangle)a); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -