1 | /*
|
---|
2 | * 04/07/2005
|
---|
3 | *
|
---|
4 | * RTextAreaBase.java - The base class for an RTextArea.
|
---|
5 | *
|
---|
6 | * This library is distributed under a modified BSD license. See the included
|
---|
7 | * RSyntaxTextArea.License.txt file for details.
|
---|
8 | */
|
---|
9 | package org.fife.ui.rtextarea;
|
---|
10 |
|
---|
11 | import java.awt.AWTEvent;
|
---|
12 | import java.awt.Color;
|
---|
13 | import java.awt.Font;
|
---|
14 | import java.awt.Graphics;
|
---|
15 | import java.awt.Image;
|
---|
16 | import java.awt.Rectangle;
|
---|
17 | import java.awt.event.ComponentEvent;
|
---|
18 | import java.awt.event.FocusEvent;
|
---|
19 | import java.awt.event.FocusListener;
|
---|
20 | import java.awt.event.MouseEvent;
|
---|
21 | import java.awt.event.MouseListener;
|
---|
22 | import java.awt.event.MouseMotionListener;
|
---|
23 | import javax.swing.JTextArea;
|
---|
24 | import javax.swing.event.CaretEvent;
|
---|
25 | import javax.swing.plaf.ColorUIResource;
|
---|
26 | import javax.swing.plaf.TextUI;
|
---|
27 | import javax.swing.text.AbstractDocument;
|
---|
28 | import javax.swing.text.BadLocationException;
|
---|
29 |
|
---|
30 |
|
---|
31 | /**
|
---|
32 | * This is the base class for <code>RTextArea</code>; basically it's just an
|
---|
33 | * extension of <code>javax.swing.JTextArea</code> adding a bunch of properties.
|
---|
34 | * <p>
|
---|
35 | *
|
---|
36 | * This class is only supposed to be overridden by <code>RTextArea</code>.
|
---|
37 | *
|
---|
38 | * @author Robert Futrell
|
---|
39 | * @version 0.8
|
---|
40 | */
|
---|
41 | abstract class RTextAreaBase extends JTextArea {
|
---|
42 |
|
---|
43 | public static final String BACKGROUND_IMAGE_PROPERTY = "background.image";
|
---|
44 | public static final String CURRENT_LINE_HIGHLIGHT_COLOR_PROPERTY = "RTA.currentLineHighlightColor";
|
---|
45 | public static final String CURRENT_LINE_HIGHLIGHT_FADE_PROPERTY = "RTA.currentLineHighlightFade";
|
---|
46 | public static final String HIGHLIGHT_CURRENT_LINE_PROPERTY = "RTA.currentLineHighlight";
|
---|
47 | public static final String ROUNDED_SELECTION_PROPERTY = "RTA.roundedSelection";
|
---|
48 |
|
---|
49 | private boolean tabsEmulatedWithSpaces; // If true, tabs will be expanded to spaces.
|
---|
50 |
|
---|
51 | private boolean highlightCurrentLine; // If true, the current line is highlighted.
|
---|
52 | private Color currentLineColor; // The color used to highlight the current line.
|
---|
53 | private boolean marginLineEnabled; // If true, paint a "margin line."
|
---|
54 | private Color marginLineColor; // The color used to paint the margin line.
|
---|
55 | private int marginLineX; // The x-location of the margin line.
|
---|
56 | private int marginSizeInChars; // How many 'm' widths the margin line is over.
|
---|
57 | private boolean fadeCurrentLineHighlight; // "Fade effect" for current line highlight.
|
---|
58 | private boolean roundedSelectionEdges;
|
---|
59 | private int previousCaretY;
|
---|
60 | int currentCaretY; // Used to know when to rehighlight current line.
|
---|
61 |
|
---|
62 | private BackgroundPainterStrategy backgroundPainter; // Paints the background.
|
---|
63 |
|
---|
64 | private RTAMouseListener mouseListener;
|
---|
65 |
|
---|
66 | private static final Color DEFAULT_CARET_COLOR = new ColorUIResource(255,51,51);
|
---|
67 | private static final Color DEFAULT_CURRENT_LINE_HIGHLIGHT_COLOR = new Color(255,255,170);
|
---|
68 | private static final Color DEFAULT_MARGIN_LINE_COLOR = new Color(255,224,224);
|
---|
69 | private static final int DEFAULT_TAB_SIZE = 4;
|
---|
70 | private static final int DEFAULT_MARGIN_LINE_POSITION = 80;
|
---|
71 |
|
---|
72 |
|
---|
73 | /**
|
---|
74 | * Constructor.
|
---|
75 | */
|
---|
76 | public RTextAreaBase() {
|
---|
77 | init();
|
---|
78 | }
|
---|
79 |
|
---|
80 |
|
---|
81 | /**
|
---|
82 | * Constructor.
|
---|
83 | *
|
---|
84 | * @param doc The document for the editor.
|
---|
85 | */
|
---|
86 | public RTextAreaBase(AbstractDocument doc) {
|
---|
87 | super(doc);
|
---|
88 | init();
|
---|
89 | }
|
---|
90 |
|
---|
91 |
|
---|
92 | /**
|
---|
93 | * Constructor.
|
---|
94 | *
|
---|
95 | * @param text The initial text to display.
|
---|
96 | */
|
---|
97 | public RTextAreaBase(String text) {
|
---|
98 | super(text);
|
---|
99 | init();
|
---|
100 | }
|
---|
101 |
|
---|
102 |
|
---|
103 | /**
|
---|
104 | * Constructor.
|
---|
105 | *
|
---|
106 | * @param rows The number of rows to display.
|
---|
107 | * @param cols The number of columns to display.
|
---|
108 | * @throws IllegalArgumentException If either <code>rows</code> or
|
---|
109 | * <code>cols</code> is negative.
|
---|
110 | */
|
---|
111 | public RTextAreaBase(int rows, int cols) {
|
---|
112 | super(rows, cols);
|
---|
113 | init();
|
---|
114 | }
|
---|
115 |
|
---|
116 |
|
---|
117 | /**
|
---|
118 | * Constructor.
|
---|
119 | *
|
---|
120 | * @param text The initial text to display.
|
---|
121 | * @param rows The number of rows to display.
|
---|
122 | * @param cols The number of columns to display.
|
---|
123 | * @throws IllegalArgumentException If either <code>rows</code> or
|
---|
124 | * <code>cols</code> is negative.
|
---|
125 | */
|
---|
126 | public RTextAreaBase(String text, int rows, int cols) {
|
---|
127 | super(text, rows, cols);
|
---|
128 | init();
|
---|
129 | }
|
---|
130 |
|
---|
131 |
|
---|
132 | /**
|
---|
133 | * Constructor.
|
---|
134 | *
|
---|
135 | * @param doc The document for the editor.
|
---|
136 | * @param text The initial text to display.
|
---|
137 | * @param rows The number of rows to display.
|
---|
138 | * @param cols The number of columns to display.
|
---|
139 | * @throws IllegalArgumentException If either <code>rows</code> or
|
---|
140 | * <code>cols</code> is negative.
|
---|
141 | */
|
---|
142 | public RTextAreaBase(AbstractDocument doc, String text, int rows,
|
---|
143 | int cols) {
|
---|
144 | super(doc, text, rows, cols);
|
---|
145 | init();
|
---|
146 | }
|
---|
147 |
|
---|
148 |
|
---|
149 | /**
|
---|
150 | * Adds listeners that listen for changes to the current line, so we can
|
---|
151 | * update our "current line highlight." This is needed only because of an
|
---|
152 | * apparent difference between the JRE 1.4.2 and 1.5.0 (needed on 1.4.2,
|
---|
153 | * not needed on 1.5.0).
|
---|
154 | */
|
---|
155 | protected void addCurrentLineHighlightListeners() {
|
---|
156 | boolean add = true;
|
---|
157 | MouseMotionListener[] mouseMotionListeners = getMouseMotionListeners();
|
---|
158 | for (int i=0; i<mouseMotionListeners.length; i++) {
|
---|
159 | if (mouseMotionListeners[i]==mouseListener) {
|
---|
160 | add = false;
|
---|
161 | break;
|
---|
162 | }
|
---|
163 | }
|
---|
164 | if (add==true) {
|
---|
165 | //System.err.println("Adding mouse motion listener!");
|
---|
166 | addMouseMotionListener(mouseListener);
|
---|
167 | }
|
---|
168 | MouseListener[] mouseListeners = getMouseListeners();
|
---|
169 | for (int i=0; i<mouseListeners.length; i++) {
|
---|
170 | if (mouseListeners[i]==mouseListener) {
|
---|
171 | add = false;
|
---|
172 | break;
|
---|
173 | }
|
---|
174 | }
|
---|
175 | if (add==true) {
|
---|
176 | //System.err.println("Adding mouse listener!");
|
---|
177 | addMouseListener(mouseListener);
|
---|
178 | }
|
---|
179 | }
|
---|
180 |
|
---|
181 |
|
---|
182 | /*
|
---|
183 | * TODO: Figure out why RTextArea doesn't work with RTL orientation!
|
---|
184 | */
|
---|
185 | // public void applyComponentOrientation(ComponentOrientation orientation) {
|
---|
186 | // super.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
|
---|
187 | // }
|
---|
188 |
|
---|
189 |
|
---|
190 | /**
|
---|
191 | * Converts all instances of a number of spaces equal to a tab size
|
---|
192 | * into a tab in this text area.
|
---|
193 | *
|
---|
194 | * @see #convertTabsToSpaces
|
---|
195 | * @see #getTabsEmulated
|
---|
196 | * @see #setTabsEmulated
|
---|
197 | */
|
---|
198 | public void convertSpacesToTabs() {
|
---|
199 |
|
---|
200 | // FIXME: This is inefficient and will yield an OutOfMemoryError if
|
---|
201 | // done on a large document. We should scan 1 line at a time and
|
---|
202 | // replace; it'll be slower but safer.
|
---|
203 |
|
---|
204 | int caretPosition = getCaretPosition();
|
---|
205 | int tabSize = getTabSize();
|
---|
206 | String tabInSpaces = "";
|
---|
207 | for (int i=0; i<tabSize; i++)
|
---|
208 | tabInSpaces += " ";
|
---|
209 | String text = getText();
|
---|
210 | setText(text.replaceAll(tabInSpaces, "\t"));
|
---|
211 | int newDocumentLength = getDocument().getLength();
|
---|
212 |
|
---|
213 | // Place the caret back in its proper position.
|
---|
214 | if (caretPosition<newDocumentLength)
|
---|
215 | setCaretPosition(caretPosition);
|
---|
216 | else
|
---|
217 | setCaretPosition(newDocumentLength-1);
|
---|
218 |
|
---|
219 | }
|
---|
220 |
|
---|
221 |
|
---|
222 | /**
|
---|
223 | * Converts all instances of a tab into a number of spaces equivalent
|
---|
224 | * to a tab in this text area.
|
---|
225 | *
|
---|
226 | * @see #convertSpacesToTabs
|
---|
227 | * @see #getTabsEmulated
|
---|
228 | * @see #setTabsEmulated
|
---|
229 | */
|
---|
230 | public void convertTabsToSpaces() {
|
---|
231 |
|
---|
232 | // FIXME: This is inefficient and will yield an OutOfMemoryError if
|
---|
233 | // done on a large document. We should scan 1 line at a time and
|
---|
234 | // replace; it'll be slower but safer.
|
---|
235 |
|
---|
236 | int caretPosition = getCaretPosition();
|
---|
237 | int tabSize = getTabSize();
|
---|
238 | StringBuffer tabInSpaces = new StringBuffer();
|
---|
239 | for (int i=0; i<tabSize; i++)
|
---|
240 | tabInSpaces.append(' ');
|
---|
241 | String text = getText();
|
---|
242 | setText(text.replaceAll("\t", tabInSpaces.toString()));
|
---|
243 |
|
---|
244 | // Put caret back at same place in document.
|
---|
245 | setCaretPosition(caretPosition);
|
---|
246 |
|
---|
247 | }
|
---|
248 |
|
---|
249 |
|
---|
250 | /**
|
---|
251 | * Returns the caret event/mouse listener for <code>RTextArea</code>s.
|
---|
252 | *
|
---|
253 | * @return The caret event/mouse listener.
|
---|
254 | */
|
---|
255 | protected abstract RTAMouseListener createMouseListener();
|
---|
256 |
|
---|
257 |
|
---|
258 | /**
|
---|
259 | * Returns the a real UI to install on this text component. Subclasses
|
---|
260 | * can override this method to return an extended version of
|
---|
261 | * <code>RTextAreaUI</code>.
|
---|
262 | *
|
---|
263 | * @return The UI.
|
---|
264 | */
|
---|
265 | protected abstract RTextAreaUI createRTextAreaUI();
|
---|
266 |
|
---|
267 |
|
---|
268 | /**
|
---|
269 | * Forces the current line highlight to be repainted. This hack is
|
---|
270 | * necessary for those situations when the view (appearance) changes
|
---|
271 | * but the caret's location hasn't (and thus the current line highlight
|
---|
272 | * coordinates won't get changed). Examples of this are when
|
---|
273 | * word wrap is toggled and when syntax styles are changed in an
|
---|
274 | * <code>RSyntaxTextArea</code>.
|
---|
275 | */
|
---|
276 | protected void forceCurrentLineHighlightRepaint() {
|
---|
277 | // Check isShowing() to prevent BadLocationException
|
---|
278 | // in constructor if linewrap is set to true.
|
---|
279 | if (isShowing()) {
|
---|
280 | // Changing previousCaretY makes us sure to get a repaint.
|
---|
281 | previousCaretY = -1;
|
---|
282 | // Trick it into checking for the need to repaint by firing
|
---|
283 | // a false caret event.
|
---|
284 | fireCaretUpdate(mouseListener);
|
---|
285 | }
|
---|
286 | }
|
---|
287 |
|
---|
288 |
|
---|
289 | /**
|
---|
290 | * Returns the <code>java.awt.Color</code> used as the background color for
|
---|
291 | * this text area. If a <code>java.awt.Image</code> image is currently
|
---|
292 | * being used instead, <code>null</code> is returned.
|
---|
293 | *
|
---|
294 | * @return The current background color, or <code>null</code> if an image
|
---|
295 | * is currently the background.
|
---|
296 | */
|
---|
297 | public final Color getBackground() {
|
---|
298 | Object bg = getBackgroundObject();
|
---|
299 | return (bg instanceof Color) ? (Color)bg : null;
|
---|
300 | }
|
---|
301 |
|
---|
302 | /**
|
---|
303 | * Returns the image currently used for the background.
|
---|
304 | * If the current background is currently a <code>java.awt.Color</code> and
|
---|
305 | * not a <code>java.awt.Image</code>, then <code>null</code> is returned.
|
---|
306 | *
|
---|
307 | * @return A <code>java.awt.Image</code> used for the background, or
|
---|
308 | * <code>null</code> if the background is not an image.
|
---|
309 | * @see #setBackgroundImage
|
---|
310 | */
|
---|
311 | public final Image getBackgroundImage() {
|
---|
312 | Object bg = getBackgroundObject();
|
---|
313 | return (bg instanceof Image) ? (Image)bg : null;
|
---|
314 | }
|
---|
315 |
|
---|
316 |
|
---|
317 | /**
|
---|
318 | * Returns the <code>Object</code> representing the background for all
|
---|
319 | * documents in this tabbed pane; either a <code>java.awt.Color</code> or a
|
---|
320 | * <code>java.lang.Image</code> containing the image used as the background
|
---|
321 | * for this text area.
|
---|
322 | *
|
---|
323 | * @return The <code>Object</code> used for the background.
|
---|
324 | * @see #setBackgroundObject(Object newBackground)
|
---|
325 | */
|
---|
326 | public final Object getBackgroundObject() {
|
---|
327 | if (backgroundPainter==null)
|
---|
328 | return null;
|
---|
329 | return (backgroundPainter instanceof ImageBackgroundPainterStrategy) ?
|
---|
330 | (Object)((ImageBackgroundPainterStrategy)backgroundPainter).
|
---|
331 | getMasterImage() :
|
---|
332 | (Object)((ColorBackgroundPainterStrategy)backgroundPainter).
|
---|
333 | getColor();
|
---|
334 | }
|
---|
335 |
|
---|
336 |
|
---|
337 | /**
|
---|
338 | * Gets the line number that the caret is on.
|
---|
339 | *
|
---|
340 | * @return The zero-based line number that the caret is on.
|
---|
341 | */
|
---|
342 | public final int getCaretLineNumber() {
|
---|
343 | try {
|
---|
344 | return getLineOfOffset(getCaretPosition());
|
---|
345 | } catch (BadLocationException ble) {
|
---|
346 | return 0; // Never happens
|
---|
347 | }
|
---|
348 | }
|
---|
349 |
|
---|
350 |
|
---|
351 | /**
|
---|
352 | * Gets the position from the beginning of the current line that the caret
|
---|
353 | * is on.
|
---|
354 | *
|
---|
355 | * @return The zero-based position from the beginning of the current line
|
---|
356 | * that the caret is on.
|
---|
357 | */
|
---|
358 | public final int getCaretOffsetFromLineStart() {
|
---|
359 | try {
|
---|
360 | int pos = getCaretPosition();
|
---|
361 | return pos - getLineStartOffset(getLineOfOffset(pos));
|
---|
362 | } catch (BadLocationException ble) {
|
---|
363 | return 0; // Never happens
|
---|
364 | }
|
---|
365 | }
|
---|
366 |
|
---|
367 |
|
---|
368 | /**
|
---|
369 | * Returns the color being used to highlight the current line. Note that
|
---|
370 | * if highlighting the current line is turned off, you will not be seeing
|
---|
371 | * this highlight.
|
---|
372 | *
|
---|
373 | * @return The color being used to highlight the current line.
|
---|
374 | * @see #getHighlightCurrentLine()
|
---|
375 | * @see #setHighlightCurrentLine(boolean)
|
---|
376 | * @see #setCurrentLineHighlightColor
|
---|
377 | */
|
---|
378 | public Color getCurrentLineHighlightColor() {
|
---|
379 | return currentLineColor;
|
---|
380 | }
|
---|
381 |
|
---|
382 |
|
---|
383 | /**
|
---|
384 | * Returns the default caret color.
|
---|
385 | *
|
---|
386 | * @return The default caret color.
|
---|
387 | */
|
---|
388 | public static final Color getDefaultCaretColor() {
|
---|
389 | return DEFAULT_CARET_COLOR;
|
---|
390 | }
|
---|
391 |
|
---|
392 |
|
---|
393 | /**
|
---|
394 | * Returns the "default" color for highlighting the current line. Note
|
---|
395 | * that this color was chosen only because it looks nice (to me) against a
|
---|
396 | * white background.
|
---|
397 | *
|
---|
398 | * @return The default color for highlighting the current line.
|
---|
399 | */
|
---|
400 | public static final Color getDefaultCurrentLineHighlightColor() {
|
---|
401 | return DEFAULT_CURRENT_LINE_HIGHLIGHT_COLOR;
|
---|
402 | }
|
---|
403 |
|
---|
404 |
|
---|
405 | /**
|
---|
406 | * Returns the default font for text areas.
|
---|
407 | *
|
---|
408 | * @return The default font.
|
---|
409 | */
|
---|
410 | public static final Font getDefaultFont() {
|
---|
411 |
|
---|
412 | Font font = null;
|
---|
413 |
|
---|
414 | if (isOSX()) {
|
---|
415 | // Snow Leopard (1.6) uses Menlo as default monospaced font,
|
---|
416 | // pre-Snow Leopard used Monaco.
|
---|
417 | font = new Font("Menlo", Font.PLAIN, 12);
|
---|
418 | if (!"Menlo".equals(font.getFamily())) {
|
---|
419 | font = new Font("Monaco", Font.PLAIN, 12);
|
---|
420 | if (!"Monaco".equals(font.getFamily())) { // Shouldn't happen
|
---|
421 | font = new Font("Monospaced", Font.PLAIN, 13);
|
---|
422 | }
|
---|
423 | }
|
---|
424 | }
|
---|
425 | else {
|
---|
426 | font = new Font("Monospaced", Font.PLAIN, 13);
|
---|
427 | }
|
---|
428 |
|
---|
429 | //System.out.println(font.getFamily() + ", " + font.getName());
|
---|
430 | return font;
|
---|
431 |
|
---|
432 | }
|
---|
433 |
|
---|
434 |
|
---|
435 | /**
|
---|
436 | * Returns the default foreground color for text in this text area.
|
---|
437 | *
|
---|
438 | * @return The default foreground color.
|
---|
439 | */
|
---|
440 | public static final Color getDefaultForeground() {
|
---|
441 | return Color.BLACK;
|
---|
442 | }
|
---|
443 |
|
---|
444 |
|
---|
445 | /**
|
---|
446 | * Returns the default color for the margin line.
|
---|
447 | *
|
---|
448 | * @return The default margin line color.
|
---|
449 | * @see #getMarginLineColor()
|
---|
450 | * @see #setMarginLineColor(Color)
|
---|
451 | */
|
---|
452 | public static final Color getDefaultMarginLineColor() {
|
---|
453 | return DEFAULT_MARGIN_LINE_COLOR;
|
---|
454 | }
|
---|
455 |
|
---|
456 |
|
---|
457 | /**
|
---|
458 | * Returns the default margin line position.
|
---|
459 | *
|
---|
460 | * @return The default margin line position.
|
---|
461 | * @see #getMarginLinePosition
|
---|
462 | * @see #setMarginLinePosition
|
---|
463 | */
|
---|
464 | public static final int getDefaultMarginLinePosition() {
|
---|
465 | return DEFAULT_MARGIN_LINE_POSITION;
|
---|
466 | }
|
---|
467 |
|
---|
468 |
|
---|
469 | /**
|
---|
470 | * Returns the default tab size, in spaces.
|
---|
471 | *
|
---|
472 | * @return The default tab size.
|
---|
473 | */
|
---|
474 | public static final int getDefaultTabSize() {
|
---|
475 | return DEFAULT_TAB_SIZE;
|
---|
476 | }
|
---|
477 |
|
---|
478 |
|
---|
479 | /**
|
---|
480 | * Returns whether the current line highlight is faded.
|
---|
481 | *
|
---|
482 | * @return Whether the current line highlight is faded.
|
---|
483 | * @see #setFadeCurrentLineHighlight
|
---|
484 | */
|
---|
485 | public boolean getFadeCurrentLineHighlight() {
|
---|
486 | return fadeCurrentLineHighlight;
|
---|
487 | }
|
---|
488 |
|
---|
489 |
|
---|
490 | /**
|
---|
491 | * Returns whether or not the current line is highlighted.
|
---|
492 | *
|
---|
493 | * @return Whether or the current line is highlighted.
|
---|
494 | * @see #setHighlightCurrentLine(boolean)
|
---|
495 | * @see #getCurrentLineHighlightColor
|
---|
496 | * @see #setCurrentLineHighlightColor
|
---|
497 | */
|
---|
498 | public boolean getHighlightCurrentLine() {
|
---|
499 | return highlightCurrentLine;
|
---|
500 | }
|
---|
501 |
|
---|
502 |
|
---|
503 | /**
|
---|
504 | * Returns the offset of the last character of the line that the caret is
|
---|
505 | * on.
|
---|
506 | *
|
---|
507 | * @return The last offset of the line that the caret is currently on.
|
---|
508 | */
|
---|
509 | public final int getLineEndOffsetOfCurrentLine() {
|
---|
510 | try {
|
---|
511 | return getLineEndOffset(getCaretLineNumber());
|
---|
512 | } catch (BadLocationException ble) {
|
---|
513 | return 0; // Never happens
|
---|
514 | }
|
---|
515 | }
|
---|
516 |
|
---|
517 |
|
---|
518 | /**
|
---|
519 | * Returns the height of a line of text in this text area.
|
---|
520 | *
|
---|
521 | * @return The height of a line of text.
|
---|
522 | */
|
---|
523 | public int getLineHeight() {
|
---|
524 | return getRowHeight();
|
---|
525 | }
|
---|
526 |
|
---|
527 |
|
---|
528 | /**
|
---|
529 | * Returns the offset of the first character of the line that the caret is
|
---|
530 | * on.
|
---|
531 | *
|
---|
532 | * @return The first offset of the line that the caret is currently on.
|
---|
533 | */
|
---|
534 | public final int getLineStartOffsetOfCurrentLine() {
|
---|
535 | try {
|
---|
536 | return getLineStartOffset(getCaretLineNumber());
|
---|
537 | } catch (BadLocationException ble) {
|
---|
538 | return 0; // Never happens
|
---|
539 | }
|
---|
540 | }
|
---|
541 |
|
---|
542 |
|
---|
543 | /**
|
---|
544 | * Returns the color used to paint the margin line.
|
---|
545 | *
|
---|
546 | * @return The margin line color.
|
---|
547 | * @see #setMarginLineColor(Color)
|
---|
548 | */
|
---|
549 | public Color getMarginLineColor() {
|
---|
550 | return marginLineColor;
|
---|
551 | }
|
---|
552 |
|
---|
553 |
|
---|
554 | /**
|
---|
555 | * Returns the margin line position (in pixels) from the left-hand side of
|
---|
556 | * the text area.
|
---|
557 | *
|
---|
558 | * @return The margin line position.
|
---|
559 | * @see #getDefaultMarginLinePosition
|
---|
560 | * @see #setMarginLinePosition
|
---|
561 | */
|
---|
562 | public int getMarginLinePixelLocation() {
|
---|
563 | return marginLineX;
|
---|
564 | }
|
---|
565 |
|
---|
566 |
|
---|
567 | /**
|
---|
568 | * Returns the margin line position (which is the number of 'm' widths in
|
---|
569 | * the current font the margin line is over).
|
---|
570 | *
|
---|
571 | * @return The margin line position.
|
---|
572 | * @see #getDefaultMarginLinePosition
|
---|
573 | * @see #setMarginLinePosition
|
---|
574 | */
|
---|
575 | public int getMarginLinePosition() {
|
---|
576 | return marginSizeInChars;
|
---|
577 | }
|
---|
578 |
|
---|
579 |
|
---|
580 | /**
|
---|
581 | * Returns whether selection edges are rounded in this text area.
|
---|
582 | *
|
---|
583 | * @return Whether selection edges are rounded.
|
---|
584 | * @see #setRoundedSelectionEdges(boolean)
|
---|
585 | */
|
---|
586 | public boolean getRoundedSelectionEdges() {
|
---|
587 | return roundedSelectionEdges;
|
---|
588 | }
|
---|
589 |
|
---|
590 |
|
---|
591 | /**
|
---|
592 | * Returns whether or not tabs are emulated with spaces (i.e., "soft"
|
---|
593 | * tabs).
|
---|
594 | *
|
---|
595 | * @return <code>true</code> if tabs are emulated with spaces;
|
---|
596 | * <code>false</code> if they aren't.
|
---|
597 | * @see #setTabsEmulated
|
---|
598 | */
|
---|
599 | public boolean getTabsEmulated() {
|
---|
600 | return tabsEmulatedWithSpaces;
|
---|
601 | }
|
---|
602 |
|
---|
603 |
|
---|
604 | /**
|
---|
605 | * Initializes this text area.
|
---|
606 | */
|
---|
607 | private void init() {
|
---|
608 |
|
---|
609 | // Sets the UI. Note that setUI() is overridden in RTextArea to only
|
---|
610 | // update the popup menu; this method must be called to set the real
|
---|
611 | // UI. This is done because the look and feel of an RTextArea is
|
---|
612 | // independent of the installed Java look and feels.
|
---|
613 | setRTextAreaUI(createRTextAreaUI());
|
---|
614 |
|
---|
615 | // So we get notified when the component is resized.
|
---|
616 | enableEvents(AWTEvent.COMPONENT_EVENT_MASK|AWTEvent.KEY_EVENT_MASK);
|
---|
617 |
|
---|
618 | // Defaults for various properties.
|
---|
619 | setHighlightCurrentLine(true);
|
---|
620 | setCurrentLineHighlightColor(getDefaultCurrentLineHighlightColor());
|
---|
621 | setMarginLineEnabled(false);
|
---|
622 | setMarginLineColor(getDefaultMarginLineColor());
|
---|
623 | setMarginLinePosition(getDefaultMarginLinePosition());
|
---|
624 | setBackgroundObject(Color.WHITE);
|
---|
625 | setWrapStyleWord(true);// We only support wrapping at word boundaries.
|
---|
626 | setTabSize(5);
|
---|
627 | setForeground(Color.BLACK);
|
---|
628 | setTabsEmulated(false);
|
---|
629 |
|
---|
630 | // Stuff needed by the caret listener below.
|
---|
631 | previousCaretY = currentCaretY = getInsets().top;
|
---|
632 |
|
---|
633 | // Stuff to highlight the current line.
|
---|
634 | mouseListener = createMouseListener();
|
---|
635 | // Also acts as a focus listener so we can update our shared actions
|
---|
636 | // (cut, copy, etc. on the popup menu).
|
---|
637 | addFocusListener(mouseListener);
|
---|
638 | addCurrentLineHighlightListeners();
|
---|
639 |
|
---|
640 | }
|
---|
641 |
|
---|
642 |
|
---|
643 | /**
|
---|
644 | * Returns whether or not the margin line is being painted.
|
---|
645 | *
|
---|
646 | * @return Whether or not the margin line is being painted.
|
---|
647 | * @see #setMarginLineEnabled
|
---|
648 | */
|
---|
649 | public boolean isMarginLineEnabled() {
|
---|
650 | return marginLineEnabled;
|
---|
651 | }
|
---|
652 |
|
---|
653 |
|
---|
654 | /**
|
---|
655 | * Returns whether the OS we're running on is OS X.
|
---|
656 | *
|
---|
657 | * @return Whether the OS we're running on is OS X.
|
---|
658 | */
|
---|
659 | public static boolean isOSX() {
|
---|
660 | // Recommended at:
|
---|
661 | // http://developer.apple.com/mac/library/technotes/tn2002/tn2110.html
|
---|
662 | String osName = System.getProperty("os.name").toLowerCase();
|
---|
663 | return osName.startsWith("mac os x");
|
---|
664 | }
|
---|
665 |
|
---|
666 |
|
---|
667 | /**
|
---|
668 | * Paints the text area.
|
---|
669 | *
|
---|
670 | * @param g The graphics context with which to paint.
|
---|
671 | */
|
---|
672 | protected void paintComponent(Graphics g) {
|
---|
673 |
|
---|
674 | //long startTime = System.currentTimeMillis();
|
---|
675 |
|
---|
676 | backgroundPainter.paint(g, getVisibleRect());
|
---|
677 |
|
---|
678 | // Paint the main part of the text area.
|
---|
679 | TextUI ui = getUI();
|
---|
680 | if (ui != null) {
|
---|
681 | // Not allowed to modify g, so make a copy.
|
---|
682 | Graphics scratchGraphics = g.create();
|
---|
683 | try {
|
---|
684 | ui.update(scratchGraphics, this);
|
---|
685 | } finally {
|
---|
686 | scratchGraphics.dispose();
|
---|
687 | }
|
---|
688 | }
|
---|
689 |
|
---|
690 | //long endTime = System.currentTimeMillis();
|
---|
691 | //System.err.println(endTime-startTime);
|
---|
692 |
|
---|
693 | }
|
---|
694 |
|
---|
695 |
|
---|
696 | /**
|
---|
697 | * Updates the current line highlight location.
|
---|
698 | */
|
---|
699 | protected void possiblyUpdateCurrentLineHighlightLocation() {
|
---|
700 |
|
---|
701 | int width = getWidth();
|
---|
702 | int lineHeight = getLineHeight();
|
---|
703 | int dot = getCaretPosition();
|
---|
704 |
|
---|
705 | // If we're wrapping lines we need to check the actual y-coordinate
|
---|
706 | // of the caret, not just the line number, since a single logical
|
---|
707 | // line can span multiple physical lines.
|
---|
708 | if (getLineWrap()) {
|
---|
709 | try {
|
---|
710 | Rectangle temp = modelToView(dot);
|
---|
711 | if (temp!=null) {
|
---|
712 | currentCaretY = temp.y;
|
---|
713 | }
|
---|
714 | } catch (BadLocationException ble) {
|
---|
715 | ble.printStackTrace(); // Should never happen.
|
---|
716 | }
|
---|
717 | }
|
---|
718 |
|
---|
719 | // No line wrap - we can simply check the line number (quicker).
|
---|
720 | else {
|
---|
721 | // Document doc = getDocument();
|
---|
722 | // if (doc!=null) {
|
---|
723 | // Element map = doc.getDefaultRootElement();
|
---|
724 | // int caretLine = map.getElementIndex(dot);
|
---|
725 | // Rectangle alloc = ((RTextAreaUI)getUI()).
|
---|
726 | // getVisibleEditorRect();
|
---|
727 | // if (alloc!=null)
|
---|
728 | // currentCaretY = alloc.y + caretLine*lineHeight;
|
---|
729 | // }
|
---|
730 | // Modified for code folding requirements
|
---|
731 | try {
|
---|
732 | Rectangle temp = modelToView(dot);
|
---|
733 | if (temp!=null) {
|
---|
734 | currentCaretY = temp.y;
|
---|
735 | }
|
---|
736 | } catch (BadLocationException ble) {
|
---|
737 | ble.printStackTrace(); // Should never happen.
|
---|
738 | }
|
---|
739 | }
|
---|
740 |
|
---|
741 | // Repaint current line (to fill in entire highlight), and old line
|
---|
742 | // (to erase entire old highlight) if necessary. Always repaint
|
---|
743 | // current line in case selection is added or removed.
|
---|
744 | repaint(0,currentCaretY, width,lineHeight);
|
---|
745 | if (previousCaretY!=currentCaretY) {
|
---|
746 | repaint(0,previousCaretY, width,lineHeight);
|
---|
747 | }
|
---|
748 |
|
---|
749 | previousCaretY = currentCaretY;
|
---|
750 |
|
---|
751 | }
|
---|
752 |
|
---|
753 |
|
---|
754 | /**
|
---|
755 | * Overridden so we can tell when the text area is resized and update the
|
---|
756 | * current-line highlight, if necessary (i.e., if it is enabled and if
|
---|
757 | * lineWrap is enabled.
|
---|
758 | *
|
---|
759 | * @param e The component event about to be sent to all registered
|
---|
760 | * <code>ComponentListener</code>s.
|
---|
761 | */
|
---|
762 | protected void processComponentEvent(ComponentEvent e) {
|
---|
763 |
|
---|
764 | // In line wrap mode, resizing the text area means that the caret's
|
---|
765 | // "line" could change - not to a different logical line, but a
|
---|
766 | // different physical one. So, here we force a repaint of the current
|
---|
767 | // line's highlight if necessary.
|
---|
768 | if (e.getID()==ComponentEvent.COMPONENT_RESIZED &&
|
---|
769 | getLineWrap()==true && getHighlightCurrentLine()) {
|
---|
770 | previousCaretY = -1; // So we are sure to repaint.
|
---|
771 | fireCaretUpdate(mouseListener);
|
---|
772 | }
|
---|
773 |
|
---|
774 | super.processComponentEvent(e);
|
---|
775 |
|
---|
776 | }
|
---|
777 |
|
---|
778 |
|
---|
779 | /**
|
---|
780 | * Sets the background color of this text editor. Note that this is
|
---|
781 | * equivalent to calling <code>setBackgroundObject(bg)</code>.
|
---|
782 | *
|
---|
783 | * NOTE: the opaque property is set to <code>true</code> when the
|
---|
784 | * background is set to a color (by this method). When an image is used
|
---|
785 | * for the background, opaque is set to false. This is because
|
---|
786 | * we perform better when setOpaque is true, but if we use an
|
---|
787 | * image for the background when opaque is true, we get on-screen
|
---|
788 | * garbage when the user scrolls via the arrow keys. Thus we
|
---|
789 | * need setOpaque to be false in that case.<p>
|
---|
790 | * You never have to change the opaque property yourself; it is always done
|
---|
791 | * for you.
|
---|
792 | *
|
---|
793 | * @param bg The color to use as the background color.
|
---|
794 | */
|
---|
795 | public void setBackground(Color bg) {
|
---|
796 | Object oldBG = getBackgroundObject();
|
---|
797 | if (oldBG instanceof Color) { // Just change color of strategy.
|
---|
798 | ((ColorBackgroundPainterStrategy)backgroundPainter).
|
---|
799 | setColor(bg);
|
---|
800 | }
|
---|
801 | else { // Was an image painter...
|
---|
802 | backgroundPainter = new ColorBackgroundPainterStrategy(bg);
|
---|
803 | }
|
---|
804 | setOpaque(true);
|
---|
805 | firePropertyChange("background", oldBG, bg);
|
---|
806 | repaint();
|
---|
807 | }
|
---|
808 |
|
---|
809 |
|
---|
810 | /**
|
---|
811 | * Sets this image as the background image. This method fires a
|
---|
812 | * property change event of type {@link #BACKGROUND_IMAGE_PROPERTY}.<p>
|
---|
813 | *
|
---|
814 | * NOTE: the opaque property is set to <code>true</code> when the
|
---|
815 | * background is set to a color. When an image is used for the
|
---|
816 | * background (by this method), opaque is set to false. This is because
|
---|
817 | * we perform better when setOpaque is true, but if we use an
|
---|
818 | * image for the background when opaque is true, we get on-screen
|
---|
819 | * garbage when the user scrolls via the arrow keys. Thus we
|
---|
820 | * need setOpaque to be false in that case.<p>
|
---|
821 | * You never have to change the opaque property yourself; it is always done
|
---|
822 | * for you.
|
---|
823 | *
|
---|
824 | * @param image The image to use as this text area's background.
|
---|
825 | * @see #getBackgroundImage
|
---|
826 | */
|
---|
827 | public void setBackgroundImage(Image image) {
|
---|
828 | Object oldBG = getBackgroundObject();
|
---|
829 | if (oldBG instanceof Image) { // Just change image being displayed.
|
---|
830 | ((BufferedImageBackgroundPainterStrategy)backgroundPainter).
|
---|
831 | setImage(image);
|
---|
832 | }
|
---|
833 | else { // Was a color strategy...
|
---|
834 | BufferedImageBackgroundPainterStrategy strategy =
|
---|
835 | new BufferedImageBackgroundPainterStrategy(this);
|
---|
836 | strategy.setImage(image);
|
---|
837 | backgroundPainter = strategy;
|
---|
838 | }
|
---|
839 | setOpaque(false);
|
---|
840 | firePropertyChange(BACKGROUND_IMAGE_PROPERTY, oldBG, image);
|
---|
841 | repaint();
|
---|
842 | }
|
---|
843 |
|
---|
844 |
|
---|
845 | /**
|
---|
846 | * Makes the background into this <code>Object</code>.
|
---|
847 | *
|
---|
848 | * @param newBackground The <code>java.awt.Color</code> or
|
---|
849 | * <code>java.awt.Image</code> object. If <code>newBackground</code>
|
---|
850 | * is not either of these, the background is set to plain white.
|
---|
851 | */
|
---|
852 | public void setBackgroundObject(Object newBackground) {
|
---|
853 | if (newBackground instanceof Color) {
|
---|
854 | setBackground((Color)newBackground);
|
---|
855 | }
|
---|
856 | else if (newBackground instanceof Image) {
|
---|
857 | setBackgroundImage((Image)newBackground);
|
---|
858 | }
|
---|
859 | else {
|
---|
860 | setBackground(Color.WHITE);
|
---|
861 | }
|
---|
862 |
|
---|
863 | }
|
---|
864 |
|
---|
865 |
|
---|
866 | /*
|
---|
867 | * TODO: Figure out why RTextArea doesn't work with RTL (e.g. Arabic)
|
---|
868 | * and fix it!
|
---|
869 | */
|
---|
870 | // public void setComponentOrientation(ComponentOrientation o) {
|
---|
871 | // if (!o.isLeftToRight()) {
|
---|
872 | // o = ComponentOrientation.LEFT_TO_RIGHT;
|
---|
873 | // }
|
---|
874 | // super.setComponentOrientation(o);
|
---|
875 | // }
|
---|
876 |
|
---|
877 |
|
---|
878 | /**
|
---|
879 | * Sets the color to use to highlight the current line. Note that if
|
---|
880 | * highlighting the current line is turned off, you will not be able to
|
---|
881 | * see this highlight. This method fires a property change of type
|
---|
882 | * {@link #CURRENT_LINE_HIGHLIGHT_COLOR_PROPERTY}.
|
---|
883 | *
|
---|
884 | * @param color The color to use to highlight the current line.
|
---|
885 | * @throws NullPointerException if <code>color</code> is <code>null</code>.
|
---|
886 | * @see #getHighlightCurrentLine()
|
---|
887 | * @see #setHighlightCurrentLine(boolean)
|
---|
888 | * @see #getCurrentLineHighlightColor
|
---|
889 | */
|
---|
890 | public void setCurrentLineHighlightColor(Color color) {
|
---|
891 | if (color==null)
|
---|
892 | throw new NullPointerException();
|
---|
893 | if (!color.equals(currentLineColor)) {
|
---|
894 | Color old = currentLineColor;
|
---|
895 | currentLineColor = color;
|
---|
896 | firePropertyChange(CURRENT_LINE_HIGHLIGHT_COLOR_PROPERTY,
|
---|
897 | old, color);
|
---|
898 | }
|
---|
899 | }
|
---|
900 |
|
---|
901 |
|
---|
902 | /**
|
---|
903 | * Sets whether the current line highlight should have a "fade" effect.
|
---|
904 | * This method fires a property change event of type
|
---|
905 | * <code>CURRENT_LINE_HIGHLIGHT_FADE_PROPERTY</code>.
|
---|
906 | *
|
---|
907 | * @param fade Whether the fade effect should be enabled.
|
---|
908 | * @see #getFadeCurrentLineHighlight
|
---|
909 | */
|
---|
910 | public void setFadeCurrentLineHighlight(boolean fade) {
|
---|
911 | if (fade!=fadeCurrentLineHighlight) {
|
---|
912 | fadeCurrentLineHighlight = fade;
|
---|
913 | if (getHighlightCurrentLine())
|
---|
914 | forceCurrentLineHighlightRepaint();
|
---|
915 | firePropertyChange(CURRENT_LINE_HIGHLIGHT_FADE_PROPERTY,
|
---|
916 | !fade, fade);
|
---|
917 | }
|
---|
918 | }
|
---|
919 |
|
---|
920 |
|
---|
921 | /**
|
---|
922 | * Sets the font for this text area. This is overridden only so that we
|
---|
923 | * can update the size of the "current line highlight" and the location of
|
---|
924 | * the "margin line," if necessary.
|
---|
925 | *
|
---|
926 | * @param font The font to use for this text component.
|
---|
927 | */
|
---|
928 | public void setFont(Font font) {
|
---|
929 | super.setFont(font);
|
---|
930 | updateMarginLineX();
|
---|
931 | if (highlightCurrentLine)
|
---|
932 | possiblyUpdateCurrentLineHighlightLocation();
|
---|
933 | }
|
---|
934 |
|
---|
935 |
|
---|
936 | /**
|
---|
937 | * Sets whether or not the current line is highlighted. This method
|
---|
938 | * fires a property change of type {@link #HIGHLIGHT_CURRENT_LINE_PROPERTY}.
|
---|
939 | *
|
---|
940 | * @param highlight Whether or not to highlight the current line.
|
---|
941 | * @see #getHighlightCurrentLine()
|
---|
942 | * @see #getCurrentLineHighlightColor
|
---|
943 | * @see #setCurrentLineHighlightColor
|
---|
944 | */
|
---|
945 | public void setHighlightCurrentLine(boolean highlight) {
|
---|
946 | if (highlight!=highlightCurrentLine) {
|
---|
947 | highlightCurrentLine = highlight;
|
---|
948 | firePropertyChange(HIGHLIGHT_CURRENT_LINE_PROPERTY,
|
---|
949 | !highlight, highlight);
|
---|
950 | repaint(); // Repaint entire width of line.
|
---|
951 | }
|
---|
952 | }
|
---|
953 |
|
---|
954 |
|
---|
955 | /**
|
---|
956 | * Sets whether or not word wrap is enabled. This is overridden so that
|
---|
957 | * the "current line highlight" gets updated if it needs to be.
|
---|
958 | *
|
---|
959 | * @param wrap Whether or not word wrap should be enabled.
|
---|
960 | */
|
---|
961 | public void setLineWrap(boolean wrap) {
|
---|
962 | super.setLineWrap(wrap);
|
---|
963 | forceCurrentLineHighlightRepaint();
|
---|
964 | }
|
---|
965 |
|
---|
966 |
|
---|
967 | /**
|
---|
968 | * Sets the color used to paint the margin line.
|
---|
969 | *
|
---|
970 | * @param color The new margin line color.
|
---|
971 | * @see #getDefaultMarginLineColor()
|
---|
972 | * @see #getMarginLineColor()
|
---|
973 | */
|
---|
974 | public void setMarginLineColor(Color color) {
|
---|
975 | marginLineColor = color;
|
---|
976 | if (marginLineEnabled) {
|
---|
977 | Rectangle visibleRect = getVisibleRect();
|
---|
978 | repaint(marginLineX,visibleRect.y, 1,visibleRect.height);
|
---|
979 | }
|
---|
980 | }
|
---|
981 |
|
---|
982 |
|
---|
983 | /**
|
---|
984 | * Enables or disables the margin line.
|
---|
985 | *
|
---|
986 | * @param enabled Whether or not the margin line should be enabled.
|
---|
987 | * @see #isMarginLineEnabled
|
---|
988 | */
|
---|
989 | public void setMarginLineEnabled(boolean enabled) {
|
---|
990 | if (enabled!=marginLineEnabled) {
|
---|
991 | marginLineEnabled = enabled;
|
---|
992 | if (marginLineEnabled) {
|
---|
993 | Rectangle visibleRect = getVisibleRect();
|
---|
994 | repaint(marginLineX,visibleRect.y, 1,visibleRect.height);
|
---|
995 | }
|
---|
996 | }
|
---|
997 | }
|
---|
998 |
|
---|
999 |
|
---|
1000 | /**
|
---|
1001 | * Sets the number of 'm' widths the margin line is over.
|
---|
1002 | *
|
---|
1003 | * @param size The margin size.
|
---|
1004 | * #see #getDefaultMarginLinePosition
|
---|
1005 | * @see #getMarginLinePosition
|
---|
1006 | */
|
---|
1007 | public void setMarginLinePosition(int size) {
|
---|
1008 | marginSizeInChars = size;
|
---|
1009 | if (marginLineEnabled) {
|
---|
1010 | Rectangle visibleRect = getVisibleRect();
|
---|
1011 | repaint(marginLineX,visibleRect.y, 1,visibleRect.height);
|
---|
1012 | updateMarginLineX();
|
---|
1013 | repaint(marginLineX,visibleRect.y, 1,visibleRect.height);
|
---|
1014 | }
|
---|
1015 | }
|
---|
1016 |
|
---|
1017 |
|
---|
1018 | /**
|
---|
1019 | * Sets whether the edges of selections are rounded in this text area.
|
---|
1020 | * This method fires a property change of type
|
---|
1021 | * {@link #ROUNDED_SELECTION_PROPERTY}.
|
---|
1022 | *
|
---|
1023 | * @param rounded Whether selection edges should be rounded.
|
---|
1024 | * @see #getRoundedSelectionEdges()
|
---|
1025 | */
|
---|
1026 | public void setRoundedSelectionEdges(boolean rounded) {
|
---|
1027 | if (roundedSelectionEdges!=rounded) {
|
---|
1028 | roundedSelectionEdges = rounded;
|
---|
1029 | ConfigurableCaret cc = (ConfigurableCaret)getCaret();
|
---|
1030 | cc.setRoundedSelectionEdges(rounded);
|
---|
1031 | if (cc.getDot()!=cc.getMark()) { // ie, if there is a selection
|
---|
1032 | repaint();
|
---|
1033 | }
|
---|
1034 | firePropertyChange(ROUNDED_SELECTION_PROPERTY, !rounded,
|
---|
1035 | rounded);
|
---|
1036 | }
|
---|
1037 | }
|
---|
1038 |
|
---|
1039 |
|
---|
1040 | /**
|
---|
1041 | * Sets the UI for this <code>RTextArea</code>. Note that, for instances
|
---|
1042 | * of <code>RTextArea</code>, <code>setUI</code> only updates the popup
|
---|
1043 | * menu; this is because <code>RTextArea</code>s' look and feels are
|
---|
1044 | * independent of the Java Look and Feel. This method is here so
|
---|
1045 | * subclasses can set a UI (subclass of <code>RTextAreaUI</code>) if they
|
---|
1046 | * have to.
|
---|
1047 | *
|
---|
1048 | * @param ui The new UI.
|
---|
1049 | * @see #setUI
|
---|
1050 | */
|
---|
1051 | protected void setRTextAreaUI(RTextAreaUI ui) {
|
---|
1052 |
|
---|
1053 | super.setUI(ui);
|
---|
1054 |
|
---|
1055 | // Workaround as setUI makes the text area opaque, even if we don't
|
---|
1056 | // want it to be.
|
---|
1057 | setOpaque(getBackgroundObject() instanceof Color);
|
---|
1058 |
|
---|
1059 | }
|
---|
1060 |
|
---|
1061 |
|
---|
1062 | /**
|
---|
1063 | * Changes whether or not tabs should be emulated with spaces (i.e., soft
|
---|
1064 | * tabs). Note that this affects all tabs inserted AFTER this call, not
|
---|
1065 | * tabs already in the document. For that, see
|
---|
1066 | * {@link #convertTabsToSpaces} and {@link #convertSpacesToTabs}.
|
---|
1067 | *
|
---|
1068 | * @param areEmulated Whether or not tabs should be emulated with spaces.
|
---|
1069 | * @see #convertSpacesToTabs
|
---|
1070 | * @see #convertTabsToSpaces
|
---|
1071 | * @see #getTabsEmulated
|
---|
1072 | */
|
---|
1073 | public void setTabsEmulated(boolean areEmulated) {
|
---|
1074 | tabsEmulatedWithSpaces = areEmulated;
|
---|
1075 | }
|
---|
1076 |
|
---|
1077 |
|
---|
1078 | /**
|
---|
1079 | * Workaround, since in JDK1.4 it appears that <code>setTabSize()</code>
|
---|
1080 | * doesn't work for a <code>JTextArea</code> unless you use the constructor
|
---|
1081 | * specifying the number of rows and columns...<p>
|
---|
1082 | * Sets the number of characters to expand tabs to. This will be multiplied
|
---|
1083 | * by the maximum advance for variable width fonts. A PropertyChange event
|
---|
1084 | * ("tabSize") is fired when the tab size changes.
|
---|
1085 | *
|
---|
1086 | * @param size Number of characters to expand to.
|
---|
1087 | */
|
---|
1088 | public void setTabSize(int size) {
|
---|
1089 | super.setTabSize(size);
|
---|
1090 | boolean b = getLineWrap();
|
---|
1091 | setLineWrap(!b);
|
---|
1092 | setLineWrap(b);
|
---|
1093 | }
|
---|
1094 |
|
---|
1095 |
|
---|
1096 | /**
|
---|
1097 | * This is here so subclasses such as <code>RSyntaxTextArea</code> that
|
---|
1098 | * have multiple fonts can define exactly what it means, for example, for
|
---|
1099 | * the margin line to be "80 characters" over.
|
---|
1100 | */
|
---|
1101 | protected void updateMarginLineX() {
|
---|
1102 | marginLineX = getFontMetrics(getFont()).charWidth('m') *
|
---|
1103 | marginSizeInChars;
|
---|
1104 | }
|
---|
1105 |
|
---|
1106 |
|
---|
1107 | /**
|
---|
1108 | * Returns the y-coordinate of the specified line.
|
---|
1109 | *
|
---|
1110 | * @param line The line number.
|
---|
1111 | * @return The y-coordinate of the top of the line, or <code>-1</code> if
|
---|
1112 | * this text area doesn't yet have a positive size or the line is
|
---|
1113 | * hidden (i.e. from folding).
|
---|
1114 | * @throws BadLocationException If <code>line</code> isn't a valid line
|
---|
1115 | * number for this document.
|
---|
1116 | */
|
---|
1117 | public int yForLine(int line) throws BadLocationException {
|
---|
1118 | return ((RTextAreaUI)getUI()).yForLine(line);
|
---|
1119 | }
|
---|
1120 |
|
---|
1121 |
|
---|
1122 | /**
|
---|
1123 | * Returns the y-coordinate of the line containing an offset.
|
---|
1124 | *
|
---|
1125 | * @param offs The offset info the document.
|
---|
1126 | * @return The y-coordinate of the top of the offset, or <code>-1</code> if
|
---|
1127 | * this text area doesn't yet have a positive size or the line is
|
---|
1128 | * hidden (i.e. from folding).
|
---|
1129 | * @throws BadLocationException If <code>offs</code> isn't a valid offset
|
---|
1130 | * into the document.
|
---|
1131 | */
|
---|
1132 | public int yForLineContaining(int offs) throws BadLocationException {
|
---|
1133 | return ((RTextAreaUI)getUI()).yForLineContaining(offs);
|
---|
1134 | }
|
---|
1135 |
|
---|
1136 |
|
---|
1137 | protected class RTAMouseListener extends CaretEvent implements
|
---|
1138 | MouseListener, MouseMotionListener, FocusListener {
|
---|
1139 |
|
---|
1140 | RTAMouseListener(RTextAreaBase textArea) {
|
---|
1141 | super(textArea);
|
---|
1142 | }
|
---|
1143 |
|
---|
1144 | public void focusGained(FocusEvent e) {}
|
---|
1145 | public void focusLost(FocusEvent e) {}
|
---|
1146 | public void mouseDragged(MouseEvent e) {}
|
---|
1147 | public void mouseMoved(MouseEvent e) {}
|
---|
1148 | public void mouseClicked(MouseEvent e) {}
|
---|
1149 | public void mousePressed(MouseEvent e) {}
|
---|
1150 | public void mouseReleased(MouseEvent e) {}
|
---|
1151 | public void mouseEntered(MouseEvent e) {}
|
---|
1152 | public void mouseExited(MouseEvent e) {}
|
---|
1153 |
|
---|
1154 | public int getDot() {
|
---|
1155 | return dot;
|
---|
1156 | }
|
---|
1157 |
|
---|
1158 | public int getMark() {
|
---|
1159 | return mark;
|
---|
1160 | }
|
---|
1161 |
|
---|
1162 | protected int dot;
|
---|
1163 | protected int mark;
|
---|
1164 |
|
---|
1165 | }
|
---|
1166 |
|
---|
1167 |
|
---|
1168 | } |
---|