gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.swing / org.gvsig.scripting.swing.impl / src / main / java / org / gvsig / scripting / swing / impl / syntaxhighlight / JRSyntaxTextArea.java @ 1486
History | View | Annotate | Download (24.6 KB)
1 |
package org.gvsig.scripting.swing.impl.syntaxhighlight; |
---|---|
2 |
|
3 |
import java.awt.BorderLayout; |
4 |
import java.awt.Color; |
5 |
import java.awt.Component; |
6 |
import java.awt.Container; |
7 |
import java.awt.Cursor; |
8 |
import java.awt.Dimension; |
9 |
import java.awt.Font; |
10 |
import java.awt.Point; |
11 |
import java.awt.Rectangle; |
12 |
import java.awt.event.ActionEvent; |
13 |
import java.awt.event.ActionListener; |
14 |
import java.awt.event.FocusListener; |
15 |
import java.awt.event.InputEvent; |
16 |
import java.awt.event.KeyEvent; |
17 |
import java.awt.event.KeyListener; |
18 |
import java.awt.event.MouseAdapter; |
19 |
import java.awt.event.MouseEvent; |
20 |
import java.net.URL; |
21 |
import java.util.ArrayList; |
22 |
import java.util.Arrays; |
23 |
import java.util.Comparator; |
24 |
import java.util.HashMap; |
25 |
import java.util.HashSet; |
26 |
import java.util.List; |
27 |
import java.util.Map; |
28 |
import java.util.Set; |
29 |
import java.util.TreeSet; |
30 |
import javax.swing.DefaultListCellRenderer; |
31 |
import javax.swing.Icon; |
32 |
import javax.swing.ImageIcon; |
33 |
import javax.swing.JCheckBox; |
34 |
import javax.swing.JComponent; |
35 |
import javax.swing.JLabel; |
36 |
import javax.swing.JList; |
37 |
import javax.swing.JOptionPane; |
38 |
import javax.swing.JPanel; |
39 |
|
40 |
import javax.swing.JScrollPane; |
41 |
import javax.swing.JViewport; |
42 |
import javax.swing.KeyStroke; |
43 |
import javax.swing.SwingUtilities; |
44 |
import javax.swing.UIDefaults; |
45 |
import javax.swing.UIManager; |
46 |
import javax.swing.event.CaretEvent; |
47 |
import javax.swing.event.CaretListener; |
48 |
import javax.swing.text.BadLocationException; |
49 |
import javax.swing.text.Element; |
50 |
import javax.swing.text.JTextComponent; |
51 |
import org.apache.commons.lang3.StringUtils; |
52 |
import org.fife.rsta.ui.CollapsibleSectionPanel; |
53 |
import org.fife.rsta.ui.search.FindToolBar; |
54 |
import org.fife.rsta.ui.search.ReplaceToolBar; |
55 |
import org.fife.rsta.ui.search.SearchEvent; |
56 |
import org.fife.rsta.ui.search.SearchListener; |
57 |
import org.fife.ui.autocomplete.AutoCompletion; |
58 |
import org.fife.ui.autocomplete.BasicCompletion; |
59 |
import org.fife.ui.autocomplete.Completion; |
60 |
import org.fife.ui.autocomplete.CompletionProvider; |
61 |
import org.fife.ui.autocomplete.DefaultCompletionProvider; |
62 |
|
63 |
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; |
64 |
import org.fife.ui.rsyntaxtextarea.SyntaxConstants; |
65 |
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory; |
66 |
import org.fife.ui.rtextarea.GutterIconInfo; |
67 |
import org.fife.ui.rtextarea.RTextScrollPane; |
68 |
import org.fife.ui.rtextarea.SearchContext; |
69 |
import org.fife.ui.rtextarea.SearchEngine; |
70 |
import org.fife.ui.rtextarea.SearchResult; |
71 |
import org.gvsig.scripting.swing.api.ScriptingSwingLocator; |
72 |
import org.gvsig.scripting.swing.api.ScriptingUIManager; |
73 |
import org.gvsig.scripting.swing.api.SyntaxtHighlightTextComponent; |
74 |
import org.slf4j.Logger; |
75 |
import org.slf4j.LoggerFactory; |
76 |
|
77 |
public class JRSyntaxTextArea implements SyntaxtHighlightTextComponent, SearchListener { |
78 |
|
79 |
private static final Logger logger = LoggerFactory.getLogger(JRSyntaxTextArea.class); |
80 |
|
81 |
public static class MyCheckBox extends JCheckBox { |
82 |
|
83 |
private static final String uiClassID = "ToggleButtonUI"; |
84 |
|
85 |
@Override
|
86 |
public String getUIClassID() { |
87 |
return uiClassID;
|
88 |
} |
89 |
|
90 |
} |
91 |
|
92 |
private class MyFindToolBar extends FindToolBar { |
93 |
|
94 |
public MyFindToolBar(SearchListener listener) {
|
95 |
super(listener);
|
96 |
} |
97 |
|
98 |
@Override
|
99 |
protected JCheckBox createCB(String key) { |
100 |
JCheckBox cb = new MyCheckBox(); |
101 |
cb.setToolTipText(searchMsg.getString(key)); |
102 |
cb.addActionListener(listener); |
103 |
cb.addMouseListener(listener); |
104 |
cb.setIcon(getIcon("scripting-search-" + key.toLowerCase()));
|
105 |
return cb;
|
106 |
} |
107 |
|
108 |
} |
109 |
|
110 |
private class MyReplaceToolBar extends ReplaceToolBar { |
111 |
|
112 |
public MyReplaceToolBar(SearchListener listener) {
|
113 |
super(listener);
|
114 |
} |
115 |
|
116 |
@Override
|
117 |
protected JCheckBox createCB(String key) { |
118 |
JCheckBox cb = new MyCheckBox(); |
119 |
cb.setToolTipText(searchMsg.getString(key)); |
120 |
cb.addActionListener(listener); |
121 |
cb.addMouseListener(listener); |
122 |
cb.setIcon(getIcon("scripting-search-" + key.toLowerCase()));
|
123 |
return cb;
|
124 |
} |
125 |
} |
126 |
|
127 |
private class LineTrackerPanel extends JPanel { |
128 |
|
129 |
private static final long serialVersionUID = -1923556745197997373L; |
130 |
|
131 |
private class Line extends JLabel { |
132 |
|
133 |
private static final long serialVersionUID = 8966359978957026490L; |
134 |
private final int lineno; |
135 |
private final String tag; |
136 |
|
137 |
public Line(String tag, final int lineno, int posy, Color color, String tooltip) { |
138 |
UIDefaults uidefaults = UIManager.getLookAndFeel().getDefaults(); |
139 |
this.setBackground((Color) uidefaults.get("EditorPane.background")); |
140 |
this.setForeground((Color) uidefaults.get("EditorPane.foreground")); |
141 |
|
142 |
this.lineno = lineno;
|
143 |
this.tag = tag;
|
144 |
this.setBackground(color);
|
145 |
this.setBounds(0, posy, 15, 2); |
146 |
this.setOpaque(true); |
147 |
this.setToolTipText(tooltip);
|
148 |
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
149 |
this.addMouseListener(new MouseAdapter() { |
150 |
|
151 |
@Override
|
152 |
public void mouseClicked(MouseEvent e) { |
153 |
gotoline(lineno); |
154 |
} |
155 |
}); |
156 |
// Rectangle r = this.getBounds();
|
157 |
// logger.info("LineTracker: created lineno:"+lineno+", tag:"+tag+", x:"+ r.x + ", y:"+ r.y + ", w:"+ r.width+", h:"+ r.height);
|
158 |
} |
159 |
|
160 |
public int getLineno() { |
161 |
return this.lineno; |
162 |
} |
163 |
|
164 |
public String getTag() { |
165 |
return this.tag; |
166 |
} |
167 |
} |
168 |
|
169 |
public LineTrackerPanel() {
|
170 |
setLayout(null);
|
171 |
} |
172 |
|
173 |
@Override
|
174 |
public Dimension getPreferredSize() { |
175 |
Dimension d = super.getPreferredSize(); |
176 |
return new Dimension(15, d.height); |
177 |
} |
178 |
|
179 |
public void addLineTracker(String tag, int lineno, String tooltip, Color color) { |
180 |
int posy = (int) (((float)lineno)*this.getSize().height / textArea.getLineCount()); |
181 |
Line line = new Line(tag,lineno,posy,color,tooltip); |
182 |
this.add(line);
|
183 |
this.repaint();
|
184 |
} |
185 |
|
186 |
public void removeLineTrackers() { |
187 |
this.removeAll();
|
188 |
this.repaint();
|
189 |
} |
190 |
|
191 |
public void removeLineTrackers(String tag) { |
192 |
if( StringUtils.isEmpty(tag) ) {
|
193 |
return;
|
194 |
} |
195 |
List<Line> toremove = new ArrayList<>(); |
196 |
for( int i=0; i<this.getComponentCount(); i++ ) { |
197 |
Line line = (Line) this.getComponent(i); |
198 |
if( tag.equalsIgnoreCase(line.getTag()) ) {
|
199 |
toremove.add(line); |
200 |
} |
201 |
} |
202 |
for (Line line : toremove) { |
203 |
this.remove(line);
|
204 |
} |
205 |
this.repaint();
|
206 |
} |
207 |
} |
208 |
|
209 |
private static class IconsTracker { |
210 |
|
211 |
private Map<String,Set<GutterIconInfo>>iconInfos = new HashMap<>(); |
212 |
|
213 |
public IconsTracker() {
|
214 |
|
215 |
} |
216 |
|
217 |
public void add(String tag, GutterIconInfo x) { |
218 |
Set<GutterIconInfo> set = this.iconInfos.get(tag); |
219 |
if( set == null ) { |
220 |
set = new HashSet<>(); |
221 |
this.iconInfos.put(tag, set);
|
222 |
} |
223 |
set.add(x); |
224 |
} |
225 |
|
226 |
public void removeAll() { |
227 |
this.iconInfos = new HashMap<>(); |
228 |
} |
229 |
|
230 |
public void remove(String tag) { |
231 |
this.iconInfos.remove(tag);
|
232 |
} |
233 |
|
234 |
public void remove(String tag, GutterIconInfo x) { |
235 |
Set<GutterIconInfo> set = this.iconInfos.get(tag); |
236 |
if( set == null ) { |
237 |
return;
|
238 |
} |
239 |
set.remove(x); |
240 |
} |
241 |
|
242 |
public boolean exists(String tag) { |
243 |
return this.iconInfos.containsKey(tag); |
244 |
} |
245 |
|
246 |
public Set<GutterIconInfo> get(String tag) { |
247 |
Set<GutterIconInfo> set = this.iconInfos.get(tag); |
248 |
return set;
|
249 |
} |
250 |
} |
251 |
|
252 |
private final FindToolBar findToolBar; |
253 |
private final ReplaceToolBar replaceToolBar; |
254 |
private final CollapsibleSectionPanel csp; |
255 |
|
256 |
public class DefaultUpdateCaretPositionActionEvent extends ActionEvent implements UpdateCaretPositionActionEvent { |
257 |
|
258 |
/**
|
259 |
*
|
260 |
*/
|
261 |
private static final long serialVersionUID = 8238486105726094074L; |
262 |
int line = -1; |
263 |
int column = -1; |
264 |
|
265 |
public DefaultUpdateCaretPositionActionEvent(Object source, int id, |
266 |
String command, int line, int column) { |
267 |
super(source, id, command);
|
268 |
this.line = line;
|
269 |
this.column = column;
|
270 |
} |
271 |
|
272 |
public int getLine() { |
273 |
return this.line + 1; |
274 |
} |
275 |
|
276 |
public int getColumn() { |
277 |
return this.column; |
278 |
} |
279 |
|
280 |
public boolean hasLineAndColumn() { |
281 |
return this.line >= 0 && this.column >= 0; |
282 |
} |
283 |
|
284 |
} |
285 |
|
286 |
protected ActionListener updateCaretPosition = null; |
287 |
protected RSyntaxTextArea textArea = null; |
288 |
private final RTextScrollPane scrollPanel; |
289 |
private final JPanel panel; |
290 |
private final Map<String, String> contentTypeAlias; |
291 |
private final IconsTracker iconsTracker = new IconsTracker(); |
292 |
private LineTrackerPanel lineTrackerPanel;
|
293 |
private ScriptingUIManager scriptingUIManager;
|
294 |
|
295 |
|
296 |
public JRSyntaxTextArea() {
|
297 |
this.contentTypeAlias = new HashMap<>(); |
298 |
this.contentTypeAlias.put("text/r", SyntaxConstants.SYNTAX_STYLE_C); |
299 |
this.contentTypeAlias.put("text/ecmascript", SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT); |
300 |
this.contentTypeAlias.put("text/cosa", SyntaxConstants.SYNTAX_STYLE_SQL); |
301 |
|
302 |
this.textArea = new RSyntaxTextArea(20, 60); |
303 |
|
304 |
UIDefaults uidefaults = UIManager.getLookAndFeel().getDefaults(); |
305 |
|
306 |
// https://alvinalexander.com/java/java-uimanager-color-keys-list/
|
307 |
this.textArea.setBackground((Color) uidefaults.get("EditorPane.background")); |
308 |
this.textArea.setForeground((Color) uidefaults.get("EditorPane.foreground")); |
309 |
this.textArea.setFont((Font) uidefaults.get("EditorPane.font")); |
310 |
|
311 |
this.init();
|
312 |
lineTrackerPanel = new LineTrackerPanel();
|
313 |
this.scrollPanel = new RTextScrollPane(this.textArea); |
314 |
this.scrollPanel.setBackground((Color) uidefaults.get("EditorPane.background")); |
315 |
this.scrollPanel.setForeground((Color) uidefaults.get("EditorPane.foreground")); |
316 |
this.scrollPanel.setFont((Font) uidefaults.get("EditorPane.font")); |
317 |
this.scrollPanel.setIconRowHeaderEnabled(true); |
318 |
this.scrollPanel.setLineNumbersEnabled(true); |
319 |
this.scrollPanel.setFoldIndicatorEnabled(true); |
320 |
|
321 |
panel = new JPanel(); |
322 |
panel.setLayout(new BorderLayout()); |
323 |
panel.add(scrollPanel, BorderLayout.CENTER);
|
324 |
panel.add(lineTrackerPanel,BorderLayout.EAST);
|
325 |
|
326 |
findToolBar = new MyFindToolBar(this); |
327 |
replaceToolBar = new MyReplaceToolBar(this); |
328 |
replaceToolBar.setSearchContext(findToolBar.getSearchContext()); |
329 |
csp = new CollapsibleSectionPanel();
|
330 |
csp.add(scrollPanel); |
331 |
panel.add(csp, BorderLayout.CENTER);
|
332 |
int ctrl = (KeyEvent.CTRL_MASK | KeyEvent.ALT_MASK); |
333 |
KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F, ctrl); |
334 |
csp.addBottomComponent(ks, findToolBar); |
335 |
ks = KeyStroke.getKeyStroke(KeyEvent.VK_H, ctrl); |
336 |
csp.addBottomComponent(ks, replaceToolBar); |
337 |
|
338 |
textArea.addKeyListener(new KeyListener() { |
339 |
|
340 |
@Override
|
341 |
public void keyTyped(KeyEvent ke) { |
342 |
} |
343 |
|
344 |
@Override
|
345 |
public void keyPressed(KeyEvent ke) { |
346 |
if (ke.getModifiers() == (KeyEvent.CTRL_MASK | KeyEvent.ALT_MASK)) { |
347 |
if (ke.getKeyCode() == KeyEvent.VK_H) { |
348 |
csp.showBottomComponent(replaceToolBar); |
349 |
} else if (ke.getKeyCode() == KeyEvent.VK_F) { |
350 |
csp.showBottomComponent(findToolBar); |
351 |
} |
352 |
} |
353 |
} |
354 |
|
355 |
@Override
|
356 |
public void keyReleased(KeyEvent ke) { |
357 |
} |
358 |
}); |
359 |
|
360 |
} |
361 |
|
362 |
protected void init() { |
363 |
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PYTHON); |
364 |
textArea.setCodeFoldingEnabled(true);
|
365 |
textArea.setClearWhitespaceLinesEnabled(true);
|
366 |
textArea.setAutoIndentEnabled(true);
|
367 |
textArea.setCloseCurlyBraces(true);
|
368 |
textArea.setWhitespaceVisible(true);
|
369 |
textArea.setAnimateBracketMatching(true);
|
370 |
textArea.setBracketMatchingEnabled(true);
|
371 |
textArea.setAutoIndentEnabled(true);
|
372 |
textArea.setTabsEmulated(true);
|
373 |
textArea.setTabSize(2);
|
374 |
textArea.setAntiAliasingEnabled(true);
|
375 |
|
376 |
textArea.addCaretListener(new CaretListener() { |
377 |
public void caretUpdate(CaretEvent e) { |
378 |
if (updateCaretPosition == null) { |
379 |
return;
|
380 |
} |
381 |
updateCaretPosition.actionPerformed( |
382 |
new DefaultUpdateCaretPositionActionEvent(textArea, 1, "position", textArea.getCaretLineNumber(), textArea.getCaretOffsetFromLineStart()) |
383 |
); |
384 |
} |
385 |
|
386 |
}); |
387 |
|
388 |
CompletionProvider provider = new MyCompletionProvider(python_keywords);
|
389 |
AutoCompletion ac = new AutoCompletion(provider);
|
390 |
ac.setListCellRenderer(new MyListCellRenderer());
|
391 |
ac.setTriggerKey(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.CTRL_DOWN_MASK)); |
392 |
ac.install(textArea); |
393 |
} |
394 |
|
395 |
private ScriptingUIManager getUIManager() {
|
396 |
if( this.scriptingUIManager==null ) { |
397 |
this.scriptingUIManager = ScriptingSwingLocator.getUIManager();
|
398 |
} |
399 |
return this.scriptingUIManager; |
400 |
} |
401 |
|
402 |
private ImageIcon getIcon(String key) { |
403 |
ImageIcon icon = this.getUIManager().getIcon(key); |
404 |
return icon;
|
405 |
} |
406 |
|
407 |
|
408 |
private static class MyListCellRenderer extends DefaultListCellRenderer { |
409 |
|
410 |
@Override
|
411 |
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { |
412 |
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); //To change body of generated methods, choose Tools | Templates. |
413 |
((JLabel) comp).setIcon(((Completion) value).getIcon());
|
414 |
return comp;
|
415 |
} |
416 |
|
417 |
} |
418 |
|
419 |
private String[] python_keywords = new String[]{ |
420 |
"except",
|
421 |
"class",
|
422 |
"continue",
|
423 |
"else",
|
424 |
"finally",
|
425 |
"if",
|
426 |
"elif",
|
427 |
"in",
|
428 |
"return",
|
429 |
"raise",
|
430 |
"try",
|
431 |
"while",
|
432 |
"def",
|
433 |
"print",
|
434 |
"globals",
|
435 |
"for",
|
436 |
"pass",
|
437 |
"from",
|
438 |
"import",
|
439 |
"True",
|
440 |
"False",
|
441 |
"None",
|
442 |
"self",
|
443 |
"break",
|
444 |
"__init__",
|
445 |
"__len__",
|
446 |
"__str__",
|
447 |
"__repr__",
|
448 |
"__call__",
|
449 |
"__iter__",
|
450 |
"__class__",
|
451 |
"__getattr__",
|
452 |
"__setattr__",
|
453 |
"__delattr__",
|
454 |
"__getitem__",
|
455 |
"__setitem__",
|
456 |
"__delitem__",
|
457 |
"__getslice__",
|
458 |
"__setslice__",
|
459 |
"__delslice__",
|
460 |
"__getattribute__",
|
461 |
"__setattribute__",
|
462 |
"__contains__",
|
463 |
"__reduce__",
|
464 |
"__cmp__",
|
465 |
"__eq__",
|
466 |
"__ne__",
|
467 |
"__lt__",
|
468 |
"__le__",
|
469 |
"__gt__",
|
470 |
"__ge__",
|
471 |
"__mul__",
|
472 |
"__imul__",
|
473 |
"__rmul__",
|
474 |
"__add__",
|
475 |
"__iadd__",
|
476 |
"__radd__",
|
477 |
"__mod__",
|
478 |
"__rmod__",
|
479 |
"int",
|
480 |
"unicode",
|
481 |
"str",
|
482 |
"float",
|
483 |
"long",
|
484 |
"list",
|
485 |
"tuple",
|
486 |
"dict",
|
487 |
"iter",
|
488 |
"vars",
|
489 |
"isinstance",
|
490 |
"dir",
|
491 |
"repr",
|
492 |
"reduce",
|
493 |
"zip",
|
494 |
"chr",
|
495 |
"hex",
|
496 |
"id",
|
497 |
"max",
|
498 |
"min",
|
499 |
"oct",
|
500 |
"pow",
|
501 |
"ord",
|
502 |
"unichr",
|
503 |
"range",
|
504 |
"xrange",
|
505 |
"abs",
|
506 |
"len",
|
507 |
"apply",
|
508 |
"open",
|
509 |
"getattr",
|
510 |
"setattr",
|
511 |
"hasattr"
|
512 |
}; |
513 |
|
514 |
private class MyCompletionProvider extends DefaultCompletionProvider { |
515 |
|
516 |
private List<Completion> keywords; |
517 |
private Icon keywordIcon; |
518 |
private Icon wordIcon; |
519 |
|
520 |
public MyCompletionProvider(String[] keywords) { |
521 |
ClassLoader loader = this.getClass().getClassLoader(); |
522 |
URL url = loader.getResource("org/gvsig/scripting/swing/impl/syntaxhighlight/images/autocompletion_keywords.png"); |
523 |
if (url != null) { |
524 |
keywordIcon = new ImageIcon(url); |
525 |
} |
526 |
url = loader.getResource("org/gvsig/scripting/swing/impl/syntaxhighlight/images/autocompletion_words.png");
|
527 |
if (url != null) { |
528 |
wordIcon = new ImageIcon(url); |
529 |
} |
530 |
|
531 |
this.keywords = new ArrayList<>(); |
532 |
for (String keyword : keywords) { |
533 |
BasicCompletion completion = new BasicCompletion(this, keyword); |
534 |
completion.setIcon(keywordIcon); |
535 |
this.keywords.add(completion);
|
536 |
} |
537 |
} |
538 |
|
539 |
|
540 |
|
541 |
@Override
|
542 |
protected List<Completion> getCompletionsImpl(JTextComponent comp) { |
543 |
TreeSet all = new TreeSet(); |
544 |
all.addAll(this.keywords);
|
545 |
|
546 |
String s = comp.getText();
|
547 |
String[] x = StringUtils.split(s, "\\ \n\t\r!\"><'@#|$%&/()=??,.;:{}[]*-+"); |
548 |
TreeSet<String> words = new TreeSet(new Comparator<String>() { |
549 |
@Override
|
550 |
public int compare(String o1, String o2) { |
551 |
return o1.compareTo(o2);
|
552 |
} |
553 |
}); |
554 |
words.addAll(Arrays.asList(x));
|
555 |
for (String word : words) { |
556 |
BasicCompletion completion = new BasicCompletion(this, word); |
557 |
completion.setIcon(wordIcon); |
558 |
completion.setRelevance(10);
|
559 |
all.add(completion); |
560 |
} |
561 |
completions = new ArrayList<>(); |
562 |
completions.addAll(all); |
563 |
return super.getCompletionsImpl(comp); |
564 |
} |
565 |
|
566 |
} |
567 |
|
568 |
private String normalizeContentType(String s) { |
569 |
s = s.toLowerCase(); |
570 |
if (this.contentTypeAlias.containsKey(s)) { |
571 |
s = this.contentTypeAlias.get(s);
|
572 |
} |
573 |
return s;
|
574 |
} |
575 |
|
576 |
public void setContentType(String contentType) { |
577 |
TokenMakerFactory factory = TokenMakerFactory.getDefaultInstance(); |
578 |
Set<String> mimetypes = factory.keySet(); |
579 |
String mimetype = this.normalizeContentType(contentType); |
580 |
if( !mimetypes.contains(mimetype)) {
|
581 |
mimetype = mimetype.replace("-source", ""); |
582 |
if( !mimetypes.contains(mimetype)) {
|
583 |
mimetype = mimetype.replace("/x-", "/"); |
584 |
if( !mimetypes.contains(mimetype)) {
|
585 |
mimetype = this.normalizeContentType(contentType);
|
586 |
} |
587 |
} |
588 |
} |
589 |
this.textArea.setSyntaxEditingStyle(mimetype);
|
590 |
} |
591 |
|
592 |
public JScrollPane getJScrollPane() { |
593 |
return this.scrollPanel; |
594 |
} |
595 |
|
596 |
public JTextComponent getJTextComponent() { |
597 |
return this.textArea; |
598 |
} |
599 |
|
600 |
@Override
|
601 |
public JComponent asJComponent() { |
602 |
return this.panel; |
603 |
} |
604 |
|
605 |
public String getContentType() { |
606 |
return this.textArea.getSyntaxEditingStyle(); |
607 |
} |
608 |
|
609 |
public void addUpdateCaretPositionActionListener(ActionListener updateCaretPosition) { |
610 |
this.updateCaretPosition = updateCaretPosition;
|
611 |
} |
612 |
|
613 |
public void setText(String text) { |
614 |
this.textArea.setText(text);
|
615 |
} |
616 |
|
617 |
public String getText() { |
618 |
return this.textArea.getText(); |
619 |
} |
620 |
|
621 |
public void addKeyListener(KeyListener keyListener) { |
622 |
this.textArea.addKeyListener(keyListener);
|
623 |
} |
624 |
|
625 |
@Override
|
626 |
public void searchEvent(SearchEvent e) { |
627 |
|
628 |
SearchEvent.Type type = e.getType(); |
629 |
SearchContext context = e.getSearchContext(); |
630 |
SearchResult result = null; |
631 |
|
632 |
switch (type) {
|
633 |
default: // Prevent FindBugs warning later |
634 |
case MARK_ALL:
|
635 |
result = SearchEngine.markAll(textArea, context); |
636 |
break;
|
637 |
case FIND:
|
638 |
result = SearchEngine.find(textArea, context); |
639 |
if (!result.wasFound()) {
|
640 |
textArea.getCaret().setDot(0);
|
641 |
result = SearchEngine.find(textArea, context); |
642 |
if (!result.wasFound()) {
|
643 |
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
|
644 |
} |
645 |
} |
646 |
break;
|
647 |
case REPLACE:
|
648 |
result = SearchEngine.replace(textArea, context); |
649 |
if (!result.wasFound()) {
|
650 |
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
|
651 |
} |
652 |
break;
|
653 |
case REPLACE_ALL:
|
654 |
result = SearchEngine.replaceAll(textArea, context); |
655 |
JOptionPane.showMessageDialog(null, result.getCount() |
656 |
+ " occurrences replaced.");
|
657 |
break;
|
658 |
} |
659 |
String text = null; |
660 |
if (result.wasFound()) {
|
661 |
text = "Text found; occurrences marked: " + result.getMarkedCount();
|
662 |
} else if (type == SearchEvent.Type.MARK_ALL) { |
663 |
if (result.getMarkedCount() > 0) { |
664 |
text = "Occurrences marked: " + result.getMarkedCount();
|
665 |
} else {
|
666 |
text = "";
|
667 |
} |
668 |
} else {
|
669 |
text = "Text not found";
|
670 |
} |
671 |
//setMessage(text);
|
672 |
} |
673 |
|
674 |
@Override
|
675 |
public String getSelectedText() { |
676 |
return textArea.getSelectedText();
|
677 |
} |
678 |
|
679 |
/**
|
680 |
*
|
681 |
*/
|
682 |
@Override
|
683 |
public void discardAllEdits() { |
684 |
this.textArea.discardAllEdits();
|
685 |
} |
686 |
|
687 |
@Override
|
688 |
public void removeTrackingIcons() { |
689 |
this.scrollPanel.getGutter().removeAllTrackingIcons();
|
690 |
this.iconsTracker.removeAll();
|
691 |
this.lineTrackerPanel.removeLineTrackers();
|
692 |
} |
693 |
|
694 |
@Override
|
695 |
public void addLineTrackingIcon(String tag, int line, Icon icon, String tip) { |
696 |
addLineTrackingIcon(tag, line, icon, tip, Color.BLUE.darker());
|
697 |
} |
698 |
|
699 |
@Override
|
700 |
public void addLineTrackingIcon(String tag, int line, Icon icon, String tip, Color color) { |
701 |
try {
|
702 |
GutterIconInfo x = this.scrollPanel.getGutter().addLineTrackingIcon(line,icon,tip);
|
703 |
this.iconsTracker.add(tag, x);
|
704 |
this.lineTrackerPanel.addLineTracker(tag, line, tip, color);
|
705 |
} catch (BadLocationException ex) { |
706 |
throw new RuntimeException("Can't add tracking icon with tag '"+tag+"' in line '"+line+"', tip='"+tip+"'", ex); |
707 |
} |
708 |
} |
709 |
|
710 |
@Override
|
711 |
public void removeTrackingIcons(String tag) { |
712 |
Set<GutterIconInfo> icontags = this.iconsTracker.get(tag); |
713 |
if( icontags!=null ) { |
714 |
for (GutterIconInfo icontag : icontags) {
|
715 |
this.scrollPanel.getGutter().removeTrackingIcon(icontag);
|
716 |
} |
717 |
this.iconsTracker.remove(tag);
|
718 |
} |
719 |
this.lineTrackerPanel.removeLineTrackers(tag);
|
720 |
} |
721 |
|
722 |
@Override
|
723 |
public void gotoline(final int line) { |
724 |
JTextComponent component = getJTextComponent();
|
725 |
|
726 |
Element root = component.getDocument().getDefaultRootElement();
|
727 |
int lineno = Math.max(line, 1); |
728 |
int maxlines = root.getElementCount();
|
729 |
lineno = Math.min(lineno, maxlines);
|
730 |
int startOfLineOffset = root.getElement( lineno - 1 ).getStartOffset(); |
731 |
component.setCaretPosition( startOfLineOffset ); |
732 |
|
733 |
Container container = SwingUtilities.getAncestorOfClass(JViewport.class, component); |
734 |
if (container == null) { |
735 |
return;
|
736 |
} |
737 |
try {
|
738 |
Rectangle r = component.modelToView(component.getCaretPosition());
|
739 |
JViewport viewport = (JViewport) container; |
740 |
int extentHeight = viewport.getExtentSize().height;
|
741 |
int viewHeight = viewport.getViewSize().height;
|
742 |
|
743 |
int y = Math.max(0, r.y - ((extentHeight - r.height) / 2)); |
744 |
y = Math.min(y, viewHeight - extentHeight);
|
745 |
|
746 |
viewport.setViewPosition(new Point(0, y)); |
747 |
} catch (BadLocationException ble) { |
748 |
ble.printStackTrace(); |
749 |
} |
750 |
try {
|
751 |
component.setCaretPosition( startOfLineOffset+1 );
|
752 |
} catch (Exception e) { |
753 |
e.printStackTrace(); |
754 |
} |
755 |
} |
756 |
|
757 |
@Override
|
758 |
public void setEditable(boolean editable) { |
759 |
this.textArea.setEditable(editable);
|
760 |
} |
761 |
|
762 |
@Override
|
763 |
public boolean isEditable() { |
764 |
return this.textArea.isEditable(); |
765 |
} |
766 |
|
767 |
@Override
|
768 |
public void addFocusListener(FocusListener l) { |
769 |
this.textArea.addFocusListener(l);
|
770 |
} |
771 |
|
772 |
} |