提交 a0226263 编写于 作者: M mrkam

7027697: /jfc/Notepad demo needs to be improved

Reviewed-by: rupashka
上级 a2f14590
/* /*
* Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -29,17 +29,36 @@ ...@@ -29,17 +29,36 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
*/
import javax.swing.*; import java.awt.BorderLayout;
import javax.swing.event.*; import java.awt.Dimension;
import javax.swing.text.*; import java.awt.Font;
import javax.swing.tree.*; import java.beans.PropertyChangeEvent;
import javax.swing.undo.*; import java.beans.PropertyChangeListener;
import java.awt.*;
import java.beans.*;
import java.util.*; import java.util.*;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.JTextComponent;
import javax.swing.text.StyleConstants;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
/** /**
* Displays a tree showing all the elements in a text Document. Selecting * Displays a tree showing all the elements in a text Document. Selecting
...@@ -49,16 +68,20 @@ import java.util.*; ...@@ -49,16 +68,20 @@ import java.util.*;
* *
* @author Scott Violet * @author Scott Violet
*/ */
public class ElementTreePanel extends JPanel implements CaretListener, DocumentListener, PropertyChangeListener, TreeSelectionListener { @SuppressWarnings("serial")
public class ElementTreePanel extends JPanel implements CaretListener,
DocumentListener, PropertyChangeListener, TreeSelectionListener {
/** Tree showing the documents element structure. */ /** Tree showing the documents element structure. */
protected JTree tree; protected JTree tree;
/** Text component showing elemenst for. */ /** Text component showing elemenst for. */
protected JTextComponent editor; protected JTextComponent editor;
/** Model for the tree. */ /** Model for the tree. */
protected ElementTreeModel treeModel; protected ElementTreeModel treeModel;
/** Set to true when updatin the selection. */ /** Set to true when updatin the selection. */
protected boolean updatingSelection; protected boolean updatingSelection;
@SuppressWarnings("LeakingThisInConstructor")
public ElementTreePanel(JTextComponent editor) { public ElementTreePanel(JTextComponent editor) {
this.editor = editor; this.editor = editor;
...@@ -67,25 +90,28 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -67,25 +90,28 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
// Create the tree. // Create the tree.
treeModel = new ElementTreeModel(document); treeModel = new ElementTreeModel(document);
tree = new JTree(treeModel) { tree = new JTree(treeModel) {
@Override
public String convertValueToText(Object value, boolean selected, public String convertValueToText(Object value, boolean selected,
boolean expanded, boolean leaf, boolean expanded, boolean leaf,
int row, boolean hasFocus) { int row, boolean hasFocus) {
// Should only happen for the root // Should only happen for the root
if(!(value instanceof Element)) if (!(value instanceof Element)) {
return value.toString(); return value.toString();
}
Element e = (Element)value; Element e = (Element) value;
AttributeSet as = e.getAttributes().copyAttributes(); AttributeSet as = e.getAttributes().copyAttributes();
String asString; String asString;
if(as != null) { if (as != null) {
StringBuffer retBuffer = new StringBuffer("["); StringBuilder retBuffer = new StringBuilder("[");
Enumeration names = as.getAttributeNames(); Enumeration names = as.getAttributeNames();
while(names.hasMoreElements()) { while (names.hasMoreElements()) {
Object nextName = names.nextElement(); Object nextName = names.nextElement();
if(nextName != StyleConstants.ResolveAttribute) { if (nextName != StyleConstants.ResolveAttribute) {
retBuffer.append(" "); retBuffer.append(" ");
retBuffer.append(nextName); retBuffer.append(nextName);
retBuffer.append("="); retBuffer.append("=");
...@@ -94,16 +120,16 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -94,16 +120,16 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
} }
retBuffer.append(" ]"); retBuffer.append(" ]");
asString = retBuffer.toString(); asString = retBuffer.toString();
} } else {
else
asString = "[ ]"; asString = "[ ]";
}
if(e.isLeaf()) if (e.isLeaf()) {
return e.getName() + " [" + e.getStartOffset() + return e.getName() + " [" + e.getStartOffset() + ", " + e.
", " + e.getEndOffset() +"] Attributes: " + asString; getEndOffset() + "] Attributes: " + asString;
return e.getName() + " [" + e.getStartOffset() + }
", " + e.getEndOffset() + "] Attributes: " + return e.getName() + " [" + e.getStartOffset() + ", " + e.
asString; getEndOffset() + "] Attributes: " + asString;
} }
}; };
tree.addTreeSelectionListener(this); tree.addTreeSelectionListener(this);
...@@ -117,10 +143,13 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -117,10 +143,13 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
// This is a temporary workaround, increase the needed size by 15, // This is a temporary workaround, increase the needed size by 15,
// hoping that will be enough. // hoping that will be enough.
tree.setCellRenderer(new DefaultTreeCellRenderer() { tree.setCellRenderer(new DefaultTreeCellRenderer() {
@Override
public Dimension getPreferredSize() { public Dimension getPreferredSize() {
Dimension retValue = super.getPreferredSize(); Dimension retValue = super.getPreferredSize();
if(retValue != null) if (retValue != null) {
retValue.width += 15; retValue.width += 15;
}
return retValue; return retValue;
} }
}); });
...@@ -139,7 +168,8 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -139,7 +168,8 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
add(new JScrollPane(tree), BorderLayout.CENTER); add(new JScrollPane(tree), BorderLayout.CENTER);
// Add a label above tree to describe what is being shown // Add a label above tree to describe what is being shown
JLabel label = new JLabel("Elements that make up the current document", SwingConstants.CENTER); JLabel label = new JLabel("Elements that make up the current document",
SwingConstants.CENTER);
label.setFont(new Font("Dialog", Font.BOLD, 14)); label.setFont(new Font("Dialog", Font.BOLD, 14));
add(label, BorderLayout.NORTH); add(label, BorderLayout.NORTH);
...@@ -157,7 +187,7 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -157,7 +187,7 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
} }
if (this.editor != null) { if (this.editor != null) {
Document oldDoc = this.editor.getDocument(); Document oldDoc = this.editor.getDocument();
oldDoc.removeDocumentListener(this); oldDoc.removeDocumentListener(this);
this.editor.removePropertyChangeListener(this); this.editor.removePropertyChangeListener(this);
...@@ -167,9 +197,8 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -167,9 +197,8 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
if (editor == null) { if (editor == null) {
treeModel = null; treeModel = null;
tree.setModel(null); tree.setModel(null);
} } else {
else { Document newDoc = editor.getDocument();
Document newDoc = editor.getDocument();
newDoc.addDocumentListener(this); newDoc.addDocumentListener(this);
editor.addPropertyChangeListener(this); editor.addPropertyChangeListener(this);
...@@ -180,17 +209,15 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -180,17 +209,15 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
} }
// PropertyChangeListener // PropertyChangeListener
/** /**
* Invoked when a property changes. We are only interested in when the * Invoked when a property changes. We are only interested in when the
* Document changes to reset the DocumentListener. * Document changes to reset the DocumentListener.
*/ */
public void propertyChange(PropertyChangeEvent e) { public void propertyChange(PropertyChangeEvent e) {
if (e.getSource() == getEditor() && if (e.getSource() == getEditor() && e.getPropertyName().equals(
e.getPropertyName().equals("document")) { "document")) {
JTextComponent editor = getEditor(); Document oldDoc = (Document) e.getOldValue();
Document oldDoc = (Document)e.getOldValue(); Document newDoc = (Document) e.getNewValue();
Document newDoc = (Document)e.getNewValue();
// Reset the DocumentListener // Reset the DocumentListener
oldDoc.removeDocumentListener(this); oldDoc.removeDocumentListener(this);
...@@ -202,9 +229,7 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -202,9 +229,7 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
} }
} }
// DocumentListener // DocumentListener
/** /**
* Gives notification that there was an insert into the document. The * Gives notification that there was an insert into the document. The
* given range bounds the freshly inserted region. * given range bounds the freshly inserted region.
...@@ -236,53 +261,50 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -236,53 +261,50 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
} }
// CaretListener // CaretListener
/** /**
* Messaged when the selection in the editor has changed. Will update * Messaged when the selection in the editor has changed. Will update
* the selection in the tree. * the selection in the tree.
*/ */
public void caretUpdate(CaretEvent e) { public void caretUpdate(CaretEvent e) {
if(!updatingSelection) { if (!updatingSelection) {
JTextComponent editor = getEditor(); int selBegin = Math.min(e.getDot(), e.getMark());
int selBegin = Math.min(e.getDot(), e.getMark()); int end = Math.max(e.getDot(), e.getMark());
int end = Math.max(e.getDot(), e.getMark()); List<TreePath> paths = new ArrayList<TreePath>();
Vector paths = new Vector(); TreeModel model = getTreeModel();
TreeModel model = getTreeModel(); Object root = model.getRoot();
Object root = model.getRoot(); int rootCount = model.getChildCount(root);
int rootCount = model.getChildCount(root);
// Build an array of all the paths to all the character elements // Build an array of all the paths to all the character elements
// in the selection. // in the selection.
for(int counter = 0; counter < rootCount; counter++) { for (int counter = 0; counter < rootCount; counter++) {
int start = selBegin; int start = selBegin;
while(start <= end) { while (start <= end) {
TreePath path = getPathForIndex(start, root, TreePath path = getPathForIndex(start, root,
(Element)model.getChild(root, counter)); (Element) model.getChild(root, counter));
Element charElement = (Element)path. Element charElement = (Element) path.getLastPathComponent();
getLastPathComponent();
paths.addElement(path); paths.add(path);
if(start >= charElement.getEndOffset()) if (start >= charElement.getEndOffset()) {
start++; start++;
else } else {
start = charElement.getEndOffset(); start = charElement.getEndOffset();
}
} }
} }
// If a path was found, select it (them). // If a path was found, select it (them).
int numPaths = paths.size(); int numPaths = paths.size();
if(numPaths > 0) { if (numPaths > 0) {
TreePath[] pathArray = new TreePath[numPaths]; TreePath[] pathArray = new TreePath[numPaths];
paths.copyInto(pathArray); paths.toArray(pathArray);
updatingSelection = true; updatingSelection = true;
try { try {
getTree().setSelectionPaths(pathArray); getTree().setSelectionPaths(pathArray);
getTree().scrollPathToVisible(pathArray[0]); getTree().scrollPathToVisible(pathArray[0]);
} } finally {
finally {
updatingSelection = false; updatingSelection = false;
} }
} }
...@@ -290,27 +312,24 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -290,27 +312,24 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
} }
// TreeSelectionListener // TreeSelectionListener
/** /**
* Called whenever the value of the selection changes. * Called whenever the value of the selection changes.
* @param e the event that characterizes the change. * @param e the event that characterizes the change.
*/ */
public void valueChanged(TreeSelectionEvent e) { public void valueChanged(TreeSelectionEvent e) {
JTree tree = getTree();
if(!updatingSelection && tree.getSelectionCount() == 1) { if (!updatingSelection && tree.getSelectionCount() == 1) {
TreePath selPath = tree.getSelectionPath(); TreePath selPath = tree.getSelectionPath();
Object lastPathComponent = selPath.getLastPathComponent(); Object lastPathComponent = selPath.getLastPathComponent();
if(!(lastPathComponent instanceof DefaultMutableTreeNode)) { if (!(lastPathComponent instanceof DefaultMutableTreeNode)) {
Element selElement = (Element)lastPathComponent; Element selElement = (Element) lastPathComponent;
updatingSelection = true; updatingSelection = true;
try { try {
getEditor().select(selElement.getStartOffset(), getEditor().select(selElement.getStartOffset(),
selElement.getEndOffset()); selElement.getEndOffset());
} } finally {
finally {
updatingSelection = false; updatingSelection = false;
} }
} }
...@@ -318,7 +337,6 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -318,7 +337,6 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
} }
// Local methods // Local methods
/** /**
* @return tree showing elements. * @return tree showing elements.
*/ */
...@@ -347,15 +365,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -347,15 +365,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
protected void updateTree(DocumentEvent event) { protected void updateTree(DocumentEvent event) {
updatingSelection = true; updatingSelection = true;
try { try {
TreeModel model = getTreeModel(); TreeModel model = getTreeModel();
Object root = model.getRoot(); Object root = model.getRoot();
for(int counter = model.getChildCount(root) - 1; counter >= 0; for (int counter = model.getChildCount(root) - 1; counter >= 0;
counter--) { counter--) {
updateTree(event, (Element)model.getChild(root, counter)); updateTree(event, (Element) model.getChild(root, counter));
} }
} } finally {
finally {
updatingSelection = false; updatingSelection = false;
} }
} }
...@@ -372,53 +389,50 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -372,53 +389,50 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
DocumentEvent.ElementChange ec = event.getChange(element); DocumentEvent.ElementChange ec = event.getChange(element);
if (ec != null) { if (ec != null) {
Element[] removed = ec.getChildrenRemoved(); Element[] removed = ec.getChildrenRemoved();
Element[] added = ec.getChildrenAdded(); Element[] added = ec.getChildrenAdded();
int startIndex = ec.getIndex(); int startIndex = ec.getIndex();
// Check for removed. // Check for removed.
if(removed != null && removed.length > 0) { if (removed != null && removed.length > 0) {
int[] indices = new int[removed.length]; int[] indices = new int[removed.length];
for(int counter = 0; counter < removed.length; counter++) { for (int counter = 0; counter < removed.length; counter++) {
indices[counter] = startIndex + counter; indices[counter] = startIndex + counter;
} }
getTreeModel().nodesWereRemoved((TreeNode)element, indices, getTreeModel().nodesWereRemoved((TreeNode) element, indices,
removed); removed);
} }
// check for added // check for added
if(added != null && added.length > 0) { if (added != null && added.length > 0) {
int[] indices = new int[added.length]; int[] indices = new int[added.length];
for(int counter = 0; counter < added.length; counter++) { for (int counter = 0; counter < added.length; counter++) {
indices[counter] = startIndex + counter; indices[counter] = startIndex + counter;
} }
getTreeModel().nodesWereInserted((TreeNode)element, indices); getTreeModel().nodesWereInserted((TreeNode) element, indices);
} }
} }
if(!element.isLeaf()) { if (!element.isLeaf()) {
int startIndex = element.getElementIndex int startIndex = element.getElementIndex(event.getOffset());
(event.getOffset()); int elementCount = element.getElementCount();
int elementCount = element.getElementCount(); int endIndex = Math.min(elementCount - 1,
int endIndex = Math.min(elementCount - 1, element.getElementIndex(event.getOffset()
element.getElementIndex + event.getLength()));
(event.getOffset() + event.getLength()));
if (startIndex > 0 && startIndex < elementCount && element.
if(startIndex > 0 && startIndex < elementCount && getElement(startIndex).getStartOffset() == event.getOffset()) {
element.getElement(startIndex).getStartOffset() ==
event.getOffset()) {
// Force checking the previous element. // Force checking the previous element.
startIndex--; startIndex--;
} }
if(startIndex != -1 && endIndex != -1) { if (startIndex != -1 && endIndex != -1) {
for(int counter = startIndex; counter <= endIndex; counter++) { for (int counter = startIndex; counter <= endIndex; counter++) {
updateTree(event, element.getElement(counter)); updateTree(event, element.getElement(counter));
} }
} }
} } else {
else {
// Element is a leaf, assume it changed // Element is a leaf, assume it changed
getTreeModel().nodeChanged((TreeNode)element); getTreeModel().nodeChanged((TreeNode) element);
} }
} }
...@@ -426,14 +440,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -426,14 +440,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
* Returns a TreePath to the element at <code>position</code>. * Returns a TreePath to the element at <code>position</code>.
*/ */
protected TreePath getPathForIndex(int position, Object root, protected TreePath getPathForIndex(int position, Object root,
Element rootElement) { Element rootElement) {
TreePath path = new TreePath(root); TreePath path = new TreePath(root);
Element child = rootElement.getElement Element child = rootElement.getElement(rootElement.getElementIndex(
(rootElement.getElementIndex(position)); position));
path = path.pathByAddingChild(rootElement); path = path.pathByAddingChild(rootElement);
path = path.pathByAddingChild(child); path = path.pathByAddingChild(child);
while(!child.isLeaf()) { while (!child.isLeaf()) {
child = child.getElement(child.getElementIndex(position)); child = child.getElement(child.getElementIndex(position));
path = path.pathByAddingChild(child); path = path.pathByAddingChild(child);
} }
...@@ -456,7 +470,8 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -456,7 +470,8 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
* methods have been subclassed, primarily to special case the root. * methods have been subclassed, primarily to special case the root.
*/ */
public static class ElementTreeModel extends DefaultTreeModel { public static class ElementTreeModel extends DefaultTreeModel {
protected Element[] rootElements;
protected Element[] rootElements;
public ElementTreeModel(Document document) { public ElementTreeModel(Document document) {
super(new DefaultMutableTreeNode("root"), false); super(new DefaultMutableTreeNode("root"), false);
...@@ -474,13 +489,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -474,13 +489,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
* @param parent a node in the tree, obtained from this data source * @param parent a node in the tree, obtained from this data source
* @return the child of <I>parent</I> at index <I>index</I> * @return the child of <I>parent</I> at index <I>index</I>
*/ */
@Override
public Object getChild(Object parent, int index) { public Object getChild(Object parent, int index) {
if(parent == root) if (parent == root) {
return rootElements[index]; return rootElements[index];
}
return super.getChild(parent, index); return super.getChild(parent, index);
} }
/** /**
* Returns the number of children of <I>parent</I>. Returns 0 * Returns the number of children of <I>parent</I>. Returns 0
* if the node is a leaf or if it has no children. * if the node is a leaf or if it has no children.
...@@ -490,13 +506,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -490,13 +506,14 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
* @param parent a node in the tree, obtained from this data source * @param parent a node in the tree, obtained from this data source
* @return the number of children of the node <I>parent</I> * @return the number of children of the node <I>parent</I>
*/ */
@Override
public int getChildCount(Object parent) { public int getChildCount(Object parent) {
if(parent == root) if (parent == root) {
return rootElements.length; return rootElements.length;
}
return super.getChildCount(parent); return super.getChildCount(parent);
} }
/** /**
* Returns true if <I>node</I> is a leaf. It is possible for * Returns true if <I>node</I> is a leaf. It is possible for
* this method to return false even if <I>node</I> has no * this method to return false even if <I>node</I> has no
...@@ -507,21 +524,25 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -507,21 +524,25 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
* @param node a node in the tree, obtained from this data source * @param node a node in the tree, obtained from this data source
* @return true if <I>node</I> is a leaf * @return true if <I>node</I> is a leaf
*/ */
@Override
public boolean isLeaf(Object node) { public boolean isLeaf(Object node) {
if(node == root) if (node == root) {
return false; return false;
}
return super.isLeaf(node); return super.isLeaf(node);
} }
/** /**
* Returns the index of child in parent. * Returns the index of child in parent.
*/ */
@Override
public int getIndexOfChild(Object parent, Object child) { public int getIndexOfChild(Object parent, Object child) {
if(parent == root) { if (parent == root) {
for(int counter = rootElements.length - 1; counter >= 0; for (int counter = rootElements.length - 1; counter >= 0;
counter--) { counter--) {
if(rootElements[counter] == child) if (rootElements[counter] == child) {
return counter; return counter;
}
} }
return -1; return -1;
} }
...@@ -532,18 +553,19 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -532,18 +553,19 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
* Invoke this method after you've changed how node is to be * Invoke this method after you've changed how node is to be
* represented in the tree. * represented in the tree.
*/ */
@Override
public void nodeChanged(TreeNode node) { public void nodeChanged(TreeNode node) {
if(listenerList != null && node != null) { if (listenerList != null && node != null) {
TreeNode parent = node.getParent(); TreeNode parent = node.getParent();
if(parent == null && node != root) { if (parent == null && node != root) {
parent = root; parent = root;
} }
if(parent != null) { if (parent != null) {
int anIndex = getIndexOfChild(parent, node); int anIndex = getIndexOfChild(parent, node);
if(anIndex != -1) { if (anIndex != -1) {
int[] cIndexs = new int[1]; int[] cIndexs = new int[1];
cIndexs[0] = anIndex; cIndexs[0] = anIndex;
nodesChanged(parent, cIndexs); nodesChanged(parent, cIndexs);
...@@ -555,26 +577,28 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL ...@@ -555,26 +577,28 @@ public class ElementTreePanel extends JPanel implements CaretListener, DocumentL
/** /**
* Returns the path to a particluar node. This is recursive. * Returns the path to a particluar node. This is recursive.
*/ */
@Override
protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) { protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) {
TreeNode[] retNodes; TreeNode[] retNodes;
/* Check for null, in case someone passed in a null node, or /* Check for null, in case someone passed in a null node, or
they passed in an element that isn't rooted at root. */ they passed in an element that isn't rooted at root. */
if(aNode == null) { if (aNode == null) {
if(depth == 0) if (depth == 0) {
return null; return null;
else } else {
retNodes = new TreeNode[depth]; retNodes = new TreeNode[depth];
} }
else { } else {
depth++; depth++;
if(aNode == root) if (aNode == root) {
retNodes = new TreeNode[depth]; retNodes = new TreeNode[depth];
else { } else {
TreeNode parent = aNode.getParent(); TreeNode parent = aNode.getParent();
if(parent == null) if (parent == null) {
parent = root; parent = root;
}
retNodes = getPathToRoot(parent, depth); retNodes = getPathToRoot(parent, depth);
} }
retNodes[retNodes.length - depth] = aNode; retNodes[retNodes.length - depth] = aNode;
......
/* /*
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -29,20 +29,73 @@ ...@@ -29,20 +29,73 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
*/
import java.awt.*; import java.awt.BorderLayout;
import java.awt.event.*; import java.awt.Color;
import java.beans.*; import java.awt.Component;
import java.io.*; import java.awt.Container;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;
import javax.swing.text.Segment;
import javax.swing.text.TextAction;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.text.*;
import javax.swing.undo.*;
import javax.swing.event.*;
import javax.swing.*;
/** /**
* Sample application using the simple text editor component that * Sample application using the simple text editor component that
...@@ -50,22 +103,24 @@ import javax.swing.*; ...@@ -50,22 +103,24 @@ import javax.swing.*;
* *
* @author Timothy Prinzing * @author Timothy Prinzing
*/ */
@SuppressWarnings("serial")
class Notepad extends JPanel { class Notepad extends JPanel {
private static ResourceBundle resources; private static ResourceBundle resources;
private final static String EXIT_AFTER_PAINT = new String("-exit"); private final static String EXIT_AFTER_PAINT = "-exit";
private static boolean exitAfterFirstPaint; private static boolean exitAfterFirstPaint;
static { static {
try { try {
resources = ResourceBundle.getBundle("resources.Notepad", resources = ResourceBundle.getBundle("resources.Notepad",
Locale.getDefault()); Locale.getDefault());
} catch (MissingResourceException mre) { } catch (MissingResourceException mre) {
System.err.println("resources/Notepad.properties not found"); System.err.println("resources/Notepad.properties not found");
System.exit(1); System.exit(1);
} }
} }
@Override
public void paintChildren(Graphics g) { public void paintChildren(Graphics g) {
super.paintChildren(g); super.paintChildren(g);
if (exitAfterFirstPaint) { if (exitAfterFirstPaint) {
...@@ -73,17 +128,19 @@ class Notepad extends JPanel { ...@@ -73,17 +128,19 @@ class Notepad extends JPanel {
} }
} }
@SuppressWarnings("OverridableMethodCallInConstructor")
Notepad() { Notepad() {
super(true); super(true);
// Force SwingSet to come up in the Cross Platform L&F // Trying to set Nimbus look and feel
try { try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
// If you want the System L&F instead, comment out the above line and if ("Nimbus".equals(info.getName())) {
// uncomment the following: UIManager.setLookAndFeel(info.getClassName());
// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); break;
} catch (Exception exc) { }
System.err.println("Error loading L&F: " + exc); }
} catch (Exception ignored) {
} }
setBorder(BorderFactory.createEtchedBorder()); setBorder(BorderFactory.createEtchedBorder());
...@@ -95,7 +152,7 @@ class Notepad extends JPanel { ...@@ -95,7 +152,7 @@ class Notepad extends JPanel {
editor.getDocument().addUndoableEditListener(undoHandler); editor.getDocument().addUndoableEditListener(undoHandler);
// install the command table // install the command table
commands = new Hashtable(); commands = new HashMap<Object, Action>();
Action[] actions = getActions(); Action[] actions = getActions();
for (int i = 0; i < actions.length; i++) { for (int i = 0; i < actions.length; i++) {
Action a = actions[i]; Action a = actions[i];
...@@ -109,15 +166,17 @@ class Notepad extends JPanel { ...@@ -109,15 +166,17 @@ class Notepad extends JPanel {
try { try {
String vpFlag = resources.getString("ViewportBackingStore"); String vpFlag = resources.getString("ViewportBackingStore");
Boolean bs = Boolean.valueOf(vpFlag); Boolean bs = Boolean.valueOf(vpFlag);
port.setBackingStoreEnabled(bs.booleanValue()); port.setScrollMode(bs.booleanValue()
} catch (MissingResourceException mre) { ? JViewport.BACKINGSTORE_SCROLL_MODE
: JViewport.BLIT_SCROLL_MODE);
} catch (MissingResourceException ignored) {
// just use the viewport default // just use the viewport default
} }
menuItems = new Hashtable(); menuItems = new HashMap<String, JMenuItem>();
JPanel panel = new JPanel(); JPanel panel = new JPanel();
panel.setLayout(new BorderLayout()); panel.setLayout(new BorderLayout());
panel.add("North",createToolbar()); panel.add("North", createToolbar());
panel.add("Center", scroller); panel.add("Center", scroller);
add("Center", panel); add("Center", panel);
add("South", createStatusbar()); add("South", createStatusbar());
...@@ -125,28 +184,28 @@ class Notepad extends JPanel { ...@@ -125,28 +184,28 @@ class Notepad extends JPanel {
public static void main(String[] args) { public static void main(String[] args) {
try { try {
String vers = System.getProperty("java.version"); if (args.length > 0 && args[0].equals(EXIT_AFTER_PAINT)) {
if (vers.compareTo("1.1.2") < 0) { exitAfterFirstPaint = true;
System.out.println("!!!WARNING: Swing must be run with a " + }
"1.1.2 or higher version VM!!!"); SwingUtilities.invokeAndWait(new Runnable() {
}
if (args.length > 0 && args[0].equals(EXIT_AFTER_PAINT)) { public void run() {
exitAfterFirstPaint = true; JFrame frame = new JFrame();
} frame.setTitle(resources.getString("Title"));
JFrame frame = new JFrame(); frame.setBackground(Color.lightGray);
frame.setTitle(resources.getString("Title")); frame.getContentPane().setLayout(new BorderLayout());
frame.setBackground(Color.lightGray); Notepad notepad = new Notepad();
frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add("Center", notepad);
Notepad notepad = new Notepad(); frame.setJMenuBar(notepad.createMenubar());
frame.getContentPane().add("Center", notepad); frame.addWindowListener(new AppCloser());
frame.setJMenuBar(notepad.createMenubar()); frame.pack();
frame.addWindowListener(new AppCloser()); frame.setSize(500, 600);
frame.pack(); frame.setVisible(true);
frame.setSize(500, 600); }
frame.show(); });
} catch (Throwable t) { } catch (Throwable t) {
System.out.println("uncaught exception: " + t); Logger.getLogger(Notepad.class.getName()).log(Level.SEVERE,
t.printStackTrace(); "uncaught exception", t);
} }
} }
...@@ -177,6 +236,7 @@ class Notepad extends JPanel { ...@@ -177,6 +236,7 @@ class Notepad extends JPanel {
return editor; return editor;
} }
/** /**
* To shutdown when run as an application. This is a * To shutdown when run as an application. This is a
* fairly lame implementation. A more self-respecting * fairly lame implementation. A more self-respecting
...@@ -184,6 +244,8 @@ class Notepad extends JPanel { ...@@ -184,6 +244,8 @@ class Notepad extends JPanel {
* was needed. * was needed.
*/ */
protected static final class AppCloser extends WindowAdapter { protected static final class AppCloser extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
System.exit(0); System.exit(0);
} }
...@@ -239,11 +301,11 @@ class Notepad extends JPanel { ...@@ -239,11 +301,11 @@ class Notepad extends JPanel {
* if one wasn't created. * if one wasn't created.
*/ */
protected JMenuItem getMenuItem(String cmd) { protected JMenuItem getMenuItem(String cmd) {
return (JMenuItem) menuItems.get(cmd); return menuItems.get(cmd);
} }
protected Action getAction(String cmd) { protected Action getAction(String cmd) {
return (Action) commands.get(cmd); return commands.get(cmd);
} }
protected String getResourceString(String nm) { protected String getResourceString(String nm) {
...@@ -328,10 +390,14 @@ class Notepad extends JPanel { ...@@ -328,10 +390,14 @@ class Notepad extends JPanel {
protected JButton createToolbarButton(String key) { protected JButton createToolbarButton(String key) {
URL url = getResource(key + imageSuffix); URL url = getResource(key + imageSuffix);
JButton b = new JButton(new ImageIcon(url)) { JButton b = new JButton(new ImageIcon(url)) {
public float getAlignmentY() { return 0.5f; }
@Override
public float getAlignmentY() {
return 0.5f;
}
}; };
b.setRequestFocusEnabled(false); b.setRequestFocusEnabled(false);
b.setMargin(new Insets(1,1,1,1)); b.setMargin(new Insets(1, 1, 1, 1));
String astr = getResourceString(key + actionSuffix); String astr = getResourceString(key + actionSuffix);
if (astr == null) { if (astr == null) {
...@@ -360,15 +426,17 @@ class Notepad extends JPanel { ...@@ -360,15 +426,17 @@ class Notepad extends JPanel {
* resource file. * resource file.
*/ */
protected String[] tokenize(String input) { protected String[] tokenize(String input) {
Vector v = new Vector(); List<String> v = new ArrayList<String>();
StringTokenizer t = new StringTokenizer(input); StringTokenizer t = new StringTokenizer(input);
String cmd[]; String cmd[];
while (t.hasMoreTokens()) while (t.hasMoreTokens()) {
v.addElement(t.nextToken()); v.add(t.nextToken());
}
cmd = new String[v.size()]; cmd = new String[v.size()];
for (int i = 0; i < cmd.length; i++) for (int i = 0; i < cmd.length; i++) {
cmd[i] = (String) v.elementAt(i); cmd[i] = v.get(i);
}
return cmd; return cmd;
} }
...@@ -416,13 +484,16 @@ class Notepad extends JPanel { ...@@ -416,13 +484,16 @@ class Notepad extends JPanel {
} }
// Yarked from JMenu, ideally this would be public. // Yarked from JMenu, ideally this would be public.
private class ActionChangedListener implements PropertyChangeListener { private class ActionChangedListener implements PropertyChangeListener {
JMenuItem menuItem; JMenuItem menuItem;
ActionChangedListener(JMenuItem mi) { ActionChangedListener(JMenuItem mi) {
super(); super();
this.menuItem = mi; this.menuItem = mi;
} }
public void propertyChange(PropertyChangeEvent e) { public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName(); String propertyName = e.getPropertyName();
if (e.getPropertyName().equals(Action.NAME)) { if (e.getPropertyName().equals(Action.NAME)) {
...@@ -434,56 +505,48 @@ class Notepad extends JPanel { ...@@ -434,56 +505,48 @@ class Notepad extends JPanel {
} }
} }
} }
private JTextComponent editor; private JTextComponent editor;
private Hashtable commands; private Map<Object, Action> commands;
private Hashtable menuItems; private Map<String, JMenuItem> menuItems;
private JMenuBar menubar; private JMenuBar menubar;
private JToolBar toolbar; private JToolBar toolbar;
private JComponent status; private JComponent status;
private JFrame elementTreeFrame; private JFrame elementTreeFrame;
protected ElementTreePanel elementTreePanel; protected ElementTreePanel elementTreePanel;
protected FileDialog fileDialog; protected FileDialog fileDialog;
/** /**
* Listener for the edits on the current document. * Listener for the edits on the current document.
*/ */
protected UndoableEditListener undoHandler = new UndoHandler(); protected UndoableEditListener undoHandler = new UndoHandler();
/** UndoManager that we add edits to. */ /** UndoManager that we add edits to. */
protected UndoManager undo = new UndoManager(); protected UndoManager undo = new UndoManager();
/** /**
* Suffix applied to the key used in resource file * Suffix applied to the key used in resource file
* lookups for an image. * lookups for an image.
*/ */
public static final String imageSuffix = "Image"; public static final String imageSuffix = "Image";
/** /**
* Suffix applied to the key used in resource file * Suffix applied to the key used in resource file
* lookups for a label. * lookups for a label.
*/ */
public static final String labelSuffix = "Label"; public static final String labelSuffix = "Label";
/** /**
* Suffix applied to the key used in resource file * Suffix applied to the key used in resource file
* lookups for an action. * lookups for an action.
*/ */
public static final String actionSuffix = "Action"; public static final String actionSuffix = "Action";
/** /**
* Suffix applied to the key used in resource file * Suffix applied to the key used in resource file
* lookups for tooltip text. * lookups for tooltip text.
*/ */
public static final String tipSuffix = "Tooltip"; public static final String tipSuffix = "Tooltip";
public static final String openAction = "open"; public static final String openAction = "open";
public static final String newAction = "new"; public static final String newAction = "new";
public static final String saveAction = "save"; public static final String saveAction = "save";
public static final String exitAction = "exit"; public static final String exitAction = "exit";
public static final String showElementTreeAction = "showElementTree"; public static final String showElementTreeAction = "showElementTree";
class UndoHandler implements UndoableEditListener { class UndoHandler implements UndoableEditListener {
/** /**
...@@ -497,6 +560,7 @@ class Notepad extends JPanel { ...@@ -497,6 +560,7 @@ class Notepad extends JPanel {
} }
} }
/** /**
* FIXME - I'm not very useful yet * FIXME - I'm not very useful yet
*/ */
...@@ -507,17 +571,14 @@ class Notepad extends JPanel { ...@@ -507,17 +571,14 @@ class Notepad extends JPanel {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
} }
@Override
public void paint(Graphics g) { public void paint(Graphics g) {
super.paint(g); super.paint(g);
} }
} }
// --- action implementations ----------------------------------- // --- action implementations -----------------------------------
private UndoAction undoAction = new UndoAction(); private UndoAction undoAction = new UndoAction();
private RedoAction redoAction = new RedoAction(); private RedoAction redoAction = new RedoAction();
/** /**
* Actions defined by the Notepad class * Actions defined by the Notepad class
*/ */
...@@ -531,7 +592,9 @@ class Notepad extends JPanel { ...@@ -531,7 +592,9 @@ class Notepad extends JPanel {
redoAction redoAction
}; };
class UndoAction extends AbstractAction { class UndoAction extends AbstractAction {
public UndoAction() { public UndoAction() {
super("Undo"); super("Undo");
setEnabled(false); setEnabled(false);
...@@ -541,26 +604,27 @@ class Notepad extends JPanel { ...@@ -541,26 +604,27 @@ class Notepad extends JPanel {
try { try {
undo.undo(); undo.undo();
} catch (CannotUndoException ex) { } catch (CannotUndoException ex) {
System.out.println("Unable to undo: " + ex); Logger.getLogger(UndoAction.class.getName()).log(Level.SEVERE,
ex.printStackTrace(); "Unable to undo", ex);
} }
update(); update();
redoAction.update(); redoAction.update();
} }
protected void update() { protected void update() {
if(undo.canUndo()) { if (undo.canUndo()) {
setEnabled(true); setEnabled(true);
putValue(Action.NAME, undo.getUndoPresentationName()); putValue(Action.NAME, undo.getUndoPresentationName());
} } else {
else {
setEnabled(false); setEnabled(false);
putValue(Action.NAME, "Undo"); putValue(Action.NAME, "Undo");
} }
} }
} }
class RedoAction extends AbstractAction { class RedoAction extends AbstractAction {
public RedoAction() { public RedoAction() {
super("Redo"); super("Redo");
setEnabled(false); setEnabled(false);
...@@ -570,31 +634,32 @@ class Notepad extends JPanel { ...@@ -570,31 +634,32 @@ class Notepad extends JPanel {
try { try {
undo.redo(); undo.redo();
} catch (CannotRedoException ex) { } catch (CannotRedoException ex) {
System.out.println("Unable to redo: " + ex); Logger.getLogger(RedoAction.class.getName()).log(Level.SEVERE,
ex.printStackTrace(); "Unable to redo", ex);
} }
update(); update();
undoAction.update(); undoAction.update();
} }
protected void update() { protected void update() {
if(undo.canRedo()) { if (undo.canRedo()) {
setEnabled(true); setEnabled(true);
putValue(Action.NAME, undo.getRedoPresentationName()); putValue(Action.NAME, undo.getRedoPresentationName());
} } else {
else {
setEnabled(false); setEnabled(false);
putValue(Action.NAME, "Redo"); putValue(Action.NAME, "Redo");
} }
} }
} }
class OpenAction extends NewAction { class OpenAction extends NewAction {
OpenAction() { OpenAction() {
super(openAction); super(openAction);
} }
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
Frame frame = getFrame(); Frame frame = getFrame();
JFileChooser chooser = new JFileChooser(); JFileChooser chooser = new JFileChooser();
...@@ -607,8 +672,9 @@ class Notepad extends JPanel { ...@@ -607,8 +672,9 @@ class Notepad extends JPanel {
File f = chooser.getSelectedFile(); File f = chooser.getSelectedFile();
if (f.isFile() && f.canRead()) { if (f.isFile() && f.canRead()) {
Document oldDoc = getEditor().getDocument(); Document oldDoc = getEditor().getDocument();
if(oldDoc != null) if (oldDoc != null) {
oldDoc.removeUndoableEditListener(undoHandler); oldDoc.removeUndoableEditListener(undoHandler);
}
if (elementTreePanel != null) { if (elementTreePanel != null) {
elementTreePanel.setEditor(null); elementTreePanel.setEditor(null);
} }
...@@ -625,6 +691,7 @@ class Notepad extends JPanel { ...@@ -625,6 +691,7 @@ class Notepad extends JPanel {
} }
} }
class SaveAction extends AbstractAction { class SaveAction extends AbstractAction {
SaveAction() { SaveAction() {
...@@ -647,6 +714,7 @@ class Notepad extends JPanel { ...@@ -647,6 +714,7 @@ class Notepad extends JPanel {
} }
} }
class NewAction extends AbstractAction { class NewAction extends AbstractAction {
NewAction() { NewAction() {
...@@ -659,8 +727,9 @@ class Notepad extends JPanel { ...@@ -659,8 +727,9 @@ class Notepad extends JPanel {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
Document oldDoc = getEditor().getDocument(); Document oldDoc = getEditor().getDocument();
if(oldDoc != null) if (oldDoc != null) {
oldDoc.removeUndoableEditListener(undoHandler); oldDoc.removeUndoableEditListener(undoHandler);
}
getEditor().setDocument(new PlainDocument()); getEditor().setDocument(new PlainDocument());
getEditor().getDocument().addUndoableEditListener(undoHandler); getEditor().getDocument().addUndoableEditListener(undoHandler);
resetUndoManager(); resetUndoManager();
...@@ -669,6 +738,7 @@ class Notepad extends JPanel { ...@@ -669,6 +738,7 @@ class Notepad extends JPanel {
} }
} }
/** /**
* Really lame implementation of an exit command * Really lame implementation of an exit command
*/ */
...@@ -683,6 +753,7 @@ class Notepad extends JPanel { ...@@ -683,6 +753,7 @@ class Notepad extends JPanel {
} }
} }
/** /**
* Action that brings up a JFrame with a JTree showing the structure * Action that brings up a JFrame with a JTree showing the structure
* of the document. * of the document.
...@@ -698,18 +769,19 @@ class Notepad extends JPanel { ...@@ -698,18 +769,19 @@ class Notepad extends JPanel {
} }
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if(elementTreeFrame == null) { if (elementTreeFrame == null) {
// Create a frame containing an instance of // Create a frame containing an instance of
// ElementTreePanel. // ElementTreePanel.
try { try {
String title = resources.getString String title = resources.getString("ElementTreeFrameTitle");
("ElementTreeFrameTitle");
elementTreeFrame = new JFrame(title); elementTreeFrame = new JFrame(title);
} catch (MissingResourceException mre) { } catch (MissingResourceException mre) {
elementTreeFrame = new JFrame(); elementTreeFrame = new JFrame();
} }
elementTreeFrame.addWindowListener(new WindowAdapter() { elementTreeFrame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent weeee) { public void windowClosing(WindowEvent weeee) {
elementTreeFrame.setVisible(false); elementTreeFrame.setVisible(false);
} }
...@@ -721,10 +793,11 @@ class Notepad extends JPanel { ...@@ -721,10 +793,11 @@ class Notepad extends JPanel {
fContentPane.add(elementTreePanel); fContentPane.add(elementTreePanel);
elementTreeFrame.pack(); elementTreeFrame.pack();
} }
elementTreeFrame.show(); elementTreeFrame.setVisible(true);
} }
} }
/** /**
* Thread to load a file into the text storage model * Thread to load a file into the text storage model
*/ */
...@@ -736,6 +809,7 @@ class Notepad extends JPanel { ...@@ -736,6 +809,7 @@ class Notepad extends JPanel {
this.doc = doc; this.doc = doc;
} }
@Override
public void run() { public void run() {
try { try {
// initialize the statusbar // initialize the statusbar
...@@ -751,22 +825,22 @@ class Notepad extends JPanel { ...@@ -751,22 +825,22 @@ class Notepad extends JPanel {
char[] buff = new char[4096]; char[] buff = new char[4096];
int nch; int nch;
while ((nch = in.read(buff, 0, buff.length)) != -1) { while ((nch = in.read(buff, 0, buff.length)) != -1) {
doc.insertString(doc.getLength(), new String(buff, 0, nch), null); doc.insertString(doc.getLength(), new String(buff, 0, nch),
null);
progress.setValue(progress.getValue() + nch); progress.setValue(progress.getValue() + nch);
} }
} } catch (IOException e) {
catch (IOException e) {
final String msg = e.getMessage(); final String msg = e.getMessage();
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
public void run() { public void run() {
JOptionPane.showMessageDialog(getFrame(), JOptionPane.showMessageDialog(getFrame(),
"Could not open file: " + msg, "Could not open file: " + msg,
"Error opening file", "Error opening file",
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} }
}); });
} } catch (BadLocationException e) {
catch (BadLocationException e) {
System.err.println(e.getMessage()); System.err.println(e.getMessage());
} }
doc.addUndoableEditListener(undoHandler); doc.addUndoableEditListener(undoHandler);
...@@ -778,21 +852,23 @@ class Notepad extends JPanel { ...@@ -778,21 +852,23 @@ class Notepad extends JPanel {
if (elementTreePanel != null) { if (elementTreePanel != null) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
public void run() { public void run() {
elementTreePanel.setEditor(getEditor()); elementTreePanel.setEditor(getEditor());
} }
}); });
} }
} }
Document doc; Document doc;
File f; File f;
} }
/** /**
* Thread to save a document to file * Thread to save a document to file
*/ */
class FileSaver extends Thread { class FileSaver extends Thread {
Document doc; Document doc;
File f; File f;
...@@ -802,13 +878,15 @@ class Notepad extends JPanel { ...@@ -802,13 +878,15 @@ class Notepad extends JPanel {
this.doc = doc; this.doc = doc;
} }
@Override
@SuppressWarnings("SleepWhileHoldingLock")
public void run() { public void run() {
try { try {
// initialize the statusbar // initialize the statusbar
status.removeAll(); status.removeAll();
JProgressBar progress = new JProgressBar(); JProgressBar progress = new JProgressBar();
progress.setMinimum(0); progress.setMinimum(0);
progress.setMaximum((int) doc.getLength()); progress.setMaximum(doc.getLength());
status.add(progress); status.add(progress);
status.revalidate(); status.revalidate();
...@@ -827,24 +905,25 @@ class Notepad extends JPanel { ...@@ -827,24 +905,25 @@ class Notepad extends JPanel {
try { try {
Thread.sleep(10); Thread.sleep(10);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); Logger.getLogger(FileSaver.class.getName()).log(
Level.SEVERE,
null, e);
} }
} }
out.flush(); out.flush();
out.close(); out.close();
} } catch (IOException e) {
catch (IOException e) {
final String msg = e.getMessage(); final String msg = e.getMessage();
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
public void run() { public void run() {
JOptionPane.showMessageDialog(getFrame(), JOptionPane.showMessageDialog(getFrame(),
"Could not save file: " + msg, "Could not save file: " + msg,
"Error saving file", "Error saving file",
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} }
}); });
} } catch (BadLocationException e) {
catch (BadLocationException e) {
System.err.println(e.getMessage()); System.err.println(e.getMessage());
} }
// we are done... get rid of progressbar // we are done... get rid of progressbar
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册