I don't think this is a new issue. But it seems that there is an error that comes up whenever an ordered/unordered list in JTextPane (EditorKit -> HTMLEditorKit, Document -> HTMLDocument) is deleted from all the way down to the top using the backspace key. The following is the exception thrown from the getText () method of GlyphView.
Exception in thread "AWT-EventQueue-0" javax.swing.text.StateInvariantError: GlyphView: Stale view: javax.swing.text.BadLocationException: Invalid location
I can provide a SSCCE for this. But it is not very difficult to simulate. Just use a JTextPane with HTMLEditorKit and HTMLDOcument model set inside it. Either use the custom "InsertOrderedList" action or have some way to insert the string
<HTML><HEAD></HEAD><BODY><UL><LI></LI></UL></BODY></HTML>
which will result in the insertion of an ordered/unordered list inside the text pane.
The weird parts of this bug are as follows:
Once you start deleting the characters (and if you happen to have lines below the bulleted list), the characters will get deleted until you hit the last character of the last bullet item. Once you reach this, the caret just refuses to move up and the error from GlyphView gets thrown.
Sometimes what happens is that after you have deleted most of the characters - you still won't be able to delete the first bullet of the list. It just hangs on until you do a ctrl+a and then backspace.
I have seen these bugs in almost all Java based HTML editors available online except for JWebEngine, where this behavior is not present. Unfortunately JWebEngine is not open sourced and hence I can't take a peek inside their code to see as to how they have solved this problem.
My guess is that the notification that is coming from the HTML document model has some problem due to which the cursor positioning code is not working correctly. I have also searched the Sun bugs database to check if this particular issue has been raised but could not find any (though I have seen quite a few bugs which are very similar to this). Also I am very sure that someone must have noticed this before and must have brought it to the Swing team's attention.
Does anyone working with Swing (particularly text) part know as to if this issue has been raised with Sun or if there is any known workaround that has been found to mitigate the problem?
Though it is possible that the user is still able to delete the lists from the pane using the mouse selection, not having the option to do the same using the backspace key just seems very weird.
SSCCE is now attached. To repro the bug pls. follow the steps as shown in the attached fig.
- Add a line of text. Then add 2/3 bullet items by clicking on the button above the text pane. Now place the caret at the end of the last char of the last bullet and keep on pressing the entire backspace key until all the chars get deleted.
Observed behavior: the last bullet will hang on (won't get deleted) and the exception will be thrown (as mentioned above)
Expected: No exception and the contents of the text pane should get cleared.
public class Test {
static final JFrame frame = new JFrame ();
static final JTextPane textPane = new JTextPane ();
static EditorKit kit;
static JButton listButton;
public static void createAndShowGUI () {
//Create frame
frame.setSize(400, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
//Customize text pane visual properties
textPane.setSize(300, 500);
textPane.setLocation(50, 50);
//customize text pane non visual properties
kit = new CustomEditorKit ();
textPane.setEditorKitForContentType("text/html", kit);
textPane.setContentType("text/html");
Action[] actions = ((HTMLEditorKit) kit).getActions();
Action action = null;
for (int i = 0; i < actions.length; i++) {
action = actions [i];
if (action.getValue(Action.NAME).equals("InsertUnorderedList")) {
break;
}
}
listButton = new JButton (action);
listButton.setText("List");
listButton.setSize(100, 20);
listButton.setLocation(100, 10);
listButton.setVisible(true);
/* Add button and text pane to frame */
frame.add(listButton);
frame.add(textPane);
}
public static void main(String[] args) {
try {
EventQueue.invokeAndWait(new Runnable () {
@Override
public void run() {
createAndShowGUI ();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
static class CustomEditorKit extends HTMLEditorKit {
@Override
public Document createDefaultDocument () {
return new HTMLDocument (this.getStyleSheet());
}
}
}
I used this
instead of default action in your example to provide correct structure.
Works fine for me. (Win 7, Java 1.6)