Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libUI / src / org / gvsig / gui / beans / SearcheableComboBox / JComboBoxSearcheableDynamic.java @ 6459

History | View | Annotate | Download (31.8 KB)

1
package org.gvsig.gui.beans.SearcheableComboBox;
2

    
3
import java.awt.Color;
4
import java.awt.Event;
5
import java.awt.event.KeyEvent;
6
import java.awt.event.KeyListener;
7
import java.util.Arrays;
8
import java.util.HashSet;
9
import java.util.Iterator;
10
import java.util.Set;
11
import java.util.Vector;
12

    
13
import javax.swing.ComboBoxEditor;
14
import javax.swing.ComboBoxModel;
15
import javax.swing.DefaultComboBoxModel;
16
import javax.swing.JComboBox;
17
import javax.swing.JOptionPane;
18
import javax.swing.JTextField;
19

    
20
import com.iver.andami.PluginServices;
21

    
22
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
23
 *
24
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
25
 *
26
 * This program is free software; you can redistribute it and/or
27
 * modify it under the terms of the GNU General Public License
28
 * as published by the Free Software Foundation; either version 2
29
 * of the License, or (at your option) any later version.
30
 *
31
 * This program is distributed in the hope that it will be useful,
32
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34
 * GNU General Public License for more details.
35
 *
36
 * You should have received a copy of the GNU General Public License
37
 * along with this program; if not, write to the Free Software
38
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
39
 *
40
 * For more information, contact:
41
 *
42
 *  Generalitat Valenciana
43
 *   Conselleria d'Infraestructures i Transport
44
 *   Av. Blasco Ib??ez, 50
45
 *   46010 VALENCIA
46
 *   SPAIN
47
 *
48
 *      +34 963862235
49
 *   gvsig@gva.es
50
 *      www.gvsig.gva.es
51
 *
52
 *    or
53
 *
54
 *   IVER T.I. S.A
55
 *   Salamanca 50
56
 *   46005 Valencia
57
 *   Spain
58
 *
59
 *   +34 963163400
60
 *   dac@iver.es
61
 */
62

    
63
/**
64
* This class allows users to insert a chain of characters and show all the sentences of the JComboBox that match its first ones characters with it.
65
* This class is also a Java Bean.
66
* The behavior of this componet can be configurated by 6 flags:
67
*  + The appearence of the items showed at the beginning and when the user presses the ESCAPE key: (This is configured with 2 flags -> 3 different states are possible) 
68
*             -> maintainPositionItems -> When we see the list of all items, this are showed in the ordenation as they have been introduced (if true); (if false) each new item 
69
*           when we write on the TextField of this Component will be showed at the end
70
*      -> all_Alphanumeric_Sorted -> All items we can see in this Component will be showed in alphanumeric ordenation (if true)
71
*  + The list of the items showed when the user makes a search writting or pressing the BACK-SPACE key (This is configured with 1 flag -> 2 different states are possible)
72
*      -> alphanumericSortedSearches -> When we write on the TextField of this Component all results (items) are showed in alphanumeric ordenation (if true)
73
*  + Show all items always
74
*      -> showAllItems -> If true -> this component shows all items always; if false -> this component only shows items that their first characters match with the string written by the user
75
*  + Key Sensitive or not when the user writes 
76
*      -> key_Sensitive -> When we write on the TextField it can discriminate upper cases from down cases (if true) or not (if false) (This is configured with 1 flag -> 2 different states are possible)
77
*  + Use one color (black) or 2 colors (black by default and red if the string written doesn't match with the beginning of all items)
78
*      -> only_One_Color -> The text on the textField only will be showed on black color (if true); false -> if the text on the textField doesn't match with any current item of this component -> the text
79
*            will be showed on red color
80
* 
81
* Combinations of flags not allowed:
82
*         ->        maintainPositionItems == allAlphanumericSorted == true
83
*        ->        ((maintain_Position_Items == false) && (all_Alphanumeric_Sorted == true) && (alphanumeric_Sorted_Searches == false))
84
*   ->  showAllItems == true && maintainPositionItems == false
85
* 
86
* Limitations:
87
* -> When we add more than one item with the same name (string value) -> the behavior of this component only considers one item in most of the cases when it does a search
88
* -> If this component has Hundreds,Thousands or even Million/s of items is probably that had quite delay to respond the evens of the user; this also depends of the machine where it's executed
89
* 
90
* @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
91
*/
92
public class JComboBoxSearcheableDynamic  extends JComboBox implements KeyListener, java.io.Serializable {
93
        private static final long serialVersionUID = -1853812970336818959L;
94
        private Vector defaultItems;
95
        private Set notRemovedItems;
96
        private Set removedItems;
97
        private boolean maintainPositionItems;        
98
        private boolean alphanumericSortedSearches;
99
        private boolean allAlphanumericSorted;
100
        private boolean keySensitive;
101
        private boolean onlyOneColor;
102
        private boolean showAllItems;
103
        private boolean allItemsAreSorted;
104
        private int lastSelectedItem;
105
        private JTextField txtField;
106
        
107
        /**
108
         * Default Constructor
109
         */
110
        public JComboBoxSearcheableDynamic() {
111
                // Invokes to the parent class constructor                
112
                super();
113
        
114
                // Set the default values of the flags
115
                maintainPositionItems = true;                
116
                alphanumericSortedSearches = true;
117
                allAlphanumericSorted = false;
118
                keySensitive = false;
119
                onlyOneColor = false;
120
                showAllItems = false;
121
                
122
                // Initializates the current Component variables
123
                this.initializateThisComponent();
124
        }
125
        
126
        /**
127
         * Default Constructor with four parameters: configure the 4 flags
128
         * 
129
         * @param boolean (true -> maintains the position of the items; false -> don't maintains the position of the items)
130
         * @param boolean (true -> all items showed when we write on the textfield will be showed in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
131
         * @param boolean (true -> all items showed will be in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
132
         * @param boolean (true -> discriminates capital letters from small letters; false -> don't discriminates capital letters from small letters)
133
         */
134
        public JComboBoxSearcheableDynamic(boolean maintain_Position_Items, boolean alphanumeric_Sorted_Searches, boolean all_Alphanumeric_Sorted, boolean key_Sensitive)        {
135
                // Invokes to the parent class constructor                
136
                super();        
137

    
138
                // Sets the options selected by the user
139
                maintainPositionItems = maintain_Position_Items;                
140
                allAlphanumericSorted = all_Alphanumeric_Sorted;
141
                alphanumericSortedSearches = alphanumeric_Sorted_Searches | allAlphanumericSorted; // If allAlphanumericSorted = true -> alphanumericSortedSearches = true
142
                keySensitive = key_Sensitive;
143
                onlyOneColor = false;
144
                showAllItems = false;
145
                
146
                if (!testFlagsConfigurationOK())
147
                        JOptionPane.showMessageDialog(this, PluginServices.getText(this, "error_message_JComboBoxSearcheableDynamic"), PluginServices.getText(this, "exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
148
                else
149
                        this.initializateThisComponent(); // Initializates the current Component variables
150
        }
151

    
152
        /**
153
         * Default Constructor with four parameters: configure the 6 flags
154
         * 
155
         * @param boolean (true -> maintains the position of the items; false -> don't maintains the position of the items)
156
         * @param boolean (true -> all items showed when we write on the textfield will be showed in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
157
         * @param boolean (true -> all items showed will be in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
158
         * @param boolean (true -> discriminates capital letters from small letters; false -> don't discriminates capital letters from small letters)
159
         * @param boolean (true -> the text on the textField only will be showed on black color (if true); false -> if the text on the textField doesn't match with any current item of this component -> the text
160
         *                           will be showed on red color)
161
           * @param boolean (true -> this component shows all items always; false -> this component only shows items that their first characters match with the string written by the user)
162
         */
163
        public JComboBoxSearcheableDynamic(boolean maintain_Position_Items, boolean alphanumeric_Sorted_Searches, boolean all_Alphanumeric_Sorted, boolean key_Sensitive, boolean only_One_Color, boolean show_All_Items) {
164
                // Invokes to the parent class constructor                
165
                super();        
166

    
167
                // Sets the options selected by the user
168
                maintainPositionItems = maintain_Position_Items;                
169
                allAlphanumericSorted = all_Alphanumeric_Sorted;
170
                alphanumericSortedSearches = alphanumeric_Sorted_Searches | allAlphanumericSorted; // If allAlphanumericSorted = true -> alphanumericSortedSearches = true
171
                keySensitive = key_Sensitive;
172
                onlyOneColor = only_One_Color;
173
                showAllItems = show_All_Items;
174
                
175
                if (!testFlagsConfigurationOK())
176
                        JOptionPane.showMessageDialog(this, PluginServices.getText(this, "error_message_JComboBoxSearcheableDynamic"), PluginServices.getText(this, "exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
177
                else
178
                        this.initializateThisComponent(); // Initializates the current Component variables
179
        }
180
        
181
        /**
182
         * Starts all the variables needed for this Component
183
         */
184
        private void initializateThisComponent() {
185
                try
186
                {
187
                        // Allows user to edit on the combobox
188
                        setEditable(true);
189
                        
190
                        // Gets the editor of the combobox_fwAndami
191
                        ComboBoxEditor editor = this.getEditor();
192
                        
193
                        // Gets JTextField of the editor of the combobox
194
                        JTextField textField = (JTextField) editor.getEditorComponent();
195
                        
196
                        // Adds a KeyListener to the JTextField of the editor of the combobox
197
                        textField.addKeyListener(this);
198
                        
199
                        // Disable the focus transversal keys (Example: CTRL+TAB) for enable the TAB key
200
                        textField.setFocusTraversalKeysEnabled(false);
201

    
202
                        // Initialize the Vector with the items
203
                        defaultItems = new Vector();                        
204
                        
205
                        // If we don't have to show all items each time
206
                        if (!showAllItems)
207
                        {
208
                                // Initialize the Set for store the items removed from the JComboBox
209
                                removedItems = new HashSet();
210
                        
211
                                // Initialize the Set for store the items won't be removed from the JComboBox
212
                                if (alphanumericSortedSearches)
213
                                        notRemovedItems = new HashSet();
214
                        }
215
                        
216
                        // By default all items showed aren't sorted
217
                        allItemsAreSorted = false;
218
                        
219
                        // Set the last selected item
220
                        lastSelectedItem = 0;
221
                }
222
                catch(Exception e)
223
                {
224
                        e.printStackTrace();
225
                }
226
        }
227
        
228
        /**
229
         * This method tests the configuration of the flags and returns true or false if its ok or not with the
230
         *   logical behavior of this component
231
         * 
232
         * @return boolean True if the configuration of the flags is oks, false if not
233
         */
234
        public boolean testFlagsConfigurationOK() {
235
                if ((maintainPositionItems == allAlphanumericSorted) && (maintainPositionItems == true))
236
                        return false;
237
                
238
                if ((maintainPositionItems == false) && (allAlphanumericSorted == true) && (alphanumericSortedSearches == false))
239
                        return false;
240
                
241
                if ((showAllItems == true) && (maintainPositionItems == false))
242
                        return false;
243
                
244
                return true;
245
        }
246

    
247

    
248
        /**
249
         * Redefines the method addItem of the JComboBox
250
         * 
251
         * @param Object the item to add
252
         */
253
        public void addItem(Object anObject) {
254
                // Add the item to this component
255
                super.addItem(anObject);
256
                
257
                // In defaultItems it's saved a copy ordered of the items
258
                defaultItems.add(anObject);
259
                
260
                // If we don't have to show all items each time
261
                if (!showAllItems)
262
                {
263
                        // Store a copy of each item that is in this component
264
                        if (alphanumericSortedSearches)
265
                                notRemovedItems.add(anObject);
266
                }
267
                else
268
                {
269
                        if ((allAlphanumericSorted) && (!allItemsAreSorted))
270
                        {
271
                                this.setModel(this.sortItemsShowed());                
272
                                allItemsAreSorted = true;
273
                        }
274
                }
275
        }
276
        
277
        /**
278
         * This private method makes a copy of items sorted and returns the copy
279
         * 
280
         * @return ComboBoxModel The ComboBoxModel with the copy of the items
281
         */
282
        private ComboBoxModel getCopyOfItems() {
283
                                
284
                DefaultComboBoxModel dCBModel = new DefaultComboBoxModel();
285
                int i;
286

    
287
                Object sorted[] = notRemovedItems.toArray();                                 
288
                Arrays.sort(sorted);
289
                        
290
                // For each item -> makes a copy if hasn't removed
291
                for (i=0; i < sorted.length; i++)
292
                        dCBModel.addElement(sorted[i]);
293
                        
294
                return dCBModel;
295
        }
296
        
297
        /**
298
         * This private method makes a copy of items according to the configuration, this method is invoked when the uses releases the key ESC(APE)
299
         * 
300
         * @return ComboBoxModel The ComboBoxModel with the copy of the items
301
         */
302
        private ComboBoxModel getCopyOfModel() {
303
                
304
                if (maintainPositionItems) // Copies the default items in the same ordenation
305
                {
306
                        DefaultComboBoxModel dCBModel = new DefaultComboBoxModel();
307
                        int i;
308
                        
309
                        // For each item -> makes a copy
310
                        for (i=0; i < defaultItems.size(); i++)
311
                                dCBModel.addElement(defaultItems.get(i));
312
                        
313
                        return dCBModel;
314
                }
315
                else
316
                {
317
                        // Get a copy of the items sorted
318
                        if ((allAlphanumericSorted) || (alphanumericSortedSearches))
319
                        {                        
320
                                DefaultComboBoxModel dCBModel = new DefaultComboBoxModel();
321
                                int i;
322
                                
323
                                Object sorted[] = defaultItems.toArray();
324
                                Arrays.sort(sorted);
325
                                
326
                                // For each item -> makes a copy
327
                                for (i=0; i < sorted.length; i++)
328
                                        dCBModel.addElement(sorted[i]);
329
                                
330
                                return dCBModel;
331
                        }
332
                        else
333
                        {
334
                                // This option isn't used
335
                                return new DefaultComboBoxModel();
336
                        }
337
                }                
338
        }
339

    
340
        /**
341
         * This private method makes a copy of items according to the configuration, this method is invoked when the uses releases the key BACK_SPACE or any key of alphanumeric or simbol character 
342
         * 
343
         * @return ComboBoxModel The ComboBoxModel with the copy of the items
344
         */
345
        private ComboBoxModel getCopyOfModelSearched() {
346
                
347
                if (alphanumericSortedSearches) // Copies the items sorted
348
                        return getCopyOfItems();
349
                else
350
                        return this.getModel();
351
        }
352

    
353
        /**
354
         * This private method sorts the items of the vector of the model of this component
355
         * 
356
         * @return ComboBoxModel The ComboBoxModel with the items sorted by alphanumeric order
357
         */
358
        private ComboBoxModel sortItemsShowed()        {
359
                DefaultComboBoxModel dCBModel = new DefaultComboBoxModel();
360
                int i;
361
        
362
                Object sorted[] = defaultItems.toArray();                                 
363
                Arrays.sort(sorted);
364
                        
365
                // For each item -> makes a copy if hasn't removed
366
                for (i=0; i < sorted.length; i++)
367
                        dCBModel.addElement(sorted[i]);
368
                        
369
                return dCBModel;
370
        }
371
        
372
        /**
373
         * This private method finds the first item of the vector of the model of this component that it start matches with a chain of characters
374
         * 
375
         * @param String text
376
         * @return int The position of the first coincidence or -1 if hasn't find any coincidence
377
         */
378
        private int findFirstCoincidence(String text) {
379
                int first_position = 0;
380
                boolean matchesTheStart = false;
381
                
382
                // If there is key sensitive
383
                if (keySensitive)
384
                {
385
                        // Find the first match
386
                        while ((first_position < this.getItemCount()) && (matchesTheStart == false))
387
                        {                                        
388
                                if (((String)this.getItemAt(first_position)).startsWith(text))
389
                                        matchesTheStart = true;                                                        
390
                                else                                                
391
                                        first_position++; // Increments index
392
                        }                                        
393
                }
394
                else
395
                {
396
                        // If there isn't key sensitive
397
                        
398
                        // Find the first match
399
                        while ((first_position < this.getItemCount()) && (matchesTheStart == false))
400
                        {                                        
401
                                if (((this.getItemAt(first_position)).toString().toUpperCase()).startsWith(text.toUpperCase()))
402
                                        matchesTheStart = true;
403
                                else
404
                                        first_position++; // Increments index
405
                        }
406
                }
407
                
408
                // Return the position value
409
                if (!matchesTheStart)
410
                        return -1;
411
                else
412
                        return first_position;
413
        }
414
        
415
        /**
416
         * Gets the flag of the configuration of the policy for maintain the position of the items of this component 
417
         * (true -> maintains the position of the items, false -> don't maintains the position of the items)
418
         * 
419
         * @return boolean The value of the flag
420
         */
421
        public boolean isMaintainPositionItems() {
422
                return maintainPositionItems;
423
        }
424
        
425
        /**
426
         * Sets the flag of the configuration of the policy for maintain the position of the items of this component 
427
         * (true -> maintains the position of the items, false -> don't maintains the position of the items)
428
         * 
429
         * @param boolean The value of the flag
430
         */
431
        public void setMaintainPositionItems(boolean maintain_Position_Items) {
432
                this.maintainPositionItems = maintain_Position_Items;
433

    
434
                if (!this.testFlagsConfigurationOK())
435
                        JOptionPane.showMessageDialog(this, PluginServices.getText(this, "error_message_JComboBoxSearcheableDynamic"), PluginServices.getText(this, "exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
436
        }
437
        
438
        /**
439
         * Gets the flag of the configuration of the alphanumericSortedSearches flag of this component 
440
         * (true -> all items showed when we write on the textfield will be showed in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
441
         * 
442
         * @return boolean The value of the flag
443
         */
444
        public boolean isAlphanumericSortedSearches() {
445
                return alphanumericSortedSearches;
446
        }
447
        
448
        /**
449
         * Sets the flag of the configuration of the alphanumericSortedSearches flag of this component 
450
         * (true -> all items showed when we write on the textfield will be showed in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
451
         * 
452
         * @param boolean The value of the flag
453
         */
454
        public void setAlphanumericSortedSearches(boolean alphanumeric_Sorted_Searches) {
455
                this.alphanumericSortedSearches = alphanumeric_Sorted_Searches;
456
                
457
                if (!testFlagsConfigurationOK())
458
                        JOptionPane.showMessageDialog(this, PluginServices.getText(this, "error_message_JComboBoxSearcheableDynamic"), PluginServices.getText(this, "exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
459

    
460
                if (alphanumericSortedSearches)
461
                {
462
                        notRemovedItems = new HashSet();
463
                        
464
                        for (int i=0; i < this.getItemCount(); i++)
465
                                notRemovedItems.add(this.getItemAt(i));
466
                }
467
                else
468
                        notRemovedItems.clear();
469

    
470
        }
471
        
472
        /**
473
         * Gets the flag of the configuration of the allAlphanumericSorted flag of this component 
474
         * (true -> all items showed will be in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
475
         * 
476
         * @return boolean The value of the flag
477
         */
478
        public boolean isAllAlphanumericSorted() {
479
                return allAlphanumericSorted;
480
        }
481
        
482
        /**
483
         * Sets the flag of the configuration of the allAlphanumericSorted flag of this component 
484
         * (true -> all items showed will be in alphanumeric ordenation; false -> they don't have to be in alphanumeric ordenation)
485
         * 
486
         * @param boolean The value of the flag
487
         */
488
        public void setAllAlphanumericSorted(boolean all_Alphanumeric_Sorted) {
489
                this.allAlphanumericSorted = all_Alphanumeric_Sorted;
490
                
491
                // If all_Alphanumeric_Sorted = true -> alphanumeric_Sorted_Searches = true
492
                setAlphanumericSortedSearches(this.alphanumericSortedSearches | this.allAlphanumericSorted);
493
                
494
                if (allAlphanumericSorted)
495
                
496
                if (!testFlagsConfigurationOK())
497
                        JOptionPane.showMessageDialog(this, PluginServices.getText(this, "error_message_JComboBoxSearcheableDynamic"), PluginServices.getText(this, "exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
498
        }
499
        
500
        /**
501
         * Gets the flag of the configuration of the keySensitive flag of this component 
502
         * (true -> discriminates capital letters from small letters ,false -> don't discriminates capital letters from small letters)
503
         * 
504
         * @return boolean The value of the flag
505
         */
506
        public boolean isKeySensitive() {
507
                return keySensitive;
508
        }
509
        
510
        /**
511
         * Sets the flag of the configuration of the keySensitive flag of this component 
512
         * (true -> discriminates capital letters from small letters ,false -> don't discriminates capital letters from small letters)
513
         * 
514
         * @param boolean The value of the flag
515
         */
516
        public void setKeySensitive(boolean key_Sensitive) {
517
                this.keySensitive = key_Sensitive;
518

    
519
                if (!testFlagsConfigurationOK())
520
                        JOptionPane.showMessageDialog(this, PluginServices.getText(this, "error_message_JComboBoxSearcheableDynamic"), PluginServices.getText(this, "exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
521
        }
522

    
523
        /**
524
         * Gets the flag of the configuration of the onlyOneColor flag of this component
525
         * (true -> The text on the textField only will be showed on black color; false -> if the text on the textField doesn't match with any current item of this 
526
         *            component -> the text will be showed on red color)
527
         * 
528
         * @return boolean The value of the flag
529
         */
530
        public boolean isOnlyOneColor() {
531
                return onlyOneColor;
532
        }
533

    
534
        
535
        /**
536
         * Sets the flag of the configuration of the onlyOneColor flag of this component 
537
         * (true -> discriminates capital letters from small letters ,false -> don't discriminates capital letters from small letters)
538
         * 
539
         * @param boolean The value of the flag
540
         */
541
        public void setOnlyOneColor(boolean only_One_Color) {
542
                this.onlyOneColor = only_One_Color;
543
                
544
                if (!testFlagsConfigurationOK())
545
                        JOptionPane.showMessageDialog(this, PluginServices.getText(this, "error_message_JComboBoxSearcheableDynamic"), PluginServices.getText(this, "exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
546
        }
547
        
548
        /**
549
         * Gets the flag of the configuration of the showAllItems flag of this component
550
         * (true -> this component shows all items always; false -> this component only shows items that their first characters match with the string written by the user) 
551
         * 
552
         * @return boolean The value of the flag
553
         */
554
        public boolean isShowAllItems() {
555
                return showAllItems;
556
        }
557

    
558
        /**
559
         * Sets the flag of the configuration of the showAllItems flag of this component
560
         * (true -> this component shows all items always; false -> this component only shows items that their first characters match with the string written by the user)
561
         * 
562
         * @return boolean The value of the flag
563
         */
564
        public void setShowAllItems(boolean show_All_Items) {
565
                this.showAllItems = show_All_Items;
566
                
567
                if (this.showAllItems == false)
568
                        this.setModel(getCopyOfModel());
569
        }
570
        
571
        
572
        //// IMPLEMENTATION OF THE METHODS OF THE KEYLISTENER ////
573
        
574
        /*
575
         * (non-Javadoc)
576
         * 
577
         * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
578
         */
579
        public void keyTyped(KeyEvent ke) {
580
        }
581
        
582
        /*
583
         * (non-Javadoc)
584
         * 
585
         * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
586
         */
587
        public void keyPressed(KeyEvent ke) {
588
        }
589
        
590
        /*
591
         * (non-Javadoc)
592
         * 
593
         * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
594
         */
595
        public void keyReleased(KeyEvent ke) {
596
                
597
                // Get the JTextField of the Editor of the JComboBox (where the user has written)
598
                // JTextField txtField = (JTextField) ke.getSource();
599
                txtField = (JTextField) ke.getSource();                
600

    
601
                if (ke.getKeyCode() == KeyEvent.VK_DOWN) {
602
                    // If the key (typed, pressed and) released has been the Down Key -> when there isn't any text (item of the list) selected, select the first 
603
                        ComboBoxModel model = this.getModel();
604
                        if ((this.getItemCount() > 0) && (lastSelectedItem == (this.getItemCount()-1))) {
605
                                this.setSelectedIndex(0);
606
                        }
607
                        
608
                        lastSelectedItem = this.getSelectedIndex();
609
                        this.showPopup();
610
                } else if (ke.getKeyCode() == KeyEvent.VK_UP) {
611
                    // If the key (typed, pressed and) released has been the Up Key -> when there isn't any text (item of the list) selected, select the last 
612
                        ComboBoxModel model = this.getModel();
613
                        
614
                        if (lastSelectedItem == 0) {
615
                                this.setSelectedIndex(this.getItemCount()-1);                                
616
                        }
617
                        
618
                        lastSelectedItem = this.getSelectedIndex();
619
                        this.showPopup();
620
                } else if (ke.getKeyChar() == KeyEvent.VK_ESCAPE) {
621
                        // If the key (typed, pressed and) released has been the Escape Key -> hide the popup list and empty the JTextField                        
622
                        this.hidePopup();
623
                        
624
                        if ((!maintainPositionItems) && (!allAlphanumericSorted))
625
                        {
626
                                if (removedItems.size() > 0)
627
                                {
628
                                        Iterator it = removedItems.iterator();
629
                                        
630
                                        while(it.hasNext())
631
                                                super.addItem(it.next());
632
                                        
633
                                        removedItems.clear();
634
                                }
635
                        }
636
                        else
637
                                this.setModel(getCopyOfModel());
638

    
639
                        txtField.setText("");
640
                        this.setSelectedIndex(-1);
641
                } else if (ke.getKeyChar() == KeyEvent.VK_ENTER) {
642
                        // If the key (typed, pressed and) released has been the Enter Key -> hide the popup list and select the characters introduced
643
                        
644
                        ComboBoxModel model = this.getModel();
645
                        
646
                        if (getSelectedItem() != null) {
647
                                txtField.setText(getSelectedItem().toString());
648
                                
649
                                // Find if the string matches with any item -> if not -> change the foreground color to RED
650
                                if (!onlyOneColor)
651
                                {
652
                                        for (int i=0; i < this.getItemCount(); i++)
653
                                        {
654
                                                if (((String)this.getModel().getElementAt(i)).compareTo(txtField.getText()) == 0)
655
                                                {
656
                                                        txtField.setForeground(Color.BLACK);
657
                                                        return;
658
                                                }
659
                                        }
660
                                        txtField.setForeground(Color.RED);
661
                                }
662
                                
663
                                model.setSelectedItem(getSelectedItem());                                
664
                        }
665
                } else if (ke.getKeyChar() == Event.BACK_SPACE) {
666
                        // If the key (typed, pressed and) released has been the TAB Key -> try to complete the current selected item from the list and hide the popup list
667

    
668
                        int i = 0;
669
                        String s;
670
                        String text = txtField.getText();
671
                        boolean matchesTheStart = false;                        
672
                        
673
                        // If it has to maintain the position of the items
674
                        if (showAllItems)
675
                        {
676
                                int first_match = this.findFirstCoincidence(text);
677
                                
678
                                // If has find a coincidence -> marks the item, else -> reset the index
679
                                this.setSelectedIndex(first_match);
680

    
681
                                txtField.setText(text);
682
                                txtField.setForeground(Color.BLACK);
683
                                this.showPopup();
684

    
685
                        }
686
                        else
687
                        {
688
                                Object objs[] = removedItems.toArray();
689
                                
690
                                if (alphanumericSortedSearches)
691
                                {
692
                                        if (keySensitive)
693
                                        {
694
                                                // If there is key sensitive
695
                                                while (i < objs.length)
696
                                                {                                        
697
                                                        s = objs[i].toString();
698
                                                        if (s.startsWith(text))
699
                                                        {
700
                                                                removedItems.remove(objs[i]);
701
                                                                notRemovedItems.add(objs[i]);
702
                                                                matchesTheStart = true;
703
                                                        }
704
                                                        
705
                                                        // Increments index
706
                                                        i++;
707
                                                }
708
                                        }
709
                                        else
710
                                        {                                        
711
                                                // If there isn't key sensitive
712
                                                while (i < objs.length)
713
                                                {                                        
714
                                                        s = (objs[i].toString().toUpperCase());
715
                                                        if (s.startsWith(text.toUpperCase()))
716
                                                        {
717
                                                                removedItems.remove(objs[i]);
718
                                                                notRemovedItems.add(objs[i]);
719
                                                                matchesTheStart = true;
720
                                                        }
721
                                                        
722
                                                        // Increments index
723
                                                        i++;
724
                                                }
725
                                        }
726
                                        
727
                                        this.setModel(getCopyOfModelSearched());
728
                                        
729
                                        if (notRemovedItems.contains(text))
730
                                                txtField.setForeground(Color.BLACK);
731
                                }
732
                                else
733
                                {
734
                                        this.hidePopup();
735
                                        
736
                                        // If it hasn't to maintain the position of the items
737
                                        if (keySensitive)
738
                                        {
739
                                                // If there is key sensitive
740
                                                while (i < objs.length)
741
                                                {
742
                                                        s = objs[i].toString();
743
                                                        if (s.startsWith(text))
744
                                                        {
745
                                                                removedItems.remove(objs[i]);
746
                                                                super.addItem(objs[i]);
747
                                                                matchesTheStart = true;
748
                                                        }
749
                                
750
                                                        // Increments index
751
                                                        i++;
752
                                                }
753
                                        }
754
                                        else
755
                                        {
756
                                                // If there isn't key sensitive
757
                                                while (i < objs.length)
758
                                                {
759
                                                        s = ((String)objs[i].toString().toUpperCase());                                                
760
                                                                                                        
761
                                                        if (s.startsWith(text.toUpperCase()))
762
                                                        {
763
                                                                removedItems.remove(objs[i]);
764
                                                                super.addItem(objs[i]);
765
                                                                matchesTheStart = true;
766
                                                        }
767
                                
768
                                                        // Increments index
769
                                                        i++;
770
                                                }
771
                                        }
772
                                }
773
                        }                        
774
                        
775
                        txtField.setText(text);                        
776

    
777
                        if (matchesTheStart)
778
                                txtField.setForeground(Color.BLACK);
779
                                
780
                        this.showPopup();
781
                } else if (ke.getKeyCode() == KeyEvent.VK_TAB) {
782
                        // If the key (typed, pressed and) released has been the TAB Key -> try to complete the current selected item from the list and hide the popup list
783
                        ComboBoxModel model = this.getModel();
784
                        if (model.getSelectedItem() == null)
785
                        {
786
                                // If there isn't any item selected and there are items, select and show the first item
787
                                if (model.getSize() > 0)
788
                                {
789
                                        this.setSelectedIndex(0);
790
                                        txtField.setText(model.getSelectedItem().toString());
791
                                }
792
                                else
793
                                        txtField.setText(""); // If there isn't any item selected and there aren't items, show anything
794
                        }
795
                        else
796
                                txtField.setText(model.getSelectedItem().toString());
797
                        this.hidePopup();                        
798
                } else if (ke.getKeyCode() == KeyEvent.VK_LEFT) {
799
                        // Do nothing
800
                } else if (ke.getKeyCode() == KeyEvent.VK_RIGHT) {
801
                        // Do nothing
802
            } else if (txtField.getText().trim().equalsIgnoreCase("")) {
803
                        // If the current string in the JTextField of the Editor is an empty string -> hide the popup list and the reset the index
804
                        this.setSelectedIndex(-1);
805
                        this.hidePopup();
806
                } else {
807
                        // When the user writtes a new character -> find a item of the list that matches it start with the characters written
808
                        // If matches the text -> change the color of the text to black, else -> change the color of the text to red and doesn't select any item from the list
809

    
810
                        ComboBoxModel model = this.getModel();
811
                        String text = txtField.getText();
812
                                        
813
                        // Try to match the characters written with the start of any string value of item of the list
814
                        int i = 0;
815
                        String s;
816
                        boolean matchesTheStart = false;
817
                        
818
                        // If it has to maintain the position of the items
819
                        if (showAllItems)
820
                        {                                
821
                                txtField.setText(text);                        
822

    
823
                                int first_match = this.findFirstCoincidence(text);
824
                                
825
                                // If has find a coincidence -> marks the item, else -> reset the index
826
                                this.setSelectedIndex(first_match);
827
                                
828
                                // Sets the written text to the text field
829
                                txtField.setText(text);
830
                        
831
                                // If has matched the text written with any item -> set the text on black color
832
                                // else -> set the text on red color
833
                                if (!onlyOneColor)
834
                                {
835
                                        if (first_match > -1)
836
                                                txtField.setForeground(Color.BLACK);
837
                                        else
838
                                                txtField.setForeground(Color.RED);
839
                                }
840
                                
841
                                this.showPopup();
842
                                return;
843
                        }
844
                        else
845
                        {
846
                                if (alphanumericSortedSearches)
847
                                {
848
                                        if (keySensitive)
849
                                        {
850
                                                while (i < model.getSize())
851
                                                {
852
                                                        s = model.getElementAt(i).toString();
853
                                                        
854
                                                        // If matches the start
855
                                                        if (s.startsWith(text)) {
856
                                                                matchesTheStart = true;
857
                                                                                
858
                                                                // Increments index
859
                                                                i++;
860
                                                        }
861
                                                        else
862
                                                        {
863
                                                                // When the characters written doesn't match -> set this characters to red color   
864
                                                                removedItems.add(model.getElementAt(i));
865
                                                                notRemovedItems.remove(model.getElementAt(i));
866
                                                                this.removeItemAt(i);
867
                                                        }                                
868
                                                }
869
                                        }
870
                                        else
871
                                        {
872
                                                while (i < model.getSize())
873
                                                {
874
                                                        s = (model.getElementAt(i).toString().toUpperCase());
875
                                                                                                        
876
                                                        // If matches the start
877
                                                        if (s.startsWith(text.toUpperCase())) {
878
                                                                matchesTheStart = true;
879
                                                                                
880
                                                                // Increments index
881
                                                                i++;
882
                                                        }
883
                                                        else
884
                                                        {
885
                                                                // When the characters written doesn't match -> set this characters to red color   
886
                                                                removedItems.add(model.getElementAt(i));
887
                                                                notRemovedItems.remove(model.getElementAt(i));
888
                                                                this.removeItemAt(i);
889
                                                        }                                
890
                                                }
891
                                        }
892
                                        
893
                                        this.setModel(getCopyOfModelSearched());
894
                                }
895
                                else
896
                                {
897
                                        this.hidePopup();
898
                                        
899
                                        if (keySensitive)
900
                                        {
901
                                                while (i < model.getSize())
902
                                                {
903
                                                        s = model.getElementAt(i).toString();
904
                                                        
905
                                                        // If matches the start
906
                                                        if (s.startsWith(text)) {
907
                                                                matchesTheStart = true;
908
                                                                                
909
                                                                // Increments index
910
                                                                i++;
911
                                                        }
912
                                                        else
913
                                                        {
914
                                                                // When the characters written doesn't match -> set this characters to red color   
915
                                                                removedItems.add(model.getElementAt(i));                                
916
                                                                this.removeItemAt(i);
917
                                                        }                                
918
                                                }
919
                                        }
920
                                        else
921
                                        {
922
                                                while (i < model.getSize())
923
                                                {
924
                                                        s = (model.getElementAt(i).toString().toUpperCase());
925
                                                                                                        
926
                                                        // If matches the start
927
                                                        if (s.startsWith(text.toUpperCase())) {
928
                                                                matchesTheStart = true;
929
                                                                                
930
                                                                // Increments index
931
                                                                i++;
932
                                                        }
933
                                                        else
934
                                                        {
935
                                                                // When the characters written doesn't match -> set this characters to red color   
936
                                                                removedItems.add(model.getElementAt(i));                                
937
                                                                this.removeItemAt(i);
938
                                                        }                                
939
                                                }
940
                                        }
941
                                }
942
                        }
943
                                                                
944
                        // Reset the index
945
                        if (this.getItemCount() > 0)
946
                                this.setSelectedIndex(0);
947
                        else
948
                                this.setSelectedIndex(-1);
949
                                
950
                        // Sets the written text to the text field
951
                        txtField.setText(text);
952
                
953
                        // If has matched the text written with any item -> set the text on black color
954
                        // else -> set the text on red color
955
                        if (!onlyOneColor)
956
                        {
957
                                if (matchesTheStart)
958
                                        txtField.setForeground(Color.BLACK);
959
                                else
960
                                        txtField.setForeground(Color.RED);
961
                        }
962
                        
963
                        this.showPopup();
964
                }                
965
        }
966
}