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

📄 wrappedsyntaxview_test.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * 08/06/2004
 *
 * WrappedSyntaxView_TEST.java - Test implementation of WrappedSyntaxView that
 *           is also aware of RSyntaxTextArea's different fonts per token type.
 * Copyright (C) 2004 Robert Futrell
 * email@address.com
 * www.website.com
 *
 * This program 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
 * of the License, or any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.fife.ui.rsyntaxtextarea;

import java.awt.*;
import javax.swing.text.*;
import javax.swing.event.*;


/**
 * The view used by {@link RSyntaxTextArea} when word wrap is enabled.<p>
 *
 * This class is a work-in-progress and will eventually replace
 * {@link WrappedSyntaxView} (which works, but ignores token styles).
 *
 * @author Robert Futrell
 * @version 0.2
 */
public class WrappedSyntaxView_TEST extends BoxView implements TabExpander {

	boolean widthChanging;
	int tabBase;
	int tabSize;
    
	/**
	 * This is reused to keep from allocating/deallocating.
	 */
	private Segment s, drawSeg;
	
	/**
	 * Another variable initialized once to keep from allocating/deallocating.
	 */
	private Rectangle tempRect;

	/**
	 * Cached for each paint() call so each drawView() call has access to it.
	 */
	private RSyntaxTextArea host;
	private FontMetrics metrics;
	private SyntaxHighlightingColorScheme colorScheme;

	/**
	 * The end-of-line marker.
	 */
	private static final char[] eolMarker = { '.' };

	/**
	 * The width of this view cannot be below this amount, as if the width
	 * is ever 0 (really a bug), we'll go into an infinite loop.
	 */
	private static final int MIN_WIDTH		= 20;


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


	/**
	 * Creates a new WrappedSyntaxView_TEST.  Lines will be wrapped
	 * on character boundaries.
	 *
	 * @param elem the element underlying the view
	 */
	public WrappedSyntaxView_TEST(Element elem) {
		super(elem, Y_AXIS);
		s = new Segment();
		drawSeg = new Segment();
		tempRect = new Rectangle();
	}



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


	/**
	 * This is called by the nested wrapped line
	 * views to determine the break location.  This can
	 * be reimplemented to alter the breaking behavior.
	 * It will either break at word or character boundaries
	 * depending upon the break argument given at
	 * construction.
	 */
	protected int calculateBreakPosition(int p0, Token tokenList, float x0) {
//System.err.println("------ beginning calculateBreakPosition() --------");
		int p = p0;
		RSyntaxTextArea textArea = (RSyntaxTextArea)getContainer();
		float currentWidth = getWidth();
		if (currentWidth==Integer.MAX_VALUE)
			currentWidth = getPreferredSpan(X_AXIS);
		// Make sure width>0; this is a huge hack to fix a bug where
		// loading text into an RTextArea before it is visible if word wrap
		// is enabled causes an infinite loop in calculateBreakPosition()
		// because of the 0-width!  We cannot simply check in setSize()
		// because the width is set to 0 somewhere else too somehow...
		currentWidth = Math.max(currentWidth, MIN_WIDTH);
		Token t = tokenList;
		while (t!=null && t.isPaintable()) {
// FIXME:  Replace the code below with the commented-out line below.  This will
// allow long tokens to be broken at embedded spaces (such as MLC's).  But it
// currently throws BadLocationExceptions sometimes...
			FontMetrics fm = textArea.getFontMetricsForTokenType(t.type);
			float tokenWidth = t.getWidth(fm, this, x0);
			if (tokenWidth>currentWidth) {
				// If the current token alone is too long for this line,
				// break at a character boundary.
				if (p==p0) {
					return t.getOffsetBeforeX(fm, this, 0, currentWidth);
				}
				// Return the first non-whitespace char (i.e., don't start
				// off the continuation of a wrapped line with whitespace).
				return (t.type==Token.WHITESPACE) ? p+t.textCount : p;
//return getBreakLocation(t, fm, x0, currentWidth, this);
			}
			currentWidth -= tokenWidth;
			x0 += tokenWidth;
			p += t.textCount;
//System.err.println("*** *** *** token fit entirely (width==" + tokenWidth + "), adding " + t.textCount + " to p, now p==" + p);
			t = t.getNextToken();
		}
//System.err.println("... ... whole line fits; returning p==" + p);
//System.err.println("------ ending calculateBreakPosition() --------");

//		return p;
return p + 1;
	}

private int getBreakLocation(Token t, FontMetrics fm, int x0, int x,
								TabExpander e) {
	Segment s = new Segment();
	s.array = t.text;
	s.offset = t.textOffset;
	s.count = t.textCount;
	return t.offset + Utilities.getBreakLocation(s, fm, x0, x, e, t.offset);
}

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


	/**
	 * Gives notification from the document that attributes were changed
	 * in a location that this view is responsible for.
	 *
	 * @param e 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
	 * @see View#changedUpdate
	 */
	public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
		updateChildren(e, a);
	}


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


	/**
	 * Draws a single view (i.e., a line of text for a wrapped view), wrapping
	 * the text onto multiple lines if necessary.
	 *
	 * @param g The graphics context in which to paint.
	 * @param r The rectangle in which to paint.
	 * @param view The <code>View</code> to paint.
	 * @param fontHeight The height of the font being used.
	 * @param y The y-coordinate at which to begin painting.
	 */
	protected void drawView(Graphics2D g, Rectangle r, View view,
						int fontHeight, int y) {

		float x = r.x;

		LayeredHighlighter dh = (LayeredHighlighter)host.getHighlighter();

		RSyntaxDocument document = (RSyntaxDocument)getDocument();
		Element map = getElement();

		int p0 = view.getStartOffset();
		int lineNumber = map.getElementIndex(p0);
		int p1 = view.getEndOffset();// - 1;

		setSegment(p0,p1-1, document, drawSeg);
		//System.err.println("drawSeg=='" + drawSeg + "' (p0/p1==" + p0 + "/" + p1 + ")");
		int start = p0 - drawSeg.offset;
		Token token = document.getTokenListForLine(lineNumber);

		// If this line is an empty line, then the token list is simply a
		// null token.  In this case, the line highlight will be skipped in
		// the loop below, so unfortunately we must manually do it here.
		if (token!=null && token.type==Token.NULL) {
			dh.paintLayeredHighlights(g, p0,p1, r, host, this);
			return;
		}

		// Loop through all tokens in this view and paint them!
		while (token!=null && token.isPaintable()) {

			int p = calculateBreakPosition(p0, token, x);

			dh.paintLayeredHighlights(g, p0,p, r, host, this);

			while (token!=null && token.isPaintable() && token.offset+token.textCount-1<p) {//<=p) {
				SyntaxScheme scheme = colorScheme.syntaxSchemes[token.type];
				x = token.paint(g, x,y, scheme, host, this);
				token = token.getNextToken();
			}
			
			if (token!=null && token.isPaintable() && token.offset<p) {
				int tokenOffset = token.offset;
				Token temp = new DefaultToken(drawSeg, tokenOffset-start,
									p-1-start, tokenOffset,
									token.type);
				SyntaxScheme scheme = colorScheme.syntaxSchemes[token.type];
				temp.paint(g, x,y, scheme, host, this);
				temp = null;
				token.makeStartAt(p);
			}

			p0 = (p==p0) ? p1 : p;
			x = r.x;
			y += fontHeight;
			
		} // End of while (token!=null && token.isPaintable()).

	}


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


	/**
	 * Determines the maximum span for this view along an
	 * axis.  This is implemented to provide the superclass
	 * behavior after first making sure that the current font
	 * metrics are cached (for the nested lines which use
	 * the metrics to determine the height of the potentially
	 * wrapped lines).
	 *
	 * @param axis may be either View.X_AXIS or View.Y_AXIS
	 * @return  the span the view would like to be rendered into.
	 *           Typically the view is told to render into the span
	 *           that is returned, although there is no guarantee.  
	 *           The parent may choose to resize or break the view.
	 * @see View#getMaximumSpan
	 */
	public float getMaximumSpan(int axis) {
		updateMetrics();
		return super.getMaximumSpan(axis);
	}


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


	/**
	 * Determines the minimum span for this view along an
	 * axis.  This is implemented to provide the superclass
	 * behavior after first making sure that the current font
	 * metrics are cached (for the nested lines which use
	 * the metrics to determine the height of the potentially
	 * wrapped lines).
	 *
	 * @param axis may be either View.X_AXIS or View.Y_AXIS
	 * @return  the span the view would like to be rendered into.
	 *           Typically the view is told to render into the span
	 *           that is returned, although there is no guarantee.  
	 *           The parent may choose to resize or break the view.
	 * @see View#getMinimumSpan
	 */
	public float getMinimumSpan(int axis) {
		updateMetrics();
		return super.getMinimumSpan(axis);
	}


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


	/**
	 * Determines the preferred span for this view along an
	 * axis.  This is implemented to provide the superclass
	 * behavior after first making sure that the current font
	 * metrics are cached (for the nested lines which use
	 * the metrics to determine the height of the potentially
	 * wrapped lines).
	 *
	 * @param axis may be either View.X_AXIS or View.Y_AXIS
	 * @return  the span the view would like to be rendered into.
	 *           Typically the view is told to render into the span
	 *           that is returned, although there is no guarantee.  
	 *           The parent may choose to resize or break the view.
	 * @see View#getPreferredSpan
	 */
	public float getPreferredSpan(int axis) {
		updateMetrics();
		return super.getPreferredSpan(axis);
	}


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


	/**
	 * Returns the tab size set for the document, defaulting to 5.
	 *
	 * @return the tab size
	 */
	protected int getTabSize() {
		Integer i = (Integer) getDocument().getProperty(PlainDocument.tabSizeAttribute);
		int size = (i != null) ? i.intValue() : 5;
		return size;
	}


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


	/**
	 * Gives notification that something was inserted into the 
	 * document in a location that this view is responsible for.
	 * This is implemented to simply update the children.
	 *
	 * @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
	 * @see View#insertUpdate
	 */
	public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) {

⌨️ 快捷键说明

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