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

📄 rsyntaxtextareaeditorkit.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 08/29/2004
 *
 * RSyntaxTextAreaEditorKit.java - The editor kit used by RSyntaxTextArea.
 * 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 java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;

import org.fife.ui.rtextarea.RecordableTextAction;
import org.fife.ui.rtextarea.RTextArea;
import org.fife.ui.rtextarea.RTextAreaEditorKit;


/**
 * An extension of <code>RTextAreaEditorKit</code> that adds functionality for
 * programming-specific stuff.  There are currently subclasses to handle:
 *
 * <ul>
 *   <li>Block indentation (increasing the indent of one or multiple lines)</li>
 *   <li>Block un-indentation (decreasing the indent of one or multiple lines)
 *       </li>
 *   <li>Auto-indent (handled by simply remembering the indent of the previous
 *       line when a newline is inserted)</li>
 *   <li>Inserting a "code template" when a configurable key (e.g. a space) is
 *       pressed</li>
 *   <li>Decreasing the point size of all fonts in the text area</li>
 *   <li>Increasing the point size of all fonts in the text area</li>
 *   <li>Moving the caret to the "matching bracket" of the one at the current
 *       caret position</li>
 * </ul>
 *
 * @author Robert Futrell
 * @version 0.3
 */
public class RSyntaxTextAreaEditorKit extends RTextAreaEditorKit {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6058766564696326312L;

	public static final String rstaDecreaseIndentAction	=  "RSyntaxTextArea.DecreaseIndentAction";
	public static final String rstaGoToMatchingBracketAction	= "RSyntaxTextArea.GoToMatchingBracketAction";
	public static final String rstaPossiblyInsertTemplateAction = "RSyntaxTextArea.TemplateAction";


	/**
	 * The actions that <code>RSyntaxTextAreaEditorKit</code> adds to those of
	 * <code>RTextAreaEditorKit</code>.
	 */
	private static final Action[] defaultActions = {
		new DecreaseIndentAction(),
		new InsertBreakAction(),
		new InsertTabAction(),
		new PossiblyInsertTemplateAction(),
	};


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


	/**
	 * Constructor.
	 */
	public RSyntaxTextAreaEditorKit() {
		super();
	}


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


	/**
	 * Returns the default document used by <code>RSyntaxTextArea</code>s.
	 *
	 * @return The document.
	 */
	public Document createDefaultDocument() {
		return new RSyntaxDocument(SyntaxConstants.NO_SYNTAX_STYLE);
	}


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


	/**
	 * Fetches the set of commands that can be used
	 * on a text component that is using a model and
	 * view produced by this kit.
	 *
	 * @return the command list
	 */ 
	public Action[] getActions() {
		return TextAction.augmentList(super.getActions(),
									RSyntaxTextAreaEditorKit.defaultActions);
	}


/*****************************************************************************/
/**************************** INNER CLASSES **********************************/
/*****************************************************************************/


	/**
	 * Action for decreasing the font size of all fonts in the text area.
	 */
	public static class DecreaseFontSizeAction
					extends RTextAreaEditorKit.DecreaseFontSizeAction {

		/**
		 * 
		 */
		private static final long serialVersionUID = 8797959862173386776L;

		public DecreaseFontSizeAction() {
			super();
		}

		public DecreaseFontSizeAction(String name, Icon icon, String desc,
							Integer mnemonic, KeyStroke accelerator) {
			super(name, icon, desc, mnemonic, accelerator);
		}

		public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {

			RSyntaxTextArea rsta = (RSyntaxTextArea)textArea;
			SyntaxHighlightingColorScheme scheme = rsta.
									getSyntaxHighlightingColorScheme();

			// All we need to do is update all of the fonts in syntax
			// schemes, then call setSyntaxHighlightingColorScheme with the
			// same scheme already being used.  This relies on the fact that
			// that method does not check whether the new scheme is different
			// from the old scheme before updating.

			boolean changed = false;
			int count = scheme.syntaxSchemes.length;
			for (int i=0; i<count; i++) {
				SyntaxScheme ss = scheme.syntaxSchemes[i];
				if (ss!=null) {
					Font font = ss.font;
					if (font!=null) {
						float oldSize = font.getSize2D();
						float newSize = oldSize - decreaseAmount;
						if (newSize>=MINIMUM_SIZE) {
							// Shrink by decreaseAmount.
							ss.font = font.deriveFont(newSize);
							changed = true;
						}
						else if (oldSize>MINIMUM_SIZE) {
							// Can't shrink by full decreaseAmount, but
							// can shrink a little bit.
							ss.font = font.deriveFont(MINIMUM_SIZE);
							changed = true;
						}
					}
				}
			}

			// If we updated at least one font, update the screen.  If
			// all of the fonts were already the minimum size, beep.
			if (changed) {
				rsta.setSyntaxHighlightingColorScheme(scheme);
				// NOTE:  This is a hack to get an encompassing
				// RTextScrollPane to repaint its line numbers to account
				// for a change in line height due to a font change.  I'm
				// not sure why we need to do this here but not when we
				// change the syntax highlighting color scheme via the
				// Options dialog... setSyntaxHighlightingColorScheme()
				// calls revalidate() which won't repaint the scroll pane
				// if scrollbars don't change, which is why we need this.
				Component parent = rsta.getParent();
				if (parent instanceof javax.swing.JViewport) {
					parent = parent.getParent();
					if (parent instanceof JScrollPane) {
						parent.repaint();
					}
				}
			}
			else
				UIManager.getLookAndFeel().provideErrorFeedback(rsta);

		}

	}


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

	
	/**
	 * Action for when un-indenting lines (either the current line if there is
	 * selection, or all selected lines if there is one).
	 */
	public static class DecreaseIndentAction extends RecordableTextAction {

		/**
		 * 
		 */
		private static final long serialVersionUID = -8480135115767268218L;
	
		private Segment s;

		public DecreaseIndentAction() {
			this(rstaDecreaseIndentAction);
		}

		public DecreaseIndentAction(String name) {
			super(name);
			s = new Segment();
		}

		public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {

			if (!textArea.isEditable() || !textArea.isEnabled()) {
				UIManager.getLookAndFeel().provideErrorFeedback(textArea);
				return;
			}

			Document document = textArea.getDocument();
			Element map = document.getDefaultRootElement();
			Caret c = textArea.getCaret();
			int dot = c.getDot();
			int mark = c.getMark();
			int line1 = map.getElementIndex(dot);
			int tabSize = textArea.getTabSize();

			// If there is a selection, indent all lines in the selection.
			// Otherwise, indent the line the caret is on.
			if (dot!=mark) {
				// Note that we cheaply reuse variables here, so don't
				// take their names to mean what they are.
				int line2 = map.getElementIndex(mark);
				dot = Math.min(line1, line2);
				mark = Math.max(line1, line2);
				Element elem;
				try {
					for (line1=dot; line1<mark; line1++) {
						elem = map.getElement(line1);
						handleDecreaseIndent(elem, document, tabSize);
					}
					// Don't do the last line if the caret is at its
					// beginning.  We must call getDot() again and not just
					// use 'dot' as the caret's position may have changed
					// due to the insertion of the tabs above.
					elem = map.getElement(mark);
					if (c.getDot()!=elem.getStartOffset())
						handleDecreaseIndent(elem, document, tabSize);
				} catch (BadLocationException ble) {
					ble.printStackTrace();
					UIManager.getLookAndFeel().
								provideErrorFeedback(textArea);
				}
			}
			else {
				Element elem = map.getElement(line1);
				try {
					handleDecreaseIndent(elem, document, tabSize);
				} catch (BadLocationException ble) {
					ble.printStackTrace();
					UIManager.getLookAndFeel().
								provideErrorFeedback(textArea);
				}
			}

		}

		public final String getMacroID() {
			return rstaDecreaseIndentAction;
		}

		/**
		 * Actually does the "de-indentation."  This method finds where the
		 * given element's leading whitespace ends, then, if there is indeed
		 * leading whitespace, removes either the last char in it (if it is a
		 * tab), or removes up to the number of spaces equal to a tab in the
		 * specified document (i.e., if the tab size was 5 and there were 3
		 * spaces at the end of the leading whitespace, the three will be
		 * removed; if there were 8 spaces, only the first 5 would be
		 * removed).
		 *
		 * @param elem The element to "de-indent."
		 * @param doc The document containing the specified element.
		 * @param tabSize The size of a tab, in spaces.
		 */
		private final void handleDecreaseIndent(Element elem, Document doc,
									int tabSize)
									throws BadLocationException {
			int start = elem.getStartOffset();
			int end = elem.getEndOffset() - 1; // Why always true??
			doc.getText(start,end-start, s);
			int i = s.offset;
			end = i+s.count;
			if (end>i) {
				// If the first character is a tab, remove it.
				if (s.array[i]=='\t') {
					doc.remove(start, 1);
				}
				// Otherwise, see if the first character is a space.  If it
				// is, remove all contiguous whitespaces at the beginning of
				// this line, up to the tab size.
				else if (s.array[i]==' ') {
					i++;
					int toRemove = 1;
					while (i<end && s.array[i]==' ' && toRemove<tabSize) {
						i++;
						toRemove++;
					}
					doc.remove(start, toRemove);
				}
			}
		}

	}


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


	/**
	 * Action for moving the caret to the "matching bracket" of the bracket
	 * at the caret position (either before or after).
	 */
	public static class GoToMatchingBracketAction
									extends RecordableTextAction {

		/**
		 * 
		 */
		private static final long serialVersionUID = -2144358106223772276L;

		public GoToMatchingBracketAction() {
			super(rstaGoToMatchingBracketAction);
		}

		public GoToMatchingBracketAction(String name, Icon icon, String desc,
							Integer mnemonic, KeyStroke accelerator) {
			super(name, icon, desc, mnemonic, accelerator);
		}

		public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
			RSyntaxTextArea rsta = (RSyntaxTextArea)textArea;
			int pos = RSyntaxUtilities.getMatchingBracketPosition(rsta);
			if (pos>-1) {
				// Go to the position AFTER the bracket so the previous
				// bracket (which we were just on) is highlighted.
				rsta.setCaretPosition(pos+1);
			}
			else {
				UIManager.getLookAndFeel().provideErrorFeedback(rsta);
			}
		}

		public final String getMacroID() {
			return rstaGoToMatchingBracketAction;
		}

	}


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


	/**

⌨️ 快捷键说明

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