Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libUI / src / org / gvsig / gui / beans / swing / jComboBoxItemsSeeker / JComboBoxItemsSeekerConfigurable.java @ 11762

History | View | Annotate | Download (24.9 KB)

1
package org.gvsig.gui.beans.swing.jComboBoxItemsSeeker;
2

    
3
import java.awt.Color;
4
import java.awt.event.FocusAdapter;
5
import java.awt.event.FocusEvent;
6
import java.awt.event.FocusListener;
7
import java.awt.event.KeyAdapter;
8
import java.awt.event.KeyEvent;
9
import java.awt.event.KeyListener;
10
import java.awt.event.MouseAdapter;
11
import java.awt.event.MouseEvent;
12
import java.util.Vector;
13

    
14
import javax.accessibility.Accessible;
15
import javax.swing.ComboBoxEditor;
16
import javax.swing.ComboBoxModel;
17
import javax.swing.JComboBox;
18
import javax.swing.JList;
19
import javax.swing.event.PopupMenuListener;
20
import javax.swing.plaf.basic.BasicComboBoxUI;
21
import javax.swing.plaf.basic.ComboPopup;
22
import javax.swing.text.AttributeSet;
23
import javax.swing.text.BadLocationException;
24
import javax.swing.text.JTextComponent;
25
import javax.swing.text.PlainDocument;
26

    
27

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

    
69

    
70
/**
71
 * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
72
 */
73
public class JComboBoxItemsSeekerConfigurable extends JComboBox implements java.io.Serializable {
74
        // AQU? ID
75
        
76
        // CONSTANTS FOR CONFIGURE THE BEHAVIOR
77
        public static final boolean DEFAULT_ONLY_ONE_COLOR_ON_TEXT_CONFIGURATION = false;
78
        public static final boolean DEFAULT_BEEP_ENABLED_CONFIGURATION = false;
79
        public static final boolean DEFAULT_HIDE_POPUP_IF_THERE_ARE_NO_ITEMS_CONFIGURATION = true;
80
        public static final boolean DEFAULT_TO_FORCE_SELECT_AN_ITEM_CONFIGURATION = true;
81
        // END CONSTANTS FOR CONFIGURE THE BEHAVIOR
82
        
83
        // EDITOR DOCUMENT REFERENCE
84
        /**
85
         * A reference to the document of this component 
86
         */
87
        private PlainDocumentTextFormatter document;
88
        // END EDITOR DOCUMENT REFERENCE
89
        
90
        // NEW ATTRIBUTES 
91
        /**
92
         * A reference to the model of this component (according to the MVC <i>(Model-View-Controller)</i> pattern)
93
         */
94
        private DefaultComboBoxItemsSeekerConfigurableModel model;
95

    
96
        /**
97
         * Has or not to hide the popup on focus loss
98
         */
99
        private boolean hidePopupOnFocusLoss;
100
        
101
        /**
102
         * Has an item of the popup been selected or not by the user
103
         */
104
        private boolean popupItemSelected;
105
        // END NEW ATTRIBUTES
106
        
107
        // LISTENERS
108
        /**
109
         * Listener for the editor key 
110
         */
111
        private KeyListener editorKeyListener;
112
        
113
        /**
114
         * Listener for the editor focus 
115
         */
116
        private FocusListener editorFocusListener;
117
        
118
        /**
119
         * Listener for the popup menu 
120
         */
121
        private PopupMenuListener popupMenuListener;
122
        
123
        /**
124
         * Last item selected
125
         */
126
        private Object previousSelected;
127
        // END LISTENERS
128
        
129
        // CONFIGURATION FLAGS
130
        private boolean onlyOneColorOnText_Flag;
131
        private boolean beepEnabled_Flag;
132
        private boolean hidePopupIfThereAreNoItems_Flag;
133
        private boolean toForceSelectAnItem_Flag;
134
        // END FLAGS
135
        
136
        /**
137
         * Default constructor without parameters
138
         */
139
        public JComboBoxItemsSeekerConfigurable() {
140
                super();
141
                initialize();
142
        }
143

    
144
        /**
145
         * Default constructor with a {@link ComboBoxModel} as parameter
146
         * 
147
         * @param aModel javax.swing.ComboBoxModel
148
         */
149
        public JComboBoxItemsSeekerConfigurable(ComboBoxModel aModel) {
150
                super(aModel);
151
                initialize();
152
        }        
153

    
154
        /**
155
         * Default constructor with an array of objects as parameter
156
         * 
157
         * @param items An array of objects. All them must implement a <i>'String toStrin()'</i> method
158
         */
159
        public JComboBoxItemsSeekerConfigurable(Object[] items) {
160
                super(items);
161
                initialize();
162
        }
163

    
164
        /**
165
         * Default constructor with a Vector of objects as parameter
166
         * 
167
         * @param items A {@link Vector} of objects. All them must implement a <i>'String toStrin()'</i> method
168
         */
169
        public JComboBoxItemsSeekerConfigurable(Vector items) {
170
                super(items);
171
                initialize();
172
        }
173
        
174
        /**
175
         * This method sets the start values of inner attributes and creates the necessary inner objects
176
         */
177
        private void initialize() {                
178
                // By default user hasn't selected an item of the popup
179
                popupItemSelected = false;
180
                
181
                // By default no item has been selected
182
                previousSelected = null;
183
                
184
                // Set default flags configuration
185
                this.setDefaultBehaviorFlagsConfiguration();
186
                
187
                // Creates the model for this component and gets it reference
188
                model = new DefaultComboBoxItemsSeekerConfigurableModel();
189
                super.setModel(model);
190
                
191
        // Allows user to edit on the combobox
192
                super.setEditable(true);
193
        
194
                // Other configuration tasks
195
                this.configure();
196
                
197
                // If there are items -> select the first
198
                if (model.getSize() > 0) {
199
                        model.setSelectedItem(model.getElementAt(0));
200
                }
201
        }
202
        
203
        /**
204
         * Configures the component and some of its elements
205
         */
206
        private void configure() {
207
        // Defines a key listener for the editor of this component
208
        this.defineEditorKeyListener(this);
209

    
210
        // Defines a focus listener for the editor of this component
211
        this.defineEditorFocusListener(this);
212
        
213
                // Configures the document of the editor of this component
214
                this.configureDocument();
215
                
216
                // Configures the editor (ComboBoxEditor) of this component
217
                this.configureEditor(this.getEditor());
218
                
219
                // Configures the popup of this component
220
                this.configurePopUp(this);
221
        }
222
        
223
        /**
224
         * Configures the editor ( {@link ComboBoxEditor} ) of this component
225
         * 
226
         * @param newEditor The new editor to configure
227
         */
228
        private void configureEditor(ComboBoxEditor newEditor) {
229
        if (newEditor != null) {
230
                   JTextComponent jTextComponentOfEditor = (JTextComponent) newEditor.getEditorComponent();
231
                
232
                // Adds the new document (tries to remove it if it existed before)
233
                jTextComponentOfEditor.setDocument(this.document);
234
                
235
                // Adds the new Key Listener (tries to remove it if it existed before)
236
                   jTextComponentOfEditor.removeKeyListener(this.editorKeyListener);
237
                jTextComponentOfEditor.addKeyListener(this.editorKeyListener);
238
                   
239
                // Adds the new Focus Listener (tries to remove it if it existed before)
240
                jTextComponentOfEditor.removeFocusListener(this.editorFocusListener);
241
                jTextComponentOfEditor.addFocusListener(this.editorFocusListener);
242
        }
243
        }
244

    
245
        /**
246
         * Configures the document of the editor of this component
247
         */
248
        private void configureDocument() {
249
                // Creates the document of the editor of this component
250
        document = new PlainDocumentTextFormatter();
251
        
252
        // Set reference to the container component
253
        document.setJComboBoxReference(this);
254
        }
255

    
256
        /**
257
         * Configures the popup of this component
258
         *
259
         * @param combo_Box A reference of this component
260
         */
261
        private void configurePopUp(JComboBoxItemsSeekerConfigurable combo_Box) {
262
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
263
                this.addPopupMenuListener(this.popupMenuListener);
264
        
265
        BasicComboBoxUI comboBoxUi = (BasicComboBoxUI)comboBoxReference.getUI();
266
        Accessible a = comboBoxUi.getAccessibleChild(comboBoxReference, 0);
267
        if (a instanceof ComboPopup) {
268
            JList jlist = ((ComboPopup)a).getList();
269

    
270
            jlist.addMouseListener(new MouseAdapter() {
271
                                /*
272
                                 *  (non-Javadoc)
273
                                 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
274
                                 */
275
                                public void mousePressed(MouseEvent e) {
276
                                        // User selects an item of the popup using the mouse
277
                                        popupItemSelected = true;
278
                                }
279
            });
280
        }
281
        }
282
        
283
        /**
284
         *  Sets the default values of the flags
285
         */
286
        private void setDefaultBehaviorFlagsConfiguration() {
287
                this.onlyOneColorOnText_Flag = DEFAULT_ONLY_ONE_COLOR_ON_TEXT_CONFIGURATION;
288
                this.beepEnabled_Flag = DEFAULT_BEEP_ENABLED_CONFIGURATION;
289
                this.hidePopupIfThereAreNoItems_Flag = DEFAULT_HIDE_POPUP_IF_THERE_ARE_NO_ITEMS_CONFIGURATION;
290
                this.toForceSelectAnItem_Flag = DEFAULT_TO_FORCE_SELECT_AN_ITEM_CONFIGURATION;
291
        }
292
        
293
        /**
294
         * Defines a key listener for the editor of this component. <br>
295
         * This method is another important difference from the JComboBox; and could work badly with some keymaps.
296
         * 
297
         * @param combo_Box A reference of this component
298
         */
299
        private void defineEditorKeyListener(JComboBoxItemsSeekerConfigurable combo_Box) {
300
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
301
                
302
                editorKeyListener = new KeyAdapter() {
303
                        /*
304
                         * (non-Javadoc)
305
                         * @see java.awt.event.KeyAdapter#keyPressed(java.awt.event.KeyEvent)
306
                         */
307
                        public void keyPressed(KeyEvent ke)  // Executed on the Start view state or Search view state
308
                        {
309
                                // According the key pressed, do some actions or others
310
                                switch (ke.getKeyCode())
311
                                {
312
                                        case KeyEvent.VK_ENTER :
313
                                                // Don't allow execute the default instructions because they have a bug (first time we remove some characteres, no item will be displayed in the popup)
314
                                                ke.consume();
315
                                                
316
                                                // Sets the caret position of the text in the document to the end:
317
                                                ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).setCaretPosition(document.getLength());
318

    
319
                                                if (toForceSelectAnItem_Flag) {
320
                                                        // Select now the first item or the previous selected
321
                                                        switch (comboBoxReference.getModel().getSize()) {
322
                                                                case 0:
323
                                                                        if (previousSelected != null) {
324
                                                                                ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).setText(previousSelected.toString());
325
                                                                        }
326
                                                                        break;
327
                                                                default:
328
                                                                        previousSelected = comboBoxReference.getItemAt(0); // Select the first
329
                                                                        comboBoxReference.setSelectedIndex(0);
330
                                                        }
331
                                                }
332
                                                
333
                                                // Hide the popup
334
                                                comboBoxReference.hidePopup();
335
                                                break;
336
                                                
337
                                        case KeyEvent.VK_UP: case KeyEvent.VK_DOWN:
338
                                                // User selects an item of the popup using the mouse
339
                                                popupItemSelected = true;
340
                                                break;
341
                                }
342
                        }
343
                };
344
        }
345
        
346
        /**
347
         * Defines a focus listener for the editor of this component
348
         * 
349
         * @param combo_Box A reference of this component
350
         */
351
        private void defineEditorFocusListener(JComboBoxItemsSeekerConfigurable combo_Box) {
352
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
353
                
354
                // Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out                
355
                hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
356
                
357
                // Highlight whole text when gaining focus
358
                editorFocusListener = new FocusAdapter() {
359

    
360
                        /*
361
                         *  (non-Javadoc)
362
                         * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent)
363
                         */
364
                        public void focusLost(FocusEvent e) {
365
                                if (toForceSelectAnItem_Flag) {
366
                                        // Select now the first item or the previous selected
367
                                        switch (comboBoxReference.getModel().getSize()) {
368
                                                case 0:
369
                                                        if (previousSelected != null) {
370
                                                                ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).setText(previousSelected.toString());
371
                                                        }
372
                                                        break;
373
                                                default:
374
                                                        previousSelected = comboBoxReference.getItemAt(0); // Select the first
375
                                                        comboBoxReference.setSelectedIndex(0);
376
                                        }
377
                                }
378
                                
379
                                comboBoxReference.hidePopup();
380
                                
381
                                // Workaround for Bug 5100422 - Hide Popup on focus loss
382
                                if (hidePopupOnFocusLoss) {
383
                                        comboBoxReference.setPopupVisible(false);
384
                                }
385
                        }                        
386
                };
387
        }
388

    
389
        ////// METHODS FOR THE BEHAVIOR FLAGS  //////
390
        /**
391
         * Returns the 'only_One_Color_On_Text' configuration value of this component. Configuration values are: <br>
392
         *   + true: always uses black color on text. <br>
393
         *   + false: by default uses black color on text, but if text written by user doesn't match with any item, text will be on red color.
394
         * 
395
         * @return 'only_One_Color_On_Text' configuration
396
         */
397
        public boolean isOnlyOneColorOnText_Flag() {
398
                return onlyOneColorOnText_Flag;
399
        }
400
        
401
        /**
402
         * Sets the 'only_One_Color_On_Text' configuration value for this component. Configuration values are: <br>
403
         *   + true: always uses black color on text. <br>
404
         *   + false: by default uses black color on text, but if text written by user doesn't match with any item, text will be on red color.
405
         * 
406
         * @param A boolean value for 'only_One_Color_On_Text' configuration flag
407
         */
408
        public void setOnlyOneColorOnText_Flag(boolean only_One_Color) {
409
                this.onlyOneColorOnText_Flag = only_One_Color;
410
        }
411

    
412
        /**
413
         * Returns the 'beep_Enabled' configuration value of this component. Configuration values are: <br>
414
         *   + true: a beep-sound is listened when no item matches with the text written. <br>
415
         *   + false: no sound is listened.
416
         * 
417
         * @return 'beep_Enabled' configuration
418
         */
419
        public boolean isBeepEnabled_Flag() {
420
                return this.beepEnabled_Flag;
421
        }
422
        
423
        /**
424
         * Sets the 'beep_Enabled' configuration value for this component. Configuration values are: <br>
425
         *   + true: a beep-sound is listened when no item matches with the text written. <br>
426
         *   + false: no sound is listened.
427
         * 
428
         * @param A boolean value for 'beep_Enabled' configuration flag
429
         */
430
        public void setBeepEnabled_Flag(boolean beep_Enabled) {
431
                this.beepEnabled_Flag = beep_Enabled;
432
        }        
433

    
434
        /**
435
         * Returns the 'hidePopupIfThereAreNoItems_Flag' configuration value of this component. Configuration values are: <br>
436
         *   + true: hides the popup if there are no items when you write.
437
         *   + false: default behaviour (if there are no items when you write, popup c <br>ontinues visible) .
438
         * 
439
         * @return 'hidePopupIfThereAreNoItems_Flag' configuration
440
         */
441
        public boolean isHidePopupIfThereAreNoItems_Flag() {
442
                return this.hidePopupIfThereAreNoItems_Flag;
443
        }
444
        
445
        /**
446
         * Sets the 'hidePopupIfThereAreNoItems_Flag' configuration value for this component. Configuration values are: <br>
447
         *   + true: hides the popup if there are no items when you write. <br>
448
         *   + false: default behaviour (if there are no items when you write, popup continues visible) .
449
         * 
450
         * @param A boolean value for 'hidePopupIfThereAreNoItems_Flag' configuration flag
451
         */
452
        public void setHidePopupIfThereAreNoItems_Flag(boolean hide) {
453
                this.hidePopupIfThereAreNoItems_Flag = hide;
454
        }
455

    
456
        /**
457
         * Returns the 'toForceSelectAnItem_Flag' configuration value of this component. Configuration values are: <br>
458
         *   + true: selects the previous selected item or the first of the list when user presses the Enter key or when the component loses the focus . <br>
459
         *   + false: default behaviour .
460
         * 
461
         * @return 'toForceSelectAnItem_Flag' configuration
462
         */
463
        public boolean isToForceSelectAnItem_Flag() {
464
                return this.toForceSelectAnItem_Flag;
465
        }
466
        
467
        /**
468
         * Sets the 'toForceSelectAnItem_Flag' configuration value for this component. Configuration values are: <br>
469
         *   + true: selects the previous selected item or the first of the list when user presses the Enter key or when the component loses the focus . <br>
470
         *   + false: default behaviour .
471
         * 
472
         * @param A boolean value for 'toForceSelectAnItem_Flag' configuration flag
473
         */
474
        public void setToForceSelectAnItem_Flag(boolean force) {
475
                this.toForceSelectAnItem_Flag = force;
476
        }
477
        ////// END METHODS FOR THE BEHAVIOR FLAGS  //////
478

    
479
        
480
        /**
481
         * Inner class that inherits of the class PlainDocument, and is used for manipulate the textWritten that has the document of the editor of this component. <br>
482
         * This class is also optimized for items seek.
483
         * 
484
         * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
485
         */
486
        private class PlainDocumentTextFormatter extends PlainDocument {
487
                private static final long serialVersionUID = 4158213349939840209L;
488
                private JComboBoxItemsSeekerConfigurable comboBoxReference;
489
                private String textWritten;
490
                private boolean updatedModel;
491
                private String textOfReplacement;
492
                private boolean textInRedColor;
493
                private int old_caretPosition;
494

    
495
                /**
496
                 * Default Constructor
497
                 */
498
                public PlainDocumentTextFormatter() {
499
                        super();
500
                        this.initialize();
501
                }
502
                
503
                /**
504
                 * This method makes some initialize operations 
505
                 */
506
                private void initialize() {
507
                        textWritten = "";
508
                        textOfReplacement = "";
509
                        textInRedColor = false;
510
                }
511

    
512
                /**
513
                 * Sets a reference of this component
514
                 * 
515
                 * @param combo_Box A reference to the class that contains this.
516
                 */
517
                private void setJComboBoxReference(JComboBoxItemsSeekerConfigurable combo_Box) {
518
                        comboBoxReference = combo_Box;
519
                }
520

    
521
                /*
522
                 *  (non-Javadoc)
523
                 * @see javax.swing.text.Document#insertString(int, java.lang.String, javax.swing.text.AttributeSet)
524
                 */
525
            public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
526
                    if (updatedModel) {
527
                            model.setTextWritten(textWritten);
528
                            super.insertString(offs, textWritten, a);
529
                            
530
                            return;
531
                    }
532

    
533
                    hidePopup();
534
                    
535
                    if (textWritten.length() > 0) {
536
                            if (offs < textWritten.length()) {
537
                                    String old_textWritten = textWritten;
538
                                    
539
                                    // End of the text
540
                                    textWritten = textWritten.substring(offs, textWritten.length());
541
                                    
542
                                    // Beginning of the text
543
                                    if (offs > 0) {
544
                                        // Reset (without text written)
545
                                            textWritten = old_textWritten.substring(0, offs) + str + textWritten;
546
                                    }
547
                                    else {
548
                                            textWritten = str + textWritten;
549
                                    }
550
                            }
551
                            else {
552
                                    textWritten = textWritten.substring(0, offs) + str;
553
                            }
554
                    }
555
                    else {
556
                            textWritten =  str;
557
                    }
558
                    
559
                    model.setTextWritten(textWritten);
560
                    
561
                    super.insertString(offs, str, a);
562

    
563
                    // Update the color of the text
564
                    updateTextColorAndRingBeep();
565
            
566
                    if (model.getSize() > 0) {
567
                                   showPopup();
568
                    }
569
                    else {
570
                            if ((textWritten.compareTo("") != 0) && (!hidePopupIfThereAreNoItems_Flag)) {
571
                                    showPopup();        
572
                            }
573
                    }
574

    
575
                    // Update the caret position -> at the same place it was or at the end
576
                    updateCaretPosition(textWritten.length());                    
577
            }
578
                
579
            /*
580
             *  (non-Javadoc)
581
             * @see javax.swing.text.AbstractDocument#replace(int, int, java.lang.String, javax.swing.text.AttributeSet)
582
             */
583
            public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
584
                    // Avoid two replaces for the same operation
585
                    if ((text.compareTo("") == 0) && (length == textWritten.length()))
586
                            return;
587
                    
588
                    // Only remove if there is text to be replaced (text selected)
589
                    if (length > 0) {
590
                            textOfReplacement = text;
591
                            remove(offset, length);
592
                    }
593
                    else {
594
                            if ((offset > 0) && (offset != textWritten.length())) {
595
                                    // Must replace the model for update the data in the popup correctly
596
                                    String old_textWritten;
597
                                
598
                                // There is a bug that when text has been removed, the elements in the popup aren seen.
599
                                // The solution to this bug is add them as a new model
600
                                hidePopup();
601

    
602
                                updatedModel = true;
603

    
604
                                old_textWritten = textWritten;
605
                                old_caretPosition = ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).getCaretPosition() + text.length();
606
                                
607
                                textWritten = "";
608
                                model.setTextWritten(textWritten);
609

    
610
                                super.remove(0, old_textWritten.length());
611
                        
612
                                // Must replace the model for update the data in the popup correctly
613
                                model = new DefaultComboBoxItemsSeekerConfigurableModel(model.getData());
614
                                comboBoxReference.setModel(model);
615
                                
616
                                // Reset (without text written)
617
                                insertString(0, textWritten, null);
618
                                
619
                                // Insert the new text
620
                                textWritten = old_textWritten.substring(0, offset) + text + old_textWritten.substring(offset, old_textWritten.length());
621
                                
622
                                insertString(0, textWritten, null);
623
                                
624
                                updatedModel = false;
625
                                
626
                                // Update the color of the text
627
                                updateTextColorAndRingBeep();
628
                                
629
                                // Update the caret position -> at the same place it was or at the end
630
                                updateCaretPosition(old_caretPosition);
631
                                
632
                                // Only show the popup if there are items to show
633
                                if (model.getSize() > 0) {
634
                                               showPopup();
635
                                }
636
                                else {
637
                                        if ((textWritten.compareTo("") != 0) && (!hidePopupIfThereAreNoItems_Flag)) {
638
                                                showPopup();        
639
                                        }
640
                                }
641
                            }
642
                            else {
643
                                    // Default replacement
644
                                    super.replace(offset, length, text, attrs);
645
                            }
646
                    }
647
            }
648
            
649
                /*
650
                 *  (non-Javadoc)
651
                 * @see javax.swing.text.Document#remove(int, int)
652
                 */
653
                public void remove(int offs, int len) throws BadLocationException {
654
                        String old_textWritten;
655
                    
656
                    // There is a bug that when text has been removed, the elements in the popup aren seen.
657
                    // The solution to this bug is add them as a new model
658
                    hidePopup();
659

    
660
                    updatedModel = true;
661

    
662
                    old_textWritten = textWritten;
663
                    old_caretPosition = Math.min(((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).getCaretPosition(), offs);
664
                    
665
                    textWritten = "";
666
                    model.setTextWritten(textWritten);
667

    
668
                    super.remove(0, old_textWritten.length());
669
            
670
                    // Must replace the model for update the data in the popup correctly
671
                    model = new DefaultComboBoxItemsSeekerConfigurableModel(model.getData());
672
                    comboBoxReference.setModel(model);
673
                    
674
                    // Reset (without text written)
675
                    insertString(0, textWritten, null);
676
                    
677
                    // Insert the new text
678
                    textWritten = old_textWritten.substring(0, offs) + textOfReplacement + old_textWritten.substring(offs + len, old_textWritten.length());
679
                    textOfReplacement = "";
680

    
681
                    insertString(0, textWritten, null);
682
                    
683
                    updatedModel = false;
684
                    
685
                    // Update the color of the text
686
                    updateTextColorAndRingBeep();
687
                    
688
                    // Only show the popup if there are items to show
689
                    if (model.getSize() > 0) {
690
                                   showPopup();
691
                    }
692
                    else {
693
                            if ((textWritten.compareTo("") != 0) && (!hidePopupIfThereAreNoItems_Flag)) {
694
                                    showPopup();        
695
                            }
696
                    }
697
          
698
                    // Update the caret position -> at the same place it was or at the end
699
                    updateCaretPosition(old_caretPosition);
700
                }
701
                
702
                /**
703
                 * Updates the color of the text in the {@link ComboBoxEditor} of this component.<br>
704
                 * Also rings a beep if there is no item
705
                 * 
706
                 * <ul>
707
                 * <li> Text in red color: if no item starts with the text written by the user.
708
                 * <li> Text in black color: if there is at least one item that starts with the text written by the user.
709
                 * </ul>
710
                 */
711
                private void updateTextColorAndRingBeep() {
712
                        if (! comboBoxReference.isOnlyOneColorOnText_Flag()) {
713
                            // Set text into red color if no items matches with the text written, or in black color if it was in red
714
                                //   color and now there is almost one element that starts with the characteres written by the user
715
                            if (textWritten.compareTo("") != 0) {
716
                                    if (model.getSize() == 0) {
717
                                               comboBoxReference.getEditor().getEditorComponent().setForeground(Color.RED);
718
                                               textInRedColor = true;
719
                                               
720
                                               // Rings a beep if allowed
721
                                                if (beepEnabled_Flag)
722
                                                        comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
723
                                    }
724
                                    else {
725
                                            comboBoxReference.getEditor().getEditorComponent().setForeground(Color.BLACK);
726
                                            textInRedColor = false;
727
                                    }
728
                            }
729
                            else {
730
                                    if (textInRedColor) {
731
                                            comboBoxReference.getEditor().getEditorComponent().setForeground(Color.BLACK);
732
                                            textInRedColor = false;
733
                                    }
734
                            }
735
                        }
736
                        else {
737
                                // Rings a beep if no there is no item, and if it's allowed
738
                                if ((textWritten.compareTo("") != 0) &&  (model.getSize() == 0)) {
739
                                        if (beepEnabled_Flag)
740
                                                comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
741
                                }
742
                        }
743
                }
744
                
745
                /**
746
                 * Updates the position of the caret in the {@link ComboBoxEditor} of this component.
747
                 * 
748
                 * @param position The new position of the caret.
749
                 */
750
                private void updateCaretPosition(int position) {
751
                        // If user has selected an item of the popup (using the mouse) -> set the caret position to the end of the text
752
                        if (popupItemSelected) {
753
                                ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).setCaretPosition(textWritten.length());
754
                                popupItemSelected = false;
755
                                return;
756
                        }
757
                        
758
                        if (position > textWritten.length())
759
                                ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).setCaretPosition(textWritten.length());
760
                        else
761
                                ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).setCaretPosition(position);
762
                }
763
        }
764
}