⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syntaxview.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
📖 第 1 页 / 共 2 页
字号:

	/**
	 * Provides a mapping, for a given region, from the document model
	 * coordinate space to the view coordinate space. The specified region is
	 * created as a union of the first and last character positions.<p>
	 *
	 * This is implemented to subtract the width of the second character, as
	 * this view's <code>modelToView</code> actually returns the width of the
	 * character instead of "1" or "0" like the View implementations in
	 * <code>javax.swing.text</code>.  Thus, if we don't override this method,
	 * the <code>View</code> implementation will return one character's width
	 * too much for its consumers (implementations of
	 * <code>javax.swing.text.Highlighter</code>).
	 *
	 * @param p0 the position of the first character (>=0)
	 * @param b0 The bias of the first character position, toward the previous
	 *           character or the next character represented by the offset, in
	 *           case the position is a boundary of two views; <code>b0</code>
	 *           will have one of these values:
	 * <ul>
	 *    <li> <code>Position.Bias.Forward</code>
	 *    <li> <code>Position.Bias.Backward</code>
	 * </ul>
	 * @param p1 the position of the last character (>=0)
	 * @param b1 the bias for the second character position, defined
	 *		one of the legal values shown above
	 * @param a the area of the view, which encompasses the requested region
	 * @return the bounding box which is a union of the region specified
	 *		by the first and last character positions
	 * @exception BadLocationException  if the given position does
	 *   not represent a valid location in the associated document
	 * @exception IllegalArgumentException if <code>b0</code> or
	 *		<code>b1</code> are not one of the
	 *		legal <code>Position.Bias</code> values listed above
	 * @see View#viewToModel
	 */
	public Shape modelToView(int p0, Position.Bias b0,
							int p1, Position.Bias b1,
							Shape a) throws BadLocationException {

		Shape s0 = modelToView(p0, a, b0);
		Shape s1;
		if (p1 ==getEndOffset()) {
			try {
				s1 = modelToView(p1, a, b1);
			} catch (BadLocationException ble) {
				s1 = null;
			}
			if (s1 == null) {
				// Assume extends left to right.
				Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
								a.getBounds();
				s1 = new Rectangle(alloc.x + alloc.width - 1, alloc.y,
								1, alloc.height);
			}
		}
		else {
			s1 = modelToView(p1, a, b1);
		}
		Rectangle r0 = s0.getBounds();
		Rectangle r1 = (s1 instanceof Rectangle) ? (Rectangle) s1 :
													s1.getBounds();
		if (r0.y != r1.y) {
			// If it spans lines, force it to be the width of the view.
			Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a :
								a.getBounds();
			r0.x = alloc.x;
			r0.width = alloc.width;
		}

		r0.add(r1);
		// The next line is the only difference between this method and
		// View's implementation.  We're subtracting the width of the second
		// character.  This is because this method is used by Highlighter
		// implementations to get the area to "highlight", and if we don't do
		// this, one character too many is highlighted thanks to our
		// modelToView() implementation returning the actual width of the
		// character requested!
		if (p1>p0) r0.width -= r1.width;

		return r0;

	}


/*****************************************************************************/


	/**
	 * Returns the next tab stop position after a given reference position.
	 * This implementation does not support things like centering so it
	 * ignores the tabOffset argument.
	 *
	 * @param x the current position >= 0
	 * @param tabOffset the position within the text stream
	 *   that the tab occurred at >= 0.
	 * @return the tab stop, measured in points >= 0
	 */
	public float nextTabStop(float x, int tabOffset) {
		if (tabSize == 0)
			return x;
		int ntabs = (((int)x) - tabBase) / tabSize;
		return tabBase + ((ntabs + 1) * tabSize);
	}


/*****************************************************************************/


	/**
	 * Actually paints the text area.  Only lines that have been damaged are
	 * repainted.
	 *
	 * @param g The graphics context with which to paint.
	 * @param a The allocated region in which to render.
	 * @see #drawLine
	 */
	public void paint(Graphics g, Shape a) {

		RSyntaxDocument document = (RSyntaxDocument)getDocument();

		Rectangle alloc = a.getBounds();

		tabBase = alloc.x;
		host = (RSyntaxTextArea)getContainer();

		Rectangle clip = g.getClipBounds();
		// An attempt to speed things up for files with long lines.  Note that
		// this will actually slow things down a tad for the common case of
		// regular-length lines, but I don't think it'll make a difference
		// visually.  We'll see...
		clipStart = clip.x;
		clipEnd = clipStart + clip.width;

		lineHeight = host.getLineHeight();
		ascent = host.getMaxAscent();//metrics.getAscent();
		int heightBelow = (alloc.y + alloc.height) - (clip.y + clip.height);
		int linesBelow = Math.max(0, heightBelow / lineHeight);
		int heightAbove = clip.y - alloc.y;
		int linesAbove = Math.max(0, heightAbove / lineHeight);
		int linesTotal = alloc.height / lineHeight;

		if (alloc.height % lineHeight != 0) {
			linesTotal++;
		}

		Rectangle lineArea = lineToRect(a, linesAbove);
		int y = lineArea.y + ascent;
		int x = lineArea.x;
		Element map = getElement();
		int lineCount = map.getElementCount();
		int endLine = Math.min(lineCount, linesTotal - linesBelow);
		lineCount--;
/*
		DefaultHighlighter dh = (DefaultHighlighter)host.getHighlighter();
		if (!dh.getDrawsLayeredHighlights()) {
			dh.paint(g); // Draw all highlights now.
		}
*/
		LayeredHighlighter dh = (LayeredHighlighter)host.getHighlighter();
		final SyntaxHighlightingColorScheme colorScheme =
								host.getSyntaxHighlightingColorScheme();
		Graphics2D g2d = (Graphics2D)g;
		Token token;
		//System.err.println("Painting lines: " + linesAbove + " to " + (endLine-1));

		for (int line = linesAbove; line < endLine; line++) {

			// Paint the highlights (both selection and "mark all").
			//if (dh.getDrawsLayeredHighlights() {
			Element lineElement = map.getElement(line);
			int startOffset = lineElement.getStartOffset();
			int endOffset = (line==lineCount ? lineElement.getEndOffset()-1 :
										lineElement.getEndOffset()-1);
			dh.paintLayeredHighlights(g2d, startOffset, endOffset, a,
													host, this);
			//}

			// Paint a line of text.
			token = document.getTokenListForLine(line);
			drawLine(token, g2d, colorScheme, x,y);
			y += lineHeight;

		}

	}


/*****************************************************************************/


	/**
	 * If the passed-in line is longer than the current longest line, then
	 * the longest line is updated.
	 *
	 * @param line The line to test against the current longest.
	 * @param lineNumber The line number of the passed-in line.
	 * @return <code>true</code> iff the current longest line was updated.
	 */
	protected boolean possiblyUpdateLongLine(Element line, int lineNumber) {
		float w = getLineWidth(lineNumber);
		if (w > longLineWidth) {
			longLineWidth = w;
			longLine = line;
			return true;
		}
		return false;
	}


/*****************************************************************************/


	/**
	 * Gives notification that something was removed from the document
	 * in a location that this view is responsible for.
	 *
	 * @param changes the change information from the associated document
	 * @param a the current allocation of the view
	 * @param f the factory to use to rebuild if the view has children
	 */
	public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
		updateDamage(changes, a, f);
	}


/*****************************************************************************/


	/**
	 * Makes our private <code>Segment s</code> point to the text in our
	 * document referenced by the specified element.  Note that
	 * <code>line</code> MUST be a valid line number in the document.
	 *
	 * @param line The line number you want to get.
	 * @param document The document from which you want to get the text.
	 */
	private void setSharedSegment(int line, Document document) {

		Element map = getElement();
		int numLines = map.getElementCount();

		Element element = map.getElement(line);
		int startOffset = element.getStartOffset();
		int endOffset = (line==numLines-1 ? element.getEndOffset()-1 :
									element.getEndOffset() - 1);

		setSharedSegment(startOffset, endOffset, document);

	}


/*****************************************************************************/


	/**
	 * Makes our private <code>Segment s</code> point to the text in our
	 * document referenced by the specified positions.  Note that the
	 * positions MUST be a valid in the document.
	 *
	 * @param p0 The starting position of the text in the document.
	 * @param p1 The ending position of the text in the document.
	 * @param document The document from which you want to get the text.
	 */
	private final void setSharedSegment(int p0, int p1, Document document) {
		try {
			document.getText(p0, p1-p0, s);
		} catch (BadLocationException ble) {
			ble.printStackTrace();
			System.exit(0);
		}
	}


/*****************************************************************************/


	public void setSize(float width, float height) {
		super.setSize(width, height);
		updateMetrics();
	}


/*****************************************************************************/


	/**
	 * Repaint the region of change covered by the given document
	 * event.  Damages the line that begins the range to cover
	 * the case when the insert/remove is only on one line.  
	 * If lines are added or removed, damages the whole 
	 * view.  The longest line is checked to see if it has 
	 * changed.
	 */
	protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f) {
		Component host = getContainer();
		updateMetrics();
		Element elem = getElement();
		DocumentEvent.ElementChange ec = changes.getChange(elem);
		Element[] added = (ec != null) ? ec.getChildrenAdded() : null;
		Element[] removed = (ec != null) ? ec.getChildrenRemoved() : null;
		if (((added != null) && (added.length > 0)) || 
			((removed != null) && (removed.length > 0))) {
			// lines were added or removed...
			if (added != null) {
				int addedAt = ec.getIndex(); // FIXME: Is this correct?????
				for (int i = 0; i < added.length; i++)
					possiblyUpdateLongLine(added[i], addedAt+i);
			}
			if (removed != null) {
				for (int i = 0; i < removed.length; i++) {
					if (removed[i] == longLine) {
						longLineWidth = -1; // Must do this!!
						calculateLongestLine();
						break;
					}
				}
			}
			preferenceChanged(null, true, true);
			host.repaint();
		}

		// This occurs when syntax highlighting only changes on lines
		// (i.e. beginning a multiline comment).
		else if (changes.getType()==DocumentEvent.EventType.CHANGE) {
			//System.err.println("Updating the damage due to a CHANGE event...");
			int startLine = changes.getOffset();
			int endLine = changes.getLength();
			damageLineRange(startLine,endLine, a, host);
		}

		else {
			Element map = getElement();
			int line = map.getElementIndex(changes.getOffset());
			damageLineRange(line, line, a, host);
			if (changes.getType() == DocumentEvent.EventType.INSERT) {
				// check to see if the line is longer than current
				// longest line.
				Element e = map.getElement(line);
				if (e == longLine) {
					// We must recalculate longest line's width here
					// because it has gotten longer.
					longLineWidth = getLineWidth(line);
					preferenceChanged(null, true, false);
				}
				else {
					// If long line gets updated, update the status bars too.
					if (possiblyUpdateLongLine(e, line))
						preferenceChanged(null, true, false);
				}
			}
			else if (changes.getType() == DocumentEvent.EventType.REMOVE) {
				if (map.getElement(line) == longLine) {
					// removed from longest line... recalc
					longLineWidth = -1; // Must do this!
					calculateLongestLine();
					preferenceChanged(null, true, false);
				}			
			}
		}
	}


/*****************************************************************************/


	/**
	 * Checks to see if the font metrics and longest line are up-to-date.
	 */
	protected void updateMetrics() {
		host = (RSyntaxTextArea)getContainer();
		Font f = host.getFont();
		if (font != f) {
			// The font changed, we need to recalculate the longest line!
			// This also updates cached font and tab size.
			calculateLongestLine();
		}
	}


/*****************************************************************************/


	/**
	 * Provides a mapping from the view coordinate space to the logical
	 * coordinate space of the model.
	 *
	 * @param fx the X coordinate >= 0
	 * @param fy the Y coordinate >= 0
	 * @param a the allocated region to render into
	 * @return the location within the model that best represents the
	 *  given point in the view >= 0
	 */
	public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {

		bias[0] = Position.Bias.Forward;

		Rectangle alloc = a.getBounds();
		RSyntaxDocument doc = (RSyntaxDocument)getDocument();
		int x = (int) fx;
		int y = (int) fy;

		// If they're asking about a view position above the area covered by
		// this view, then the position is assumed to be the starting position
		// of this view.
		if (y < alloc.y) {
			return getStartOffset();
		}

		// If they're asking about a position below this view, the position
		// is assumed to be the ending position of this view.
		else if (y > alloc.y + alloc.height) {
			return getEndOffset() - 1;
		}

		// They're asking about a position within the coverage of this view
		// vertically.  So, we figure out which line the point corresponds to.
		// If the line is greater than the number of lines contained, then
		// simply use the last line as it represents the last possible place
		// we can position to.
		else {

			Element map = doc.getDefaultRootElement();
			int lineIndex = Math.abs((y - alloc.y) / lineHeight);//metrics.getHeight() );
			if (lineIndex >= map.getElementCount())
				return getEndOffset() - 1;

			Element line = map.getElement(lineIndex);

			// If the point is to the left of the line...
			if (x < alloc.x)
				return line.getStartOffset();

			// If the point is to the right of the line...
			else if (x > alloc.x + alloc.width)
				return line.getEndOffset() - 1;

			else {
				// Determine the offset into the text
				int p0 = line.getStartOffset();
				Token tokenList = doc.getTokenListForLine(lineIndex);
				tabBase = alloc.x;
				int offs = tokenList.getListOffset(
									(RSyntaxTextArea)getContainer(),
									this, tabBase, x);
				return offs!=-1 ? offs : p0;
			}

		} // End of else.

	} 


/*****************************************************************************/

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -