Statistics
| Revision:

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 @ 1440

History | View | Annotate | Download (24.3 KB)

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