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

📄 macro.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
字号:
/*
 * 09/16/2004
 *
 * Macro.java - A macro as recorded/played back by an RTextArea.
 * 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.rtextarea;

import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;

import org.fife.io.UnicodeReader;


/**
 * A macro as recorded/played back by an <code>RTextArea</code>.
 *
 * @author Robert Futrell
 * @version 0.1
 */
public class Macro {

	private String name;
	private ArrayList macroRecords;

	private static final String ROOT_ELEMENT			= "macro";
	private static final String MACRO_NAME				= "macroName";
	private static final String ACTION					= "action";
	private static final String ID					= "id";

	private static final String UNTITLED_MACRO_NAME		= "<Untitled>";


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


	/**
	 * Constructor.
	 */
	public Macro() {
		this(UNTITLED_MACRO_NAME);
	}


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


	/**
	 * Loads a macro from a file on disk.
	 *
	 * @param file The file from which to load the macro.
	 * @throws java.io.EOFException If an EOF is reached unexpectedly (i.e.,
	 *                              the file is corrupt).
	 * @throws FileNotFoundException If the specified file does not exist, is
	 *                               a directory instead of a regular file, or
	 *                               otherwise cannot be opened.
	 * @throws IOException If an I/O exception occurs while reading the file.
	 * @see #saveToFile
	 */
	public Macro(File file) throws EOFException, FileNotFoundException,
								IOException {

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		Document doc = null;
		try {
			db = dbf.newDocumentBuilder();
			//InputSource is = new InputSource(new FileReader(file));
			InputSource is = new InputSource(new UnicodeReader(
								new FileInputStream(file), "UTF-8"));
			is.setEncoding("UTF-8");
			doc = db.parse(is);//db.parse(file);
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}

		macroRecords = new ArrayList();

		// Traverse the XML tree.
		boolean parsedOK = initializeFromXMLFile(doc);
		if (parsedOK==false) {
			name = null;
			macroRecords.clear();
			macroRecords = null;
			throw new IOException("Error parsing XML!");
		}

	}


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


	/**
	 * Constructor.
	 *
	 * @param name The name of the macro.
	 */
	public Macro(String name) {
		this(name, null);
	}


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


	/**
	 * Constructor.
	 *
	 * @param name The name of the macro.
	 * @param records The initial records of the macro.
	 */
	public Macro(String name, List records) {
		
		this.name = name;

		if (records!=null) {
			macroRecords = new ArrayList(records.size());
			Iterator i = records.iterator();
			while (i.hasNext()) {
				MacroRecord record = (MacroRecord)i.next();
				macroRecords.add(record);
			}
		}
		else {
			macroRecords = new ArrayList(10);
		}
	
	}


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


	/**
	 * Adds a macro record to this macro.
	 *
	 * @param record The record to add.  If <code>null</code>, nothing happens.
	 * @see #getMacroRecords
	 */
	public void addMacroRecord(MacroRecord record) {
		if (record!=null)
			macroRecords.add(record);
	}


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


	/**
	 * Returns the macro records that make up this macro.
	 *
	 * @return The macro records.
	 * @see #addMacroRecord
	 */
	public List getMacroRecords() {
		return macroRecords;
	}


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


	/**
	 * Returns the name of this macro.
	 *
	 * @return The macro's name.
	 * @see #setName
	 */
	public String getName() {
		return name;
	}


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


	/**
	 * Used in parsing an XML document containing a macro.  This method
	 * initializes this macro with the data contained in the passed-in node.
	 *
	 * @param node The root node of the parsed XML document.
	 * @return <code>true</code> if the macro initialization went okay;
	 *         <code>false</code> if an error occured.
	 */
	private boolean initializeFromXMLFile(Node node) {

		/*
		 * This method expects the XML document to be in the following format:
		 *
		 * <?xml version="1.0" encoding="UTF-8" ?>
		 * <macro>
		 *    <macroName>test</macroName>
		 *    <action id="default-typed">abcdefg</action>
		 *    [<action id=...>...</action>]
		 *    ...
		 * </macro>
		 *
		 */

		if (node==null)
			return false;

		int type = node.getNodeType();
		switch (type) {

			// Handle document nodes.
			case Node.DOCUMENT_NODE:
				boolean rc = initializeFromXMLFile(((Document)node).getDocumentElement());
				if (rc==false)
					return false;
				break;

			// Handle element nodes.
			case Node.ELEMENT_NODE:
				String nodeName = node.getNodeName();
				if (nodeName.equals(MACRO_NAME)) {
					NodeList childNodes = node.getChildNodes();
					if (childNodes==null)
						return false;
					if (childNodes.getLength()==0) {
						// Don't error out, just be "unnamed."
						name = UNTITLED_MACRO_NAME;
					}
					else {
						node = childNodes.item(0);
						if (node.getNodeType()!=Node.TEXT_NODE)
							return false;
						name = node.getNodeValue().trim();
					}
					System.err.println("Macro name==" + name);
				}

				else if (nodeName.equals(ROOT_ELEMENT)) {
					System.err.println("Beginning macro parsing!");
					NodeList childNodes = node.getChildNodes();
					if (childNodes!=null) {
						int length = childNodes.getLength();
						System.err.println("... num child nodes: " + length);
						for (int i=0; i<length; i++) {
							rc = initializeFromXMLFile(childNodes.item(i));
							if (rc==false)
								return false;
						}
					}
					System.err.println("Done with macro parsing!");
				}

				else if (nodeName.equals(ACTION)) {
					NamedNodeMap attributes = node.getAttributes();
					if (attributes==null || attributes.getLength()!=1)
						return false;
					Node node2 = attributes.item(0);
					MacroRecord macroRecord = new MacroRecord();
					if (node2.getNodeType()!=Node.ATTRIBUTE_NODE) {
						System.err.println("not an attribute type...");
						return false;
					}
					if (!node2.getNodeName().equals(ID)) {
						System.err.println("'id' expected but not found...");
						return false;
					}
					macroRecord.id = node2.getNodeValue();
					NodeList childNodes = node.getChildNodes();
					int length = childNodes.getLength();
					if (length==0) { // Could be empty "" command.
						System.err.println("... empty actionCommand");
						macroRecord.actionCommand = "";
						System.err.println("... adding action: " + macroRecord);
						macroRecords.add(macroRecord);
						break;
					}
					else if (length!=1) {
						System.err.println("childNodes invalid - " + childNodes);
						return false;
					}
					node = childNodes.item(0);
					if (node.getNodeType()!=Node.TEXT_NODE) {
						System.err.println("Not a text node...");
						return false;
					}
					macroRecord.actionCommand = node.getNodeValue();
					System.err.println("... adding action: " + macroRecord);
					macroRecords.add(macroRecord);
				}
				break;

			case Node.TEXT_NODE:
				System.err.println("... Throwaway whitespace node: '" + node.getNodeValue() + "'");
				break;

			// An error occured?
			default:
				System.err.println("... ERROR!!!");
				return false;

		}

		// Everything went okay.
		return true;

	}


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


	/**
	 * Saves this macro to a text file.  This file can later be read in by
	 * the constructor taking a <code>File</code> parameter; this is the
	 * mechanism for saving macros.
	 *
	 * @param fileName The name of the file in which to save the macro.
	 * @throws IOException If an error occurs while generating the XML for the
	 *                     output file.
	 */
	public void saveToFile(String fileName) throws IOException {

		/*
		 * This method writes the XML document in the following format:
		 *
		 * <?xml version="1.0" encoding="UTF-8" ?>
		 * <macro>
		 *    <macroName>test</macroName>
		 *    <action id="default-typed">abcdefg</action>
		 *    [<action id=...>...</action>]
		 *    ...
		 * </macro>
		 *
		 */

		try {
			DocumentBuilder db = DocumentBuilderFactory.newInstance().
											newDocumentBuilder();
			DOMImplementation impl = db.getDOMImplementation();

			Document doc = impl.createDocument(null, ROOT_ELEMENT, null);
			Element rootElement = doc.getDocumentElement();

			// Write the name of the macro.
			Element nameElement = doc.createElement(MACRO_NAME);
			rootElement.appendChild(nameElement);

			// Write all actions (the meat) in the macro.
			int numActions = macroRecords.size();
			for (int i=0; i<numActions; i++) {
				MacroRecord record = (MacroRecord)macroRecords.get(i);
				Element actionElement = doc.createElementNS(null, ACTION);
				actionElement.setAttributeNS(null, ID, record.id);
				if (record.actionCommand!=null &&
					!record.actionCommand.equals("")) {
					// Remove illegal characters.  I'm no XML expert, but
					// I'm not sure what I'm doing wrong.  If we don't
					// strip out chars with Unicode value < 32, our
					// generator will insert '&#<value>', which will cause
					// our parser to barf when reading the macro back in
					// (it says "Invalid XML character").  But why doesn't
					// our generator tell us the character is invalid too?
					String command = record.actionCommand;
					for (int j=0; j<command.length(); j++) {
						if (command.charAt(j)<32) {
							command = command.substring(0,j);
							if (j<command.length()-1)
								command += command.substring(j+1);
						}
					}
					Node n = doc.createTextNode(command);
					actionElement.appendChild(n);
				}
				rootElement.appendChild(actionElement);
			}

			// Dump the XML out to the file.
			StreamResult result = new StreamResult(new File(fileName));
			DOMSource source = new DOMSource(doc);
			TransformerFactory transFac = TransformerFactory.newInstance();
			Transformer transformer = transFac.newTransformer();
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			transformer.transform(source, result);

		} catch (Exception e) {
			throw new IOException("Error generating XML!");
		}

	}


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


	/**
	 * Sets the name of this macro.
	 *
	 * @param name The new name for the macro.
	 * @see #getName
	 */
	public void setName(String name) {
		this.name = name;
	}


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


	/**
	 * A "record" of a macro is a single action in the macro (corresponding to
	 * a key type and some action in the editor, such as a letter inserted into
	 * the document, scrolling one page down, selecting the current line,
	 * etc.).
	 */
	static class MacroRecord {

		public String id;
		public String actionCommand;

		public MacroRecord() {
			this(null, null);
		}

		public MacroRecord(String id, String actionCommand) {
			this.id = id;
			this.actionCommand = actionCommand;
		}

	}


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

}

⌨️ 快捷键说明

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