1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
| public class TextArea extends JTextPane implements UndoableEditListener,
Highlighter.HighlightPainter, PopupActions.Provider {
private final static long serialVersionUID = 0xAB343920;
private Highlighter highlighter;
private UndoManager undoManager;
private Object highlight;
private static final Color ERROR_COLOR = Color.RED;
private String EOL;
private PopupActions popupActions;
//
// UndoableEditListener method
//
/**
* Adds the <tt>UndoableEdit</tt> that has happened to the
* <tt>UndoManager</tt> associated with this <tt>TextArea</tt>.
*
* @param evt
* the undoable edit event encapsulating the
* <tt>UndoableEdit</tt>
*/
public void undoableEditHappened(UndoableEditEvent evt) {
undoManager.addEdit(evt.getEdit());
}
/**
* Allocates a new <tt>TextArea</tt>.
*/
@SuppressWarnings("serial")
public TextArea() {
undoManager = new UndoManager();
highlighter = new DefaultHighlighter();
setHighlighter(highlighter);
getActionMap().put("Undo", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
undo();
}
});
getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo");
getActionMap().put("Redo", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
redo();
}
});
getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
EOL = (String) getDocument().getProperty(
DefaultEditorKit.EndOfLineStringProperty);
getDocument().putProperty(DefaultEditorKit.EndOfLineStringProperty,
"\n");
getDocument().addUndoableEditListener(this);
}
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
super.paintComponent(g);
}
/**
* Undoes the last action, if any has been performed.
*/
public void undo() {
try {
if (undoManager.canUndo()) {
undoManager.undo();
for (KeyListener kl : getKeyListeners()) {
kl.keyTyped(null);
kl.keyReleased(null);
}
}
} catch (CannotUndoException e) {
}
}
/**
* Redoes the last action, if any has been performed.
*/
public void redo() {
try {
if (undoManager.canRedo()) {
undoManager.redo();
for (KeyListener kl : getKeyListeners()) {
kl.keyTyped(null);
kl.keyReleased(null);
}
}
} catch (CannotRedoException e) {
}
}
/**
* Marks the characters between the two specified positions as erroneous.
* Before this another maybe existing mark will be removed. If the
* <tt>from</tt> position is less than 0, an error mark - if present - will
* be removed.
*
* @param from
* the position of the first character
* @param to
* the position of the last character
*/
public void markError(final int from, final int to) {
if (highlight != null) {
highlighter.removeHighlight(highlight);
}
if (from >= 0) {
try {
highlight = highlighter.addHighlight(from, to, this);
} catch (BadLocationException ble) {
ble.printStackTrace();
}
}
}
/**
* Returns the number of the line the cursor is in.
*
* @return the number of the line the cursor is in
*/
public int getCaretLine() {
final int caret = getCaretPosition();
final String text = getText();
int line = 0;
for (int i = 0; i < caret; i++) {
char c = text.charAt(i);
if (c == '\n') {
line++;
}
}
return line;
}
/**
* Returns the text displayed by this <tt>TextArea</tt>, optionally
* formatted such that end-of-line characters match the platform's
* behaviour.
*
* @param format
* flag denoting if end-of-line characters should be represented
* as usual for the platform (<tt>true</tt>) or by '\n' (
* <tt>false</tt>).
* @return the text displayed by this <tt>TextArea</tt>
*/
/*public String getText(boolean format) {
String text;
if (format) {
getDocument().putProperty(DefaultEditorKit.EndOfLineStringProperty,
EOL);
text = super.getText();
getDocument().putProperty(DefaultEditorKit.EndOfLineStringProperty,
"\n");
} else {
text = super.getText();
}
return text;
}*/
/**
* Returns the text displayed by this <tt>TextArea</tt>, with a single '\n'
* used as an end-of-line character.
*
* @return the text displayed by this <tt>TextArea</tt>
*/
/*public String getText() {
return getText(false);
}*/
/**
* Returns the index of the character at the beginning of the current line
* (where the cursor is)
*
* @return the index of the character at the beginning of the current line
* (where the cursor is)
*/
public int getCurrentLineBegin() {
final int caret = getCaretPosition();
final String text = getText();
int i = Math.min(text.length() - 1, caret);
// search for the next character that is not a line break
for (; i >= 0; i--) {
final char c = text.charAt(i);
if (c != '\n' && c != '\r') {
break;
}
}
for (; i >= 0; i--) {
final char c = text.charAt(i);
if (c == '\n' || c == '\r') {
return i + 1; //2;
}
}
return 0;
}
// paint a thick line under one line of text, from r extending rightward
// to
// x2
private void paintLine(Graphics g, Rectangle r, int x2) {
int ytop = r.y + r.height - 3;
// g.fillRect(r.x, ytop, x2 - r.x, 3);
for (int x = r.x; x < x2 - r.x; x += 2) {
g.drawLine(x, ytop, x + 1, ytop + 1);
g.drawLine(x + 1, ytop + 1, x + 2, ytop);
}
}
// paint thick lines under a block of text
/**
* @see Highlighter.HighlightPainter#paint(Graphics, int, int, Shape,
* JTextComponent)
*/
public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
Rectangle r0 = null, r1 = null, rbounds = bounds.getBounds();
int xmax = rbounds.x + rbounds.width; // x coordinate of right
// edge
try { // convert positions to pixel coordinates
r0 = c.modelToView(p0);
r1 = c.modelToView(p1);
} catch (BadLocationException ex) {
return;
}
if ((r0 == null) || (r1 == null))
return;
g.setColor(ERROR_COLOR);
// special case if p0 and p1 are on the same line
if (r0.y == r1.y) {
paintLine(g, r0, r1.x);
return;
}
// first line, from p1 to end-of-line
paintLine(g, r0, xmax);
// all the full lines in between, if any (assumes that all lines
// have
// the same height--not a good assumption with
// JEditorPane/JTextPane)
r0.y += r0.height; // move r0 to next line
r0.x = rbounds.x; // move r0 to left edge
while (r0.y < r1.y) {
paintLine(g, r0, xmax);
r0.y += r0.height; // move r0 to next line
}
// last line, from beginning-of-line to p1
paintLine(g, r0, r1.x);
}
public PopupActions getPopupActions(ContextHandler contextHandler) {
if (popupActions == null) {
popupActions = new PopupActions(this, contextHandler);
}
return popupActions;
}
} |
Partager