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 / composer / SuggestionController.java @ 478

History | View | Annotate | Download (13.4 KB)

1
package org.gvsig.scripting.swing.impl.composer;
2

    
3
import java.awt.BorderLayout;
4
import java.awt.Dimension;
5
import java.awt.Point;
6
import java.awt.event.KeyEvent;
7
import java.awt.event.KeyListener;
8
import java.awt.event.WindowEvent;
9
import java.awt.event.WindowFocusListener;
10
import java.util.ArrayList;
11
import java.util.HashSet;
12
import java.util.List;
13
import java.util.Set;
14
import javax.swing.DefaultListModel;
15
import javax.swing.JFrame;
16
import javax.swing.JOptionPane;
17
import javax.swing.JTextArea;
18
import javax.swing.SwingUtilities;
19
import javax.swing.event.ListSelectionEvent;
20
import javax.swing.event.ListSelectionListener;
21
import org.apache.commons.lang3.StringUtils;
22
import org.gvsig.scripting.ScriptingHelpManager;
23
import org.gvsig.scripting.ScriptingHelpManager.ScriptingHelpClass;
24
import org.slf4j.Logger;
25
import org.slf4j.LoggerFactory;
26

    
27
public class SuggestionController extends SuggestionView {
28

    
29
    protected static final Logger logger = LoggerFactory.getLogger(SuggestionController.class);
30
    
31
    private static final List<ScriptingHelpClass> recentClasses = new ArrayList<ScriptingHelpClass>();
32
    private static final int MAX_RECENT_CLASSES = 10;
33
    
34
    private final JTextArea editor;
35
    private final String searchtext;
36
    private final ScriptingHelpManager manager;
37
    private final List<ScriptingHelpClass> helpClasses;
38
    private JFrame window;
39
    private int show_retries = 0;
40
    
41
    public SuggestionController(ScriptingHelpManager manager, JTextArea editor, String searchtext) {
42
        super();
43
        this.editor = editor;
44
        this.searchtext = searchtext;
45
        this.manager = manager;
46
        this.helpClasses = this.manager.getHelpClasses();
47

    
48
        this.initComponents();
49
    }
50

    
51
    private void initComponents() {
52

    
53
        this.lstClasses.addListSelectionListener(new ListSelectionListener() {
54

    
55
            @Override
56
            public void valueChanged(ListSelectionEvent e) {
57
                doUpdateMethodsList();
58
            }
59

    
60
        });
61
        this.lstClasses.addKeyListener(new KeyListener() {
62

    
63
            @Override
64
            public void keyTyped(KeyEvent e) {
65
                char ch = e.getKeyChar();
66
                if (ch == ' ' || ch == '\n') {
67
                    doUpdateMethodsList();
68
                    doToMethods();
69
                }
70
            }
71

    
72
            @Override
73
            public void keyPressed(KeyEvent e) {
74
            }
75

    
76
            @Override
77
            public void keyReleased(KeyEvent e) {
78
                switch (e.getKeyCode()) {
79
                    case KeyEvent.VK_ESCAPE:
80
                        doClose();
81
                        break;
82
                    case KeyEvent.VK_F1:
83
                        ScriptingHelpClass helpClass = getCurrentClass();
84
                        if( helpClass!=null ) {
85
                            JOptionPane.showMessageDialog(editor,"Oh!, falta por implementar. \nAqui sacar la ayuda de la clase '"+helpClass.getName()+"'.");
86
                        }
87
                        break;
88
                    case KeyEvent.VK_F2:
89
                        doToFilterClass();
90
                        break;
91
                    case KeyEvent.VK_F3:
92
                        doToMethods();
93
                        break;
94
                    case KeyEvent.VK_UP:
95
                        if( SuggestionController.this.lstClasses.getSelectedIndex()<1 ) {
96
                            doToFilterClass();
97
                        }
98
                        break;
99
                    case KeyEvent.VK_RIGHT:
100
                        doToMethods();
101
                        break;
102
                }
103
            }
104

    
105
        });
106

    
107
        this.txtClassFilter.addKeyListener(new KeyListener() {
108

    
109
            @Override
110
            public void keyTyped(KeyEvent e) {
111
                char ch = e.getKeyChar();
112
                if (ch == ' ' || ch == '\n') {
113
                    doUpdateClassesList();
114
                }
115
            }
116

    
117
            @Override
118
            public void keyPressed(KeyEvent e) {
119
            }
120

    
121
            @Override
122
            public void keyReleased(KeyEvent e) {
123
                switch (e.getKeyCode()) {
124
                    case KeyEvent.VK_ESCAPE:
125
                        doClose();
126
                        break;
127
                    case KeyEvent.VK_F2:
128
                    case KeyEvent.VK_DOWN:
129
                        doToClasses();
130
                        break;
131
                    case KeyEvent.VK_F3:
132
                        doToMethods();
133
                        break;
134
                    case KeyEvent.VK_RIGHT:
135
                        doToFilterMethod();
136
                        break;
137
                }
138
            }
139

    
140
        });
141
        
142
        this.lstMethods.addKeyListener(new KeyListener() {
143

    
144
            @Override
145
            public void keyTyped(KeyEvent e) {
146
                char ch = e.getKeyChar();
147
                if (ch == ' ' || ch == '\n') {
148
                    doSelectMethod();
149
                }
150
            }
151

    
152
            @Override
153
            public void keyPressed(KeyEvent e) {
154
            }
155

    
156
            @Override
157
            public void keyReleased(KeyEvent e) {
158
                switch (e.getKeyCode()) {
159
                    case KeyEvent.VK_ESCAPE:
160
                        doClose();
161
                        break;
162
                    case KeyEvent.VK_F2:
163
                        doToClasses();
164
                        break;
165
                    case KeyEvent.VK_F3:
166
                        doToFilterMethod();
167
                        break;
168
                    case KeyEvent.VK_LEFT:
169
                        doToClasses();
170
                        break;
171
                    case KeyEvent.VK_UP:
172
                        if( SuggestionController.this.lstMethods.getSelectedIndex()<1 ) {
173
                            doToFilterMethod();
174
                        }
175
                        break;
176
                }
177
            }
178

    
179
        });
180
        this.txtMethodFilter.addKeyListener(new KeyListener() {
181

    
182
            @Override
183
            public void keyTyped(KeyEvent e) {
184
                char ch = e.getKeyChar();
185
                if (ch == ' ' || ch == '\n') {
186
                    doUpdateMethodsList();
187
                }
188
            }
189

    
190
            @Override
191
            public void keyPressed(KeyEvent e) {
192
            }
193

    
194
            @Override
195
            public void keyReleased(KeyEvent e) {
196
                switch (e.getKeyCode()) {
197
                    case KeyEvent.VK_ESCAPE:
198
                        doClose();
199
                        break;
200
                    case KeyEvent.VK_F2:
201
                        doToClasses();
202
                        break;
203
                    case KeyEvent.VK_F3:
204
                    case KeyEvent.VK_DOWN:
205
                        doToMethods();
206
                        break;
207
                    case KeyEvent.VK_LEFT:
208
                        doToFilterClass();
209
                        break;
210
                }
211
            }
212

    
213
        });
214
        this.doUpdateClassesList();
215
        if( !StringUtils.isEmpty(searchtext) ) {
216
            this.txtMethodFilter.setText(searchtext);
217
            doUpdateMethodsList();
218
            doToMethods();
219
        }
220
    }
221

    
222
    private ScriptingHelpClass getCurrentClass() {
223
        return (ScriptingHelpClass) (this.lstClasses.getSelectedValue());
224
    }
225
    
226
    private void addToRecentClasses(ScriptingHelpClass helpClass) {
227
        recentClasses.add(0, helpClass);
228
        while( recentClasses.size()>MAX_RECENT_CLASSES ) {
229
            recentClasses.remove(MAX_RECENT_CLASSES-1);
230
        }
231
    }
232
    
233
    private void doToMethods() {
234
        this.lstMethods.requestFocus();
235
    }
236

    
237
    private void doToClasses() {
238
        this.lstClasses.requestFocus();
239
    }
240

    
241
    private void doToFilterClass() {
242
        this.txtClassFilter.requestFocus();
243
        this.txtClassFilter.setSelectionStart(0);
244
        this.txtClassFilter.setSelectionEnd(this.txtClassFilter.getText().length());
245
        this.lstClasses.setSelectedIndex(-1);
246
    }
247
    
248
    private void doToFilterMethod() {
249
        this.txtMethodFilter.requestFocus();
250
        this.txtMethodFilter.setSelectionStart(0);
251
        this.txtMethodFilter.setSelectionEnd(this.txtMethodFilter.getText().length());
252
        this.lstMethods.setSelectedIndex(-1);
253
    }
254

    
255
    private void doClose() {
256
        int end = editor.getSelectionEnd();
257
        editor.setSelectionStart(end);
258
        editor.setSelectionEnd(end);
259
        this.window.setVisible(false);
260
    }
261

    
262
    private void doUpdateClassesList() {
263
        Set<ScriptingHelpClass>addeds = new HashSet<ScriptingHelpClass>();
264

    
265
        String filter = this.txtClassFilter.getText();
266
        DefaultListModel modelClasses = new DefaultListModel();
267
        for (ScriptingHelpClass helpClass : recentClasses) {
268
            if( addeds.contains(helpClass) ) {
269
                continue;
270
            }
271
            if( StringUtils.isEmpty(filter) ) {
272
                modelClasses.addElement(helpClass);
273
                addeds.add(helpClass);
274
            } else {
275
                if( filter.contains("*") ) {
276
                    if( helpClass.getName().matches(filter.replace("[*]", ".*")) ) {
277
                        modelClasses.addElement(helpClass);
278
                    }
279
                } else {
280
                    // if( StringUtils.getJaroWinklerDistance(helpClass.getName(), filter) > 0.70 ) {
281
                    if( StringUtils.containsIgnoreCase(helpClass.getName(), filter) ) {
282
                        modelClasses.addElement(helpClass);
283
                        addeds.add(helpClass);
284
                    }                
285
                }
286
            }
287
        }
288
        for (ScriptingHelpClass helpClass : helpClasses) {
289
            if( addeds.contains(helpClass) ) {
290
                continue;
291
            }
292
            if( StringUtils.isEmpty(filter) ) {
293
                modelClasses.addElement(helpClass);
294
                addeds.add(helpClass);
295
            } else {
296
                if( filter.contains("*") ) {
297
                    if( helpClass.getName().toLowerCase().matches(filter.toLowerCase().replace("*", ".*")) ) {
298
                        modelClasses.addElement(helpClass);
299
                    }
300
                } else {
301
                    // if( StringUtils.getJaroWinklerDistance(helpClass.getName(), filter) > 0.70 ) {
302
                    if( StringUtils.containsIgnoreCase(helpClass.getName(), filter) ) {
303
                        modelClasses.addElement(helpClass);
304
                        addeds.add(helpClass);
305
                    }                
306
                }
307
            }
308
        }
309
        this.lstClasses.setModel(modelClasses);
310
        if( !modelClasses.isEmpty() ) {
311
            this.lstClasses.setSelectedIndex(0);            
312
        }
313
    }
314

    
315
    private void doUpdateMethodsList() {
316
        ScriptingHelpClass helpClass = (ScriptingHelpClass) (this.lstClasses.getSelectedValue());
317
        if (helpClass != null) {
318
            String filter = this.txtMethodFilter.getText();
319
            DefaultListModel methodsModel = new DefaultListModel();
320
            for (String methodname : helpClass.getMethods()) {
321
                if( StringUtils.isEmpty(filter) ) {                   
322
                    methodsModel.addElement(methodname);
323
                } else {
324
                    if( filter.contains("*") ) {
325
                        if( methodname.toLowerCase().matches(filter.toLowerCase().replace("*", ".*")) ) {
326
                            methodsModel.addElement(methodname);
327
                        }
328
                    } else {
329
                        if( methodname.toLowerCase().startsWith(filter.toLowerCase())) {
330
                            methodsModel.addElement(methodname);
331
                        }
332
                    }
333
                }
334
            }
335
            this.lstMethods.setModel(methodsModel); 
336
            if( !methodsModel.isEmpty() ) {
337
                this.lstMethods.setSelectedIndex(0);            
338
            }
339
        }
340
    }
341

    
342
    private void doSelectMethod() {
343
        String methodname = (String) (this.lstMethods.getSelectedValue());
344
        if (methodname != null) {
345
            ScriptingHelpClass helpClass = (ScriptingHelpClass) (this.lstClasses.getSelectedValue());
346
            if (helpClass != null) {
347
                addToRecentClasses(helpClass);
348
            }
349
            editor.replaceSelection(methodname);
350
            doClose();
351
        }
352
    }
353

    
354
    public void showSuggestion() {
355
        Point p = editor.getCaret().getMagicCaretPosition();
356
        if( p==null ) {
357
            // A veces getMagicCaretPosition retorna null
358
            // Lo reintentamos cuando se pueda otra vez hasta 5 veces.
359
            //logger.info("Retry showSuggestion(), retriy "+this.show_retries);
360
            if( this.show_retries >5 ) {
361
                return;
362
            }
363
            SwingUtilities.invokeLater(new Runnable() {
364

    
365
                @Override
366
                public void run() {
367
                    show_retries++;
368
                    showSuggestion();
369
                }
370
            });
371
            return;
372
        }
373
        SwingUtilities.convertPointToScreen(p, editor);
374
        p.x = p.x + 2;
375
        p.y = p.y + 20;
376

    
377
        this.window = new JFrame("Suggestions Window");
378

    
379
        window.addWindowFocusListener(new WindowFocusListener() {
380
            public void windowGainedFocus(WindowEvent e) {
381

    
382
            }
383

    
384
            public void windowLostFocus(WindowEvent e) {
385
                doClose();
386
            }
387
        });
388
        window.setUndecorated(true);
389
        window.setLayout(new BorderLayout());
390
        window.setSize(new Dimension(300, 200));
391
        window.add(this, BorderLayout.CENTER);
392
        window.pack();
393
        window.setLocation(p.x,p.y);
394
        window.setVisible(true);
395
    }
396
}