I've got a StyledDocument instance that contains, among other things, strings that represent numbers. By overriding the attributes of the string's element, I'm using a custom View for them that I derived from LabelView. I want to allow the user to select the base of the displayed number, e.g. decimal or hexadecimal. This is my current solution:
public class AddressView extends LabelView {
@Override
public Segment getText(int p0, int p1) {
// get string representation of the number from the model
String stringNumber = super.getText(p0, p1).toString();
// get base from document's attributes
int base = getDocument().getProperty(BaseProperty);
// convert string to desired base
String stringNumberOverride = Integer.toString(Integer.parseInt(stringNumber), base);
// return as segment (can have a different length, JTextPane doesn't like that)
char[] strNum = stringNumberOverride.toCharArray();
return new Segment(strNum, 0, strNum.length);
}
}
There's only one problem: Selecting text doesn't work anymore because the returned string of getText doesn't have the requested length (p1 - p0). The JTextPane component is implemented to select exactly that many chars, so with the above solution the user can only select p1 - p0 characters, even though the new base could have displayed a longer string representation of the number string in the model.
So, what's the correct way to have a View that displays a String that has a different length than the one in the model? I don't want to update the Model just because the user desires a different representation of the content.
Edit: Here's a self-contained example. Try selecting the text - you can only select all chars or no chars because there's only one character in the model.
package mini;
import javax.swing.*;
import javax.swing.text.*;
public class Mini extends JFrame {
public Mini() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
JTextPane pane = new JTextPane();
pane.setEditorKit(new MyEditorKit());
add(new JScrollPane(pane));
pack();
}
public static void main(String[] args) {
Mini mini = new Mini();
mini.setVisible(true);
}
}
class MyEditorKit extends StyledEditorKit {
@Override
public ViewFactory getViewFactory() {
return new ViewFactory() {
public View create(Element elem) {
return new MyView(elem);
}
};
}
}
class MyView extends LabelView {
public MyView(Element elem) {
super(elem);
}
@Override
public Segment getText(int p0, int p1) {
String line = "Displayed text that's longer than model text";
return new Segment(line.toCharArray(), 0, line.length());
}
}