SWING DOCUMENT LOCATIONS
In Java(tm) Foundation Classes (JFC) Project Swing, a text pane
that you use to edit text is backed by a "document". For example,
a JTextPane has, by default, a DefaultStyledDocument underlying it.
The document is what actually stores text and other content
that is displayed in the pane.
Suppose that you are using a Swing document in your application,
and you'd like to keep track of specific locations in the document.
So you decide to use character offsets for this purpose, for
example, a location that is 47 characters into the document.
This approach does work until you edit the document. For example,
suppose you delete the first 10 characters. You'll then need to
update offset 47 to 37 to keep the location correct.
A better approach to track document locations is Swing's Position
interface. If a class implements the Position interface, it defines
a location in a document. If the document changes, for instance,
after editing, the location is updated as necessary. To see how this
works, consider the following example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class PosDemo {
static Position lastpos;
public static void main(String args[]) {
JFrame frame = new JFrame("Position demo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
final JTextPane pane = new JTextPane();
pane.setPreferredSize(new Dimension(600, 400));
JButton setbutton = new JButton("Set Position");
JButton gobutton = new JButton("Go To Position");
setbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
int dot = pane.getCaret().getDot();
Document doc = pane.getDocument();
lastpos = doc.createPosition(dot);
pane.requestFocus();
}
catch (BadLocationException exc) {
System.err.println(exc);
}
}
});
gobutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (lastpos == null) {
Toolkit.getDefaultToolkit().beep();
}
else {
int pos = lastpos.getOffset();
pane.getCaret().setDot(pos);
pane.requestFocus();
}
}
});
JPanel buttonpanel = new JPanel();
buttonpanel.add(setbutton);
buttonpanel.add(gobutton);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add("North", buttonpanel);
panel.add("Center", pane);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
The demo sets up a text window, along with Set Position and Go To
Position buttons. Suppose you type some text, move the text caret
somewhere in that text, and then select Set Position. At this point
you've recorded a location in the text. Then suppose that you edit
the text, adding and deleting characters before and after the
position you selected. If you then select the Go To Position button,
the caret will move back to the original location. In other words,
the action of the Go To Position button takes into account the
changed offset of the location based on edits you've done.
To see what's going on here, enter a distinct pattern like "XYZ"
into the middle of some random text. Move the caret to that pattern
and then select Set Position. Doing it this way makes it clear that
the pattern itself is being tracked as a location, rather than
simply a specific character offset in the document.
These three lines in the example program do the actual location
saving:
int dot = pane.getCaret().getDot();
Document doc = pane.getDocument();
lastpos = doc.createPosition(dot);
The first line retrieves the current caret offset (dot). The second
line gets the document. And the third line creates a Position instance
in the document from the caret offset. The process is reversed later
in the program with the lines:
int pos = lastpos.getOffset();
pane.getCaret().setDot(pos);
where getOffset retrieves the updated offset.
|