Statistics
| Revision:

root / trunk / libraries / libUI / src / org / gvsig / gui / beans / comboBoxItemsSeeker / JComboBoxItemsSeekerConfigurable.java @ 8488

History | View | Annotate | Download (77.3 KB)

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

    
3
import java.awt.Color;
4
import java.awt.event.ActionEvent;
5
import java.awt.event.FocusAdapter;
6
import java.awt.event.FocusEvent;
7
import java.awt.event.FocusListener;
8
import java.awt.event.KeyAdapter;
9
import java.awt.event.KeyEvent;
10
import java.awt.event.KeyListener;
11
import java.awt.event.MouseAdapter;
12
import java.awt.event.MouseEvent;
13
import java.awt.event.MouseWheelEvent;
14
import java.awt.event.MouseWheelListener;
15
import java.beans.PropertyChangeEvent;
16
import java.beans.PropertyChangeListener;
17

    
18
import javax.swing.ComboBoxEditor;
19
import javax.swing.ComboBoxModel;
20
import javax.swing.JComboBox;
21
import javax.swing.JOptionPane;
22
import javax.swing.event.CaretListener;
23
import javax.swing.event.DocumentEvent;
24
import javax.swing.event.DocumentListener;
25
import javax.swing.event.ListDataEvent;
26
import javax.swing.event.ListDataListener;
27
import javax.swing.event.PopupMenuEvent;
28
import javax.swing.event.PopupMenuListener;
29
import javax.swing.event.UndoableEditEvent;
30
import javax.swing.event.UndoableEditListener;
31
import javax.swing.text.AttributeSet;
32
import javax.swing.text.BadLocationException;
33
import javax.swing.text.JTextComponent;
34
import javax.swing.text.PlainDocument;
35
import javax.swing.undo.CannotRedoException;
36
import javax.swing.undo.CannotUndoException;
37
import javax.swing.undo.UndoManager;
38

    
39
import org.apache.log4j.Logger;
40
import org.gvsig.gui.beans.Messages;
41
import org.gvsig.gui.beans.optionsEditionByMousePopupMenu.JOptionsEditionByMousePopupMenu;
42

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

    
84
/** ?? EN DESARROLLO !!
85
 * A component that is a modification of JComboBox, of which inherits.
86
 * This component allows:
87
 *    - To show item/s that the start of their string value matches with the text written in the editable field
88
 *    - To be configured it's behavior.
89
 *    
90
 * This component has been done according the MVC (Model-View-Control) pattern, and is a 'Bean'.
91
 *    
92
 * There are 10 configuration flags/attributes: 3 for the Model and the others for the Control and/or View.
93
 *    ? Model flags/attributes (for more information see the 'AbstractDefaultComboBoxItemsSeekerConfigurableModel' class documentation):
94
 *         - Start Behavior -> Configure how return items at beginning (always returns all items).         
95
 *         - Search Behavior -> Configure how return items when it's searching an item.
96
 *         - Case Sensitive -> Discriminates capital letters from small letters or not when seeks items
97
 *    ? Control and/or View flags (all flags can be 'true' or 'false'):
98
 *         - Only One Color On Text:
99
 *                     + true -> always uses black color on text
100
 *              + 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
101
 *         - Complete Matched Item:
102
 *                     + true -> When user writes, shows also the rest of the current matched item that user hasn't written.
103
 *                      + false -> Only shows the text written by the user when user is writting.
104
 *         - Beep Enabled:
105
 *              + true -> a beep-sound is listened when no item matches with the text written.
106
 *              + false -> no sound is listened.
107
 *         - Allowed Mouse Edition Popup Menu:
108
 *                     + true -> a 'PopupMenu' for text edition that appears when the user clicks on the text-edition-field with the right
109
 *                           button of the mouse.
110
 *              + false -> that 'PopupMenu' won't appear. 
111
 *         - To Force To Only Coincidences In The Search:
112
 *                     + true -> If the user has written some text that doesn't mach with any item, and press the 'Enter' key for close the popup the user will
113
 *                           see written in the text-edition-field the last item which matched with the text written, or the first item of the model if
114
 *                           there wasn't.
115
 *              + false -> If no item matches with the text written and the user presses the 'Enter' key, no item will be selected.
116
 *         - Use Highlight:
117
 *              + true -> marks characters of the text in the text-edition-field with a highlight.
118
 *              + false -> doesn't do that.
119
 *    . Control and Model flag (can be 'true' or 'false'):
120
 *         - Allowed Repeated Items -> Uses one of the two models according the value of this flag:
121
 *              + true -> Uses 'ComboBoxItemsSeekerConfigurableModel' as model (this could work slowly).
122
 *              + false -> Uses 'ComboBoxSingularItemsSeekerConfigurableModel' as model.
123
 *
124
 * By default the configuration is:
125
 *     - Start_Behavior = MAINTAIN_ORIGINAL_POSITION_START
126
 *     - Search_Behavior = ORDERED_DYNAMIC_SEARCH
127
 *     - Case_Sensitive = false
128
 *     - Only_One_Color_On_Text = false
129
 *     - Complete_Matched_Item = true
130
 *     - Beep_Enabled = true
131
 *     - Allowed_Repeated_Items = false 
132
 *     - Allowed_Mouse_Edition_Popup_Menu = true
133
 *     - To_Force_To_Only_Coincidences_In_The_Search = true
134
 *     - Use_Highlight = true
135
 *     
136
 * Other functionality:
137
 *     - Similar functionality as JComboBox:
138
 *         + Select an item from the inner popup using the mouse
139
 *         + Show item/items that match in the inner popup
140
 *         + Similar edition operations: Right, left, ...
141
 *         + ...
142
 *     - With the keyboard the user can do the same operations as with the "edition popup menu" :
143
 *         CTRL + A -> Select all text
144
 *         CTRL + Z -> Undo
145
 *         CTRL + SHIFT + Z -> Redo
146
 *         CTRL + C -> Copy selected text         
147
 *         CTRL + X -> Cut selected text
148
 *         CTRL + V -> Paste on selected text/position
149
 *         DELETE (SUPR in Spanish Keyboard) -> Remove selected text
150
 *     - ESC key -> Sets the component to its initial state (that user can estimate)
151
 *
152
 * Special-Warning characteristics
153
 *     - In same inherit states the view could don't match with the model (this states aren't final states)
154
 *
155
 * Limitations:
156
 *     - Items of the model of this component must have a "string" value returned by "toString()" method
157
 *     - If the model of the component has lot of items, this could work slowly.
158
 *     - If the model has repeated items -> set true the flag 'allowedRepeatedItems', this will use the 'ComboBoxItemsSeekerConfigurableModel' model,
159
 *         and will work more slowly than the 'ComboBoxSingularItemsSeekerConfigurableModel' model; more as more items had the model.
160
 *     - It's possible that some combination of configuration would be unmanageable.
161
 *     - It's possible that some configuration or some operation fail !!  
162
 *
163
 * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
164
 */
165
public class JComboBoxItemsSeekerConfigurable extends JComboBox implements java.io.Serializable {
166
        
167
        // CONSTANTS FOR THE CURRENT STATE OF THE COMPONENT
168
        private final int BEGINNING_VIEW_STATE = 0;
169
        private final int START_VIEW_STATE = 1;
170
        private final int SEARCH_VIEW_STATE = 2;
171
        // END CONSTANTS FOR THE CURRENT STATE OF THE COMPONENT        
172
        
173
        // ATTRIBUTE FOR THE CURRENT STATE
174
        private int currentShowState; // 0 -> at the beginning; 1 -> when is showing the start list of items; 2 -> when is showing a search list of items
175
        // END ATTRIBUTE FOR THE CURRENT STATE
176

    
177
        // CONSTANTS FOR CONFIGURE THE BEHAVIOR
178
        public static final boolean DEFAULT_ONLY_ONE_COLOR_ON_TEXT_CONFIGURATION = false;
179
        public static final boolean DEFAULT_COMPLETE_MATCHED_ITEM_CONFIGURATION = true;
180
        public static final boolean DEFAULT_BEEP_ENABLED_CONFIGURATION = true;
181
        public static final boolean DEFAULT_ALLOWED_REPEATED_ITEMS_CONFIGURATION = false;
182
        public static final boolean DEFAULT_ALLOWED_MOUSE_EDITION_POPUP_MENU_CONFIGURATION = true;
183
        public static final boolean DEFAULT_TO_FORCE_TO_ONLY_COINCIDENCES_IN_THE_SEARCH_CONFIGURATION = true;
184
        public static final boolean DEFAULT_USE_HIGHLIGHT_CONFIGURATION = true;
185
        // END CONSTANTS FOR CONFIGURE THE BEHAVIOR
186
        
187
        // CONFIGURATION FLAGS
188
        private boolean onlyOneColorOnText_Flag;
189
        private boolean completeMatchedItem_Flag;
190
        private boolean beepEnabled_Flag;
191
        private boolean allowedRepeatedItems_Flag;
192
        private boolean allowedMouseEditionPopupMenu_Flag;
193
        private boolean toForceToOnlyCoincidencesInTheSearch_Flag;
194
        private boolean useHighlight_Flag;
195
        // END FLAGS
196
        
197
        // STORE THE SELECTED ITEM AND THE LAST SELECTED ITEM
198
        private Object lastSelectedItemPopupUse; // This is used for only update (refresh) de popup when a different item is selected
199
    // END STORE THE SELECTED ITEM AND THE LAST SELECTED ITEM
200
        
201
        private int num = 0; //sobra -> se usan en el log -> ?? SE PUEDE BORRAR !!
202
        
203
        // NUMBER OF ITEMS SHOWED AT THE SAME TIME IN THE POPUP
204
        private final int POPUP_LIST_ITEMS_HEIGHT = 8;
205
    // END NUMBER OF ITEMS SHOWED AT THE SAME TIME IN THE POPUP
206
        
207
        // MODEL REFERENCE
208
        private AbstractDefaultComboBoxItemsSeekerConfigurableModel model;
209
        // END MODEL REFERENCE
210
        
211
        // LISTENERS
212
        private KeyListener editorKeyListener;
213
        private MouseAdapter editorMouseListener;
214
        private MouseWheelListener editorMouseWheelListener;
215
        private FocusListener editorFocusListener;
216
        private DocumentListener documentListener;
217
        private ListDataListener modelListDataListener;
218
        private PopupMenuListener popupMenuListener;
219
        private PropertyChangeListener editionMenuListener;
220
        private CaretListener caretListener;
221
        // END LISTENERS
222
        
223
        // EDITOR DOCUMENT REFERENCE
224
        private PlainDocumentTextFormatter document;
225
        // END EDITOR DOCUMENT REFERENCE
226
        
227
        // OTHER FLAGS
228
        private boolean allowInsertString;
229
        private boolean lastWasTheBeginningState;
230
        private boolean lastWasPressedAKeyModifier;
231
        private boolean popupWillBeVisible;
232
        private boolean optionsEditorWasVisible;
233
        private boolean selecting;
234
        private boolean hidePopupOnFocusLoss;
235
        private boolean hitBackspace;
236
        private boolean hitBackspaceOnSelection;
237
        private boolean addUndoableEditEvent;
238
        private boolean firstTimeItGainsFocusWithData;
239
        private boolean specialSelectionByUserState; // In this state it's possible that model couldn't match with view (the selected item)
240
        private boolean cutOperationDone;
241
        private boolean itemSelectedByMouse;
242
        // OTHER FLAGS
243
        
244
        // TRACE - DEBUG
245
        private Logger logger = Logger.getLogger(JComboBoxItemsSeekerConfigurable.class.getClass());
246
        // END TRACE - DEBUG
247
        
248
        // A POPUPMENU FOR EDITION OPTIONS
249
        private JOptionsEditionByMousePopupMenu optionsEditionByMouse;
250
    // END A POPUPMENU FOR EDITION OPTIONS
251
        
252
        // UNDO-REDO
253
        private UndoManager undoManager;
254
        private int undoRedoLimitActions;
255
        // END UNDO-REDO        
256
        
257
        /**
258
         * Default Constructor without parameters
259
         */
260
        public JComboBoxItemsSeekerConfigurable() {
261
                // Invokes to the parent class constructor                
262
                super();
263

    
264
                // Create attributes and set initial values
265
                this.initialize();
266
                
267
                // Set the default values of the flags
268
                this.setDefaultBehaviorFlagsConfiguration();
269
                
270
                // Other configuration tasks
271
                this.createDefaultListeners();
272
                this.configure();
273
        }
274
        
275
        /**
276
         * Default Constructor with 3 parameters: for the behavior of the Model
277
         * 
278
         * @param start_Behavior Start behavior of the Model.
279
         * @param search_Behavior Search behavior of the Model.
280
         * @param case_Sensitive Case sensitive behavior of the Model.
281
         */
282
        public JComboBoxItemsSeekerConfigurable(int start_Behavior, int search_Behavior, boolean case_Sensitive)        {
283
                // Invokes to the parent class constructor                
284
                super();
285
                
286
                // Set the default values of the flags
287
                this.setDefaultBehaviorFlagsConfiguration();
288
                
289
                // Create attributes and set initial values
290
                this.initialize();
291
                
292
                // Sets the options selected by the user
293
                this.model.setStartBehavior(start_Behavior);
294
                this.model.setStartBehavior(search_Behavior);
295
                this.model.setCaseSensitive_Flag(case_Sensitive);                
296
                
297
                if (!testFlagsConfigurationOK())
298
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
299
                else
300
                {
301
                        // Other configuration tasks
302
                        this.createDefaultListeners();
303
                        this.configure();
304
                }
305
        }
306

    
307
        /**
308
          * Default Constructor with 10 parameters
309
         * 
310
         * @param start_Behavior Start behavior of the Model.
311
         * @param search_Behavior Search behavior of the Model.
312
         * @param case_Sensitive Case sensitive behavior of the Model.
313
         * @param only_One_Color_On_Text Text color, behavior of the Control/View. 
314
         * @param complete_Matched_Item Complete matched item, behavior of the Control/View.
315
         * @param use_Beep Use beep, behavior of the Control.
316
         * @param allowed_Repeated_Items Allowed repeated items, behavior of the Control/Model.
317
         * @param allowed_Mouse_Edition_Popup_Menu Allowed mouse edition popupmenu, behavior of the Control/View.
318
         * @param to_Force_To_Only_Coincidences_In_The_Search To force to only coincidences in the search, behavior of the Control/View.
319
         * @param use_Highlight Use highlight, behavior of the Control/View.
320
         */
321
        public JComboBoxItemsSeekerConfigurable(int start_Behavior, int search_Behavior, boolean case_Sensitive, boolean only_One_Color_On_Text, boolean complete_Matched_Item, boolean use_Beep, boolean allowed_Repeated_Items, boolean allowed_Mouse_Edition_Popup_Menu, boolean to_Force_To_Only_Coincidences_In_The_Search, boolean use_Highlight) {
322
                // Invokes to the parent class constructor                
323
                super();
324
                
325
                this.onlyOneColorOnText_Flag = only_One_Color_On_Text;
326
                this.completeMatchedItem_Flag = complete_Matched_Item;
327
                this.beepEnabled_Flag = use_Beep;
328
                this.allowedRepeatedItems_Flag = allowed_Repeated_Items;
329
                this.allowedMouseEditionPopupMenu_Flag = allowed_Mouse_Edition_Popup_Menu;
330
                this.toForceToOnlyCoincidencesInTheSearch_Flag = to_Force_To_Only_Coincidences_In_The_Search;
331
                this.useHighlight_Flag = use_Highlight;
332

    
333
                // Create attributes and set initial values
334
                this.initialize();
335

    
336
                // Sets the options selected by the user
337
                this.model.setStartBehavior(start_Behavior);
338
                this.model.setSearchBehavior(search_Behavior);
339
                this.model.setCaseSensitive_Flag(case_Sensitive);
340
                
341
                if (!testFlagsConfigurationOK())
342
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
343
                else
344
                {
345
                        // Other configuration tasks
346
                        this.createDefaultListeners();
347
                        this.configure();
348
                }
349
        }
350

    
351
        /**
352
         *  Sets the default values of the flags
353
         */
354
        private void setDefaultBehaviorFlagsConfiguration() {
355
                this.onlyOneColorOnText_Flag = DEFAULT_ONLY_ONE_COLOR_ON_TEXT_CONFIGURATION;
356
                this.completeMatchedItem_Flag = DEFAULT_COMPLETE_MATCHED_ITEM_CONFIGURATION;
357
                this.beepEnabled_Flag = DEFAULT_BEEP_ENABLED_CONFIGURATION;
358
                this.allowedRepeatedItems_Flag = DEFAULT_ALLOWED_REPEATED_ITEMS_CONFIGURATION;
359
                this.allowedMouseEditionPopupMenu_Flag = DEFAULT_ALLOWED_MOUSE_EDITION_POPUP_MENU_CONFIGURATION;
360
                this.toForceToOnlyCoincidencesInTheSearch_Flag = DEFAULT_TO_FORCE_TO_ONLY_COINCIDENCES_IN_THE_SEARCH_CONFIGURATION;
361
                this.useHighlight_Flag = DEFAULT_USE_HIGHLIGHT_CONFIGURATION;
362
        }
363
        
364
        /**
365
         * This method set the start values of inner attributes and creates the necessary inner objects
366
         */
367
        private void initialize() {
368
                // Attributes for highlight selection
369
                selecting = false;
370
                hitBackspace = false;
371
                
372
                // Creates the model for this component and gets it reference
373
                if (this.allowedRepeatedItems_Flag)
374
                {
375
                        super.setModel(new ComboBoxItemsSeekerConfigurableModel());
376
                        this.model = (ComboBoxItemsSeekerConfigurableModel) super.getModel();
377
                }
378
                else
379
                {
380
                        super.setModel(new ComboBoxSingularItemsSeekerConfigurableModel());
381
                        this.model = (ComboBoxSingularItemsSeekerConfigurableModel) super.getModel();
382
                }
383
                
384
        // Allows user to edit on the combobox
385
                super.setEditable(true);
386
                
387
                // By default the last state of showign items was showing all the items (at the beginning of this component)
388
                currentShowState = BEGINNING_VIEW_STATE;
389
                
390
                // Set the last selected item -> if there isn't any item -> -1; else -> this will be 0
391
                super.setSelectedIndex(-1);
392
                
393
                // By default any text key has been pressed
394
                allowInsertString = false;
395
                
396
                // Attribute for allow composed characters: examples: ?, ?, ?
397
                lastWasPressedAKeyModifier = false;
398
                
399
                // By default popup won't be visible when gained the focus the editor associated
400
                popupWillBeVisible = false;
401
                
402
                // Text options edition popupmenu initialization
403
                optionsEditionByMouse = new JOptionsEditionByMousePopupMenu();
404
                optionsEditorWasVisible = false;
405
                
406
                // Undo-Redo initialization                
407
                addUndoableEditEvent = false; // By default don't add undoable edit events
408
                undoManager = new UndoManager();
409
                undoRedoLimitActions = 10; // By default is 1
410
                undoManager.setLimit(undoRedoLimitActions);
411
                
412
                // By default this flag will be 'true'
413
                firstTimeItGainsFocusWithData = true;
414
                
415
                // By default this component won't be in the "SpecialSelectionByUser" state
416
                specialSelectionByUserState = false;
417
                
418
                // By default no 'cut' operation has been done
419
                cutOperationDone = false;
420
                
421
                // By default no item items has been selected by mouse
422
                itemSelectedByMouse = false;
423
        }
424
        
425
        /**
426
         * Creation of default listeneres that will use the component
427
         */
428
        private void createDefaultListeners() {
429
                // Defines a listener for the PopupMenu of text edition options: when a change is produced in that component, it fires an event
430
                //   and this listener captures it
431
                this.defineEditionMenuPropertyChangeListener(this);
432
                
433
        // Defines a key listener for the editor of this component
434
        this.defineEditorKeyListener(this);
435
         
436
        // Defines a focus listener for the editor of this component
437
        this.defineEditorFocusListener(this);
438
        
439
        // Defines a mouse listener for the editor of this component
440
        this.defineEditorMouseListener(this);
441
        
442
        // Defines a mouse wheel listener for the editor of this component
443
        this.defineEditorMouseWheelListener();
444
        
445
        // Defines a document listener for changes of text
446
        this.defineDocumentListener();
447
         
448
                // Defines a list data listener for the model of this component
449
        this.defineModelListDataListener();
450
        
451
        // Defines a popup menu listener for the popup of this component
452
        this.definePopUpMenuListener();
453
        }
454
        
455

    
456
        /**
457
         * Defines a listener for the PopupMenu of text edition options: when a change is produced in that component, it fires an event
458
         *    and this listener captures and treats it
459
         *    
460
         * @param combo_Box A reference of this component
461
         */
462
        private void defineEditionMenuPropertyChangeListener(JComboBoxItemsSeekerConfigurable combo_Box) {
463
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
464
                
465
                editionMenuListener = new PropertyChangeListener() {
466
                        /*
467
                         * (non-Javadoc)
468
                         * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
469
                         */
470
                        public void propertyChange(PropertyChangeEvent arg0) {
471
                                if (arg0.getPropertyName().equals(JOptionsEditionByMousePopupMenu.SELECTEDOPTION)) {
472
                            JTextComponent editor = (JTextComponent) comboBoxReference.getEditor().getEditorComponent();
473
                
474
                            logger.debug("PropertyChanged: " + arg0.getNewValue().toString());
475
                                        
476
                                  switch(Integer.parseInt(arg0.getNewValue().toString()))
477
                                  {
478
                                          case JOptionsEditionByMousePopupMenu.UNDO:
479
                                                  undoOperationLogic();
480
                                                  break;
481
                                          case JOptionsEditionByMousePopupMenu.REDO:
482
                                                  redoOperationLogic();
483
                                                  break;
484
                                          case JOptionsEditionByMousePopupMenu.CUT:
485
                                                  editor.cut();
486
                                                  cutOperationDone = true;
487
                                                  deleteTextLogic(editor, false);
488
                                                  break;
489
                                          case JOptionsEditionByMousePopupMenu.COPY:
490
                                                  editor.copy();
491
                                                  break;
492
                                          case JOptionsEditionByMousePopupMenu.PASTE:
493
                                                  editor.paste();
494
                                                  
495
                                                  try {
496
                                                          String newPattern = document.getText(0, document.getLength());
497
                                                          model.setWrittenText(newPattern);
498
                                                          updatePopUpView();
499
                                                  } catch (BadLocationException e) {
500
                                                          e.printStackTrace();
501
                                                  }
502
                                                  break;
503
                                          case JOptionsEditionByMousePopupMenu.DELETE:
504
                                                  deleteTextLogic(editor, false);
505
                                                  break;
506
                                          case JOptionsEditionByMousePopupMenu.SELECT_ALL:
507
                                                  editor.selectAll();
508
                                                  break;
509
                                          default: // do anything
510
                                  }
511
                                }
512
                                else
513
                                {
514
                                        if (arg0.getPropertyName().equals(JOptionsEditionByMousePopupMenu.VISIBILITYCHANGED))
515
                                        {
516
                                                logger.debug("PropertyChanged: " + arg0.getNewValue().toString());
517
                                                
518
                                                // First True, after False (when false -> optionsEditorWasVisible = true)
519
                                                if (!optionsEditionByMouse.isVisible())
520
                                                        optionsEditorWasVisible = true;
521
                                                else
522
                                                        optionsEditorWasVisible = false;
523
                                        }
524
                                }
525
                        }                        
526
                };
527
        }        
528
        
529
        /**
530
         *  Defines a document listener for changes of text
531
         */
532
        private void defineDocumentListener() {
533
       documentListener = new DocumentListener() {
534
               /*
535
                * (non-Javadoc)
536
                * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
537
                */
538
               public void changedUpdate(DocumentEvent arg0) {
539
               }
540

    
541
               /*
542
                * (non-Javadoc)
543
                * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
544
                */
545
               public void insertUpdate(DocumentEvent arg0) {
546
                       logger.debug("NUM: " + num + " DocumentListener->insertUpdate");
547
                       num++;                                
548
                                
549
                       // Indicate to the model that now is disabled the start view
550
                       // This is used for the first text inserted to the document when the component is loaded and it does setSelectedIndex(0), to avoid use a search view
551
                       if (currentShowState == BEGINNING_VIEW_STATE)
552
                       {
553
                               currentShowState = START_VIEW_STATE;
554
                               lastWasTheBeginningState = true;
555
                               logger.debug("Pasa al estado 1 (de vista inicial)");
556
                       }        
557
               }
558

    
559
               /*
560
                * (non-Javadoc)
561
                * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
562
                */
563
               public void removeUpdate(DocumentEvent arg0) {
564
                       logger.debug("NUM: " + num + " DocumentListener->removeUpdate");
565
                       num++;
566
               }                        
567
       };
568
        }        
569
        
570
        /**
571
         * Defines a list data listener for the model of this component
572
         */
573
        private void defineModelListDataListener() {                
574
                this.modelListDataListener = new ListDataListener()        {
575
                        /*
576
                         * (non-Javadoc)
577
                         * @see javax.swing.event.ListDataListener#contentsChanged(javax.swing.event.ListDataEvent)
578
                         */
579
                        public void contentsChanged(ListDataEvent e) {
580
                                // This flag indicates to the 'insertString' and 'remove' methods of the PlainDocumentSeeker that the text of the item selected or written by the user
581
                                //  hasn't been written on the TextEditor of ths component
582
                                selecting = false;
583
                        }
584

    
585
                        /*
586
                         * (non-Javadoc)
587
                         * @see javax.swing.event.ListDataListener#intervalAdded(javax.swing.event.ListDataEvent)
588
                         */
589
                        public void intervalAdded(ListDataEvent e) {
590
                        }
591

    
592
                        /*
593
                         * (non-Javadoc)
594
                         * @see javax.swing.event.ListDataListener#intervalRemoved(javax.swing.event.ListDataEvent)
595
                         */
596
                        public void intervalRemoved(ListDataEvent e) {
597
                        }                        
598
                };
599
    }
600

    
601
        /**
602
         * Defines and add a property change listener for this component (AT MOMENT NOT USED!!)
603
         */
604
        private void defineAndAddPropertyChangeListener() {
605
                // Define and add a Listener for changes on the editor or the model of the JComboBox
606
        super.addPropertyChangeListener(new PropertyChangeListener() {
607
            public void propertyChange(PropertyChangeEvent ev) {
608
                if (ev.getPropertyName().equals("editor"))
609
                        configureEditor((ComboBoxEditor) ev.getNewValue());
610
                if (ev.getPropertyName().equals("model"))
611
                {
612
                        if (isAllowedRepeatedItems_Flag())
613
                                model = (ComboBoxItemsSeekerConfigurableModel) ev.getNewValue();
614
                        else
615
                                model = (ComboBoxSingularItemsSeekerConfigurableModel) ev.getNewValue();
616
                }
617
            }
618
        });
619
        }
620

    
621
        /**
622
         * Defines a focus listener for the editor of this component
623
         * 
624
         * @param combo_Box A reference of this component
625
         */
626
        private void defineEditorFocusListener(JComboBoxItemsSeekerConfigurable combo_Box) {
627
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
628
                
629
                // Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out                
630
                hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
631

    
632
                // Highlight whole text when gaining focus
633
                editorFocusListener = new FocusAdapter() {
634
                        /*
635
                         * (non-Javadoc)
636
                         * @see java.awt.event.FocusAdapter#focusGained(java.awt.event.FocusEvent)
637
                         */
638
                        public void focusGained(FocusEvent e) {
639
                                if (!optionsEditorWasVisible)
640
                                {
641
                                        logger.debug("currentShowState: " + currentShowState);
642
                                        logger.debug("EDITOR FOCUS GAINED");
643
                                        
644
                                        // This is used for set the text value of the first item added highlighted the first time the component gets the focus 
645
                                        if (firstTimeItGainsFocusWithData) {
646
                                                if (model.getSize() > 0) {
647
                                                        if (useHighlight_Flag)
648
                                                                document.highlightCompletedText(0);
649
                                                        firstTimeItGainsFocusWithData = false;
650
                                                }
651
                                        }
652
                                        
653
                                        // This is used when the component has lost the focus, the popup was in show state and is restored the focus -> update the popup
654
                                        if (popupWillBeVisible)
655
                                        {
656
                                                logger.debug("UPDATE POPUP DESDE EL FOCUSGAINED");
657
                                                comboBoxReference.updatePopUpView();
658
                                        }
659
                                }
660
                        }
661
                        
662
                        /*
663
                         * (non-Javadoc)
664
                         * @see java.awt.event.FocusAdapter#focusLost(java.awt.event.FocusEvent)
665
                         */
666
                        public void focusLost(FocusEvent e) {
667
                                logger.debug("EDITOR FOCUS LOST");
668
                                
669
                                if (isPopupVisible())
670
                                        popupWillBeVisible = true;
671
                                else
672
                                        popupWillBeVisible = false;
673
                                
674
                                // Workaround for Bug 5100422 - Hide Popup on focus loss
675
                                if (hidePopupOnFocusLoss) comboBoxReference.setPopupVisible(false);
676
                        }
677
                };
678
        }
679

    
680
        /**
681
         * Defines a mouse listener for the editor of this component
682
         * 
683
         * @param combo_Box A reference of this component
684
         */
685
        private void defineEditorMouseListener(JComboBoxItemsSeekerConfigurable combo_Box) {
686
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
687
                
688
                editorMouseListener = new MouseAdapter() {
689
                        /*
690
                         * (non-Javadoc)
691
                         * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent)
692
                         */
693
                        public void mouseClicked(MouseEvent e) {
694
                                logger.debug("MOUSE-LISTENER : MOUSE-mouseClicked!" + e.getButton());
695
                                logger.debug("MOUSE-LISTENER : MOUSE-mouseClicked!" +e.isPopupTrigger());
696
        
697
                                if (e.getButton() == MouseEvent.BUTTON3) {
698
                            JTextComponent editor = (JTextComponent) comboBoxReference.getEditor().getEditorComponent();
699
                            
700
                            // By default disable all options
701
                            optionsEditionByMouse.setEnabledAllOptions(false);
702
                            
703
                            // Enable the "Undo" option if there is any previous state to restore
704
                            if (undoManager.canUndo())
705
                                    optionsEditionByMouse.setEnabledUndoOption(true);
706
                            
707
                            // Enable the "Redo" option if there is any later state to restore
708
                            if (undoManager.canRedo())
709
                                    optionsEditionByMouse.setEnabledRedoOption(true);
710
                            
711
                            // Enable the "Copy", "Cut" and "Delete" options if there is text selected
712
                            if (editor.getCaretPosition() != editor.getCaret().getMark())
713
                            {
714
                                    optionsEditionByMouse.setEnabledCopyOption(true);
715
                                    optionsEditionByMouse.setEnabledCutOption(true);
716
                                    optionsEditionByMouse.setEnabledDeleteOption(true);
717
                            }
718
                            
719
                            // Enable the "Paste" option if there is text on the system's clipboard
720
                            if ( getToolkit().getSystemClipboard().getContents(this).toString().length() > 0 )
721
                                    optionsEditionByMouse.setEnabledPasteOption(true);
722
                            
723
                            // Enable the "Select-All" option (by default it's always enabled)
724
                            optionsEditionByMouse.setEnabledSelectAllOption(true);
725
                            
726
                                        optionsEditionByMouse.setLocation((int)comboBoxReference.getLocationOnScreen().getX() + e.getX(), (int)comboBoxReference.getLocationOnScreen().getY() + e.getY());
727
                            optionsEditionByMouse.setInvoker(comboBoxReference);
728
                            optionsEditionByMouse.setVisible(true);
729
                    }
730
                }
731
                };
732
        }
733

    
734
        /**
735
         * Defines a mouse wheel listener for the editor of this component
736
         */
737
        private void defineEditorMouseWheelListener() {
738
                editorMouseWheelListener = new MouseWheelListener() {
739
                        /*
740
                         * (non-Javadoc)
741
                         * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
742
                         */
743
                        public void mouseWheelMoved(MouseWheelEvent e) {
744
                                specialSelectionByUserState = true;
745
                                
746
                        if (e.getWheelRotation() < 0)
747
                                selectItemUp();
748
                        else
749
                                selectItemDown();
750
                        }
751
                };
752
        }
753

    
754
        /**
755
         * Defines a key listener for the editor of this component
756
         * This method is another important difference from the JComboBox; and could work badly with some keymaps
757
         * 
758
         * @param combo_Box A reference of this component
759
         */
760
        private void defineEditorKeyListener(JComboBoxItemsSeekerConfigurable combo_Box) {
761
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
762
                
763
                editorKeyListener = new KeyAdapter() {
764
                        /*
765
                         * (non-Javadoc)
766
                         * @see java.awt.event.KeyAdapter#keyPressed(java.awt.event.KeyEvent)
767
                         */
768
                        public void keyPressed(KeyEvent ke)  // Executed on the Start view state or Search view state
769
                        {
770
                                logger.debug("Tecla apretada: ->" + ke.getKeyChar() + "<- ; Su keyCode es: " + ke.getKeyCode() + " TIPO: " + Character.getType(ke.getKeyChar()));
771
                                
772
                                if (model.getParentSize() == 0)
773
                                {
774
                                        if (beepEnabled_Flag)
775
                                                comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
776
                                }
777
                                else
778
                                {                                                                
779
                                        // This flag indicates to the 'insertString' and 'remove' methods of the PlainDocumentSeeker that the text of the item selected or written by the user
780
                                        //  hasn't been written on the TextEditor of ths component
781
                                        selecting = false;
782
                                        
783
                                        // This resolves the bug when the popup wasn't seen any time and the uses press a key that updates the view of the popup (the bug is that popup has the items but
784
                                        //  aren't seen
785
                                        if (lastWasTheBeginningState)
786
                                        {
787
                                                // This maintains visible the popup
788
                                                if (comboBoxReference.isDisplayable())
789
                                                        comboBoxReference.setPopupVisible(true);
790
                                                lastWasTheBeginningState = false;
791
                                        }
792
                                        
793
                                        if (Character.isLetterOrDigit(ke.getKeyChar())) {
794
                                                logger.debug("IS LETTER OR DIGIT");
795
                                        }
796
                                        else
797
                                                logger.debug("ISN'T LETTER OR DIGIT");
798
                                        
799
                                        JTextComponent editor = (JTextComponent) comboBoxReference.getEditor().getEditorComponent();
800
                                        
801
                                        // COPY, CUT, PASTE, SELECT ALL, UNDO AND REDO WITH THE KEYBOARD (Combination of keys; REMOVE is implemented after: KV_DELETE (supr spanish key))
802
                                        if (ke.isControlDown())
803
                                        {
804
                                                // COPY
805
                                            if (ke.getKeyCode() == KeyEvent.VK_C) {
806
                                                editor.copy();
807
                                                    return;
808
                                            }
809
                                            
810
                                            // CUT
811
                                            if (ke.getKeyCode() == KeyEvent.VK_X) {
812
                                                      editor.cut();
813
                                                      
814
                                                  cutOperationDone = true;
815
                                                  deleteTextLogic(editor, false);                                                
816
                                                    return;
817
                                            }
818
                                            
819
                                            // PASTE
820
                                            if (ke.getKeyCode() == KeyEvent.VK_V) {
821
                                                    editor.paste();
822
                                          
823
                                          try {
824
                                                  String newPattern = document.getText(0, document.getLength());
825
                                                  model.setWrittenText(newPattern);
826
                                                  updatePopUpView();
827
                                          } catch (BadLocationException e) {
828
                                                  e.printStackTrace();
829
                                          }
830
                                                    return;
831
                                            }
832
                                            
833
                                            // SELECT ALL
834
                                            if (ke.getKeyCode() == KeyEvent.VK_A) {
835
                                                    editor.selectAll();
836
                                                    return;
837
                                            }
838

    
839
                                            // UNDO OR REDO
840
                                            if (ke.getKeyCode() == KeyEvent.VK_Z) {
841
                                                    if (ke.isShiftDown()) // REDO
842
                                                            redoOperationLogic();                                                            
843
                                                    else //UNDO
844
                                                            undoOperationLogic();
845
                                                    
846
                                                    return;
847
                                             }
848
                                        }
849
                                        
850
                                        // According the key pressed, do some actions or others
851
                                        switch (ke.getKeyCode())
852
                                        {
853
                                                // determine if the pressed key is backspace (needed by the remove method)
854
                                                case KeyEvent.VK_BACK_SPACE :
855
                                                                 if (useHighlight_Flag)
856
                                                                {
857
                                                                         hitBackspace = true;
858
                                                                         hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
859
                                                                }
860
                                                                 else
861
                                                                         deleteTextLogic(editor, true);
862
                                                        break;
863
                                                        
864
                                                case KeyEvent.VK_DELETE : // 'supr' key in spanish keyboard
865
                                                                specialSelectionByUserState = true;
866
                                                        
867
                                                        deleteTextLogic(editor, false);
868
                                                        break;
869
                                                        
870
                                                case KeyEvent.VK_ENTER :
871
                                                        logger.debug("ENTRA EN EL C?DIGO DE ENTER");
872
        
873
                                                        if (getSelectedItem() == null)
874
                                                                logger.debug("SELECTED ITEM: NULL");
875
                                                        else
876
                                                                logger.debug("SELECTED ITEM: " + getSelectedItem().toString());
877

    
878
                                                        try {
879
                                                                String newText = "";
880
                                                                
881
                                                                Object moreSimilarItemToLastWrittenText = model.getMoreSimilarItemToLastWrittenText();
882

    
883
                                                                // If the last item selected was null -> select the first
884
                                                                if (moreSimilarItemToLastWrittenText == null) {
885
                                                                        setSelectedItem(model.getParentElementAt(0));
886
                                                                }
887
                                                                else {
888
                                                                        if (specialSelectionByUserState) {
889
                                                                                setSelectedItem(model.getSelectedItem());
890
                                                                        }
891
                                                                        else {
892
                                                                                // Else -> select the last
893
                                                                                setSelectedItem(moreSimilarItemToLastWrittenText);
894
                                                                        }
895
                                                                }
896
                                                                
897
                                                                newText = getSelectedItem().toString();
898
                                                                
899
                                                                // Reports about the written text to the model
900
                                                            if (model.isDynamicSearch())
901
                                                                    model.setWrittenText(newText);                                                            
902
                                                                
903
                                                                specialSelectionByUserState = false;
904
                                                                
905
                                                                document.replace(0, document.getLength(), newText, null);
906
                                                        }
907
                                                        catch (BadLocationException e1) {
908
                                                            e1.printStackTrace();
909
                                                    }
910
                                                        
911
                                                    // Indicate to the model that now is disabled the start view
912
                                                        if (currentShowState == START_VIEW_STATE)
913
                                                        {
914
                                                                model.setStartStateFlag(false);
915
                                                                currentShowState = SEARCH_VIEW_STATE;
916
                                                        }
917
                                                        hidePopup();
918
                                                        
919
                                                        // Sets the caret position of the text in the document to the end:
920
                                                        editor.setCaretPosition(document.getLength());
921
                                                        break;
922
                                                        
923
                                                case KeyEvent.VK_DOWN :                                                                
924
                                                        selectItemDown();
925
                                                        showPopup();
926
                                                        break;
927
                                                        
928
                                                case KeyEvent.VK_UP :
929
                                                        selectItemUp();
930
                                                        showPopup();
931
                                                        break;
932
                                                        
933
                                                case KeyEvent.VK_LEFT :                                                
934
                                                        // Move the caret to left
935
                                                        int caretPosition = editor.getCaretPosition();
936
                                                        if (caretPosition > 0)
937
                                                        {
938
                                                                if (useHighlight_Flag) {
939
                                                                        editor.setCaretPosition(document.getLength());
940
                                                                        editor.moveCaretPosition(caretPosition - 1);
941
                                                                }
942
                                                                else
943
                                                                        editor.setCaretPosition(caretPosition - 1);
944
                                                        }
945
                                                        else
946
                                                        {
947
                                                // User hit backspace with the cursor positioned on the start => beep
948
                                                    if (beepEnabled_Flag)
949
                                                            getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
950
                                                        }
951
                                                        
952
                                                        break;
953
                                                        
954
                                                case  KeyEvent.VK_RIGHT :
955
                                                        // Move the caret to right
956
                                                        caretPosition = editor.getCaretPosition();
957
                                                        if (caretPosition < document.getLength()) {
958
                                                                if (useHighlight_Flag) {
959
                                                                        editor.setCaretPosition(document.getLength());
960
                                                                        editor.moveCaretPosition(caretPosition + 1);
961
                                                                }
962
                                                                else
963
                                                                        editor.setCaretPosition(caretPosition + 1);
964
                                                        }
965
                                                        else
966
                                                        {
967
                                                            // User hit backspace with the cursor positioned on the start => beep
968
                                                                if (beepEnabled_Flag)
969
                                                                        getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
970
                                                        }
971
                                                        
972
                                                        break;
973
                                                        
974
                                                case  KeyEvent.VK_PAGE_DOWN :
975
                                                        if (getItemCount() > 0)
976
                                                        {                                                                
977
                                                                int index;
978
                                                                specialSelectionByUserState = true;                                                                
979
                                                                
980
                                                                if (getSelectedIndex() == -1)
981
                                                                        index = 0;
982
                                                                else
983
                                                                        index = getSelectedIndex() + POPUP_LIST_ITEMS_HEIGHT;
984
                                                                
985
                                                                if (index < getItemCount())
986
                                                                        setSelectedIndex(index);
987
                                                                else
988
                                                                        setSelectedIndex(getItemCount()-1);
989
                                                        }
990
                                                        break;
991
                                                        
992
                                                case KeyEvent.VK_PAGE_UP :
993
                                                        if (getItemCount() > 0)
994
                                                        {
995
                                                                int index;
996
                                                                specialSelectionByUserState = true;
997
                                                                
998
                                                                if (getSelectedIndex() == -1)
999
                                                                        index = getItemCount() - 1;
1000
                                                                else
1001
                                                                        index = getSelectedIndex() - POPUP_LIST_ITEMS_HEIGHT;
1002
                                                                
1003
                                                                if (index > -1)
1004
                                                                        setSelectedIndex(index);
1005
                                                                else
1006
                                                                        setSelectedIndex(0);
1007
                                                        }
1008
                                                        break;
1009
                                                        
1010
                                                case KeyEvent.VK_HOME : // 'Inicio' key on the spanish keyboard
1011
                                                        editor.setCaretPosition(0);
1012
                                                        break;
1013
                                                        
1014
                                                case KeyEvent.VK_END :  // 'Fin' key on the spanish keyboard
1015
                                                        editor.setCaretPosition(document.getLength());
1016
                                                        break;
1017
                                                        
1018
                                                case KeyEvent.VK_TAB :
1019
                                                        // This avoids that popup listener could report about it detected item
1020
                                                        allowInsertString = true;
1021
                                                        
1022
                                                        if (model.getParentSize() > 0)
1023
                                                        {                                                                
1024
                                                                Object selectedItem;
1025
                                                                
1026
                                                                if (specialSelectionByUserState)
1027
                                                                        selectedItem = getSelectedItem();
1028
                                                                else
1029
                                                                        selectedItem = model.getElementAt(0);
1030
                                                                
1031
                                                                String selectedItemName = "";
1032
                                                                
1033
                                                                try {
1034
                                                                        
1035
                                                                        if (selectedItem == null)
1036
                                                                                selectedItemName = model.getFirstItemAdded().toString();
1037
                                                                        else
1038
                                                                                selectedItemName = selectedItem.toString();
1039
                                                                                
1040
                                                                                document.replace(0, document.getLength(), selectedItemName, null);
1041
                                                                } catch (BadLocationException e) {
1042
                                                                        e.printStackTrace();
1043
                                                                }
1044
                                                                
1045
                                                                if (model.isDynamicSearch()) {
1046
                                                                        model.setWrittenText(selectedItemName);
1047
                                                                        logger.debug("Texto que se le env?a al modelo: ->" + selectedItemName + "<-");
1048
                                                                }                
1049
                                                                                
1050
                                                                if (currentShowState == START_VIEW_STATE)
1051
                                                                {
1052
                                                                        model.setStartStateFlag(false);
1053
                                                                        currentShowState = SEARCH_VIEW_STATE;
1054
                                                                }
1055
                                                                
1056
                                                                // It's supposed that the text on the document is equal as the string value of the selected item -> then text must be on black color
1057
                                                                comboBoxReference.getEditor().getEditorComponent().setForeground(Color.BLACK);
1058

    
1059
                                                                updatePopUpView();
1060
                                                        }
1061
                                                        break;
1062
                                                        
1063
                                                case KeyEvent.VK_ESCAPE :
1064
                                                        specialSelectionByUserState = false;
1065
                                                        
1066
                                                        // Force update the popup
1067
                                                        if (isPopupVisible())
1068
                                                                hidePopup();
1069
        
1070
                                                        model.setWrittenText("");
1071
                                                        
1072
                                                        if (currentShowState == SEARCH_VIEW_STATE)
1073
                                                        {        
1074
                                                                try {
1075
                                                                        document.remove(0, document.getLength());
1076
                                                                } catch (BadLocationException e) {
1077
                                                                        e.printStackTrace();
1078
                                                                }
1079
                                                                
1080
                                                                // Return to the start view state
1081
                                                                model.setStartStateFlag(true);
1082
                                                                currentShowState = START_VIEW_STATE;
1083

    
1084
                                                                // Select the first Item
1085
                                                                setSelectedIndex(0);
1086
                                                                
1087
                                                                if (useHighlight_Flag)
1088
                                                                        document.highlightCompletedText(0);
1089
                                                        }
1090
                                                        else
1091
                                                        {
1092
                                                                // Select the first Item
1093
                                                                setSelectedIndex(0);
1094
                                                                
1095
                                                                if (useHighlight_Flag)
1096
                                                                        document.highlightCompletedText(0);
1097
                                                        }
1098
                                                        updatePopUpView();                                                        
1099
                                                        break;
1100
                                                        
1101
                                                case KeyEvent.VK_SHIFT : // Do nothing
1102
                                                        break;
1103
                                                        
1104
                                                case KeyEvent.VK_ALT_GRAPH : // Do nothing
1105
                                                        break;
1106
                                                        
1107
                                                case KeyEvent.VK_ALT : // Do nothing                        
1108
                                                        break;
1109
                                                        
1110
                                                case KeyEvent.VK_CONTROL : // Do nothing
1111
                                                        break;
1112
                                                        
1113
                                                case KeyEvent.VK_NUM_LOCK : // Do nothing
1114
                                                        break;
1115
                                                        
1116
                                                case KeyEvent.VK_CAPS_LOCK : // Do nothing
1117
                                                        break;
1118
                                                        
1119
                                                default:
1120
                                                        logger.debug("Actualiza view flag a false");
1121
                                                                                                
1122
                                                        logger.debug("LASTITEM1 :" + lastSelectedItemPopupUse);
1123
        
1124
                                                        logger.debug("GETMARK: " + editor.getCaret().getMark() + "GETCARETPOSITION" + editor.getCaretPosition());
1125

    
1126
                                                        specialSelectionByUserState = false;
1127
                                                        
1128
                                                        // If it has been pressed a modifier key (Examples: ^ ` ? ?), not consume the key pressed
1129
                                                        if ((Character.getType(ke.getKeyChar()) == Character.MODIFIER_LETTER) || (Character.getType(ke.getKeyChar()) == Character.MODIFIER_SYMBOL))
1130
                                                        {
1131
                                                                logger.debug("CAR?CTER MODIFICADOR");
1132
                                                                lastWasPressedAKeyModifier = true;
1133
                                                        }
1134
                                                        else
1135
                                                        {
1136
                                                                logger.debug("CAR?CTER NO MODIFICADOR");
1137
                                                                allowInsertString = true;
1138

    
1139
                                                        if (lastWasPressedAKeyModifier)
1140
                                                        {
1141
                                                                logger.debug("PRESSED: " + editor.getText().substring(0));
1142
                                                                lastWasPressedAKeyModifier = false;
1143
                                                        }
1144
                                                        
1145
                                                        if (model.isDynamicSearch())
1146
                                                        {
1147
                                                                
1148
                                                                String text;
1149
                                                                if (editor.getCaretPosition() == editor.getCaret().getMark())
1150
                                                                        text = editor.getText().substring(0, editor.getCaretPosition()) + ke.getKeyChar() + editor.getText().substring(editor.getCaretPosition(), editor.getText().length());
1151
                                                                else
1152
                                                                {
1153
                                                                        text = "" + editor.getText().substring(0, (int) Math.min(editor.getCaretPosition(), editor.getCaret().getMark())) + ke.getKeyChar();
1154
                                                                        text += editor.getText().substring((int) Math.max(editor.getCaretPosition(), editor.getCaret().getMark()), editor.getText().length());
1155
                                                                }
1156
                                                                
1157
                                                                    // Reports about the written text to the model                                                
1158
                                                                           logger.debug("Texto que se le env?a KEY al modelo: ->" + text + "<-");
1159
                                                                    model.setWrittenText(text);        
1160
                                                                    
1161
                                                                    // Indicate to the model that now is disabled the start view
1162
                                                                    if (currentShowState == START_VIEW_STATE)
1163
                                                                    {
1164
                                                                            model.setStartStateFlag(false);
1165
                                                                            currentShowState = SEARCH_VIEW_STATE;
1166
                                                                    }
1167
                                                                    
1168
                                                        }
1169
        
1170
                                                updatePopUpView();
1171
                                                        
1172
                                                        logger.debug("Key Pressed:" + ke.getKeyCode());
1173
                                                }
1174
                                        }
1175
                                        
1176
                                        // Consume the key event for not to use the handler of the keyboard of other components
1177
                                        // Only if it has been pressed a modifier key, not consume the key pressed
1178
                                        if (!lastWasPressedAKeyModifier)
1179
                                                ke.consume();
1180
                    }
1181
                        }
1182
                };
1183
        }
1184
        
1185
        /**
1186
         * Defines a popup menu listener for the popup of this component
1187
         */
1188
        private void definePopUpMenuListener() {                                
1189
                        this.popupMenuListener = new PopupMenuListener() {
1190

    
1191
                        /*
1192
                         *  (non-Javadoc)
1193
                         * @see javax.swing.event.PopupMenuListener#popupMenuCanceled(javax.swing.event.PopupMenuEvent)
1194
                         */
1195
                        public void popupMenuCanceled(PopupMenuEvent e) {
1196
                                logger.debug("MenuCANCELED");
1197
                        }
1198

    
1199
                        /*
1200
                         *  (non-Javadoc)
1201
                         * @see javax.swing.event.PopupMenuListener#popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent)
1202
                         */
1203
                        public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
1204
                                logger.debug("MenuBECOMEINVISIBLE");
1205

    
1206
                                if (!allowInsertString)
1207
                                {
1208
                                        if (!specialSelectionByUserState) {
1209
                                                if ((getSelectedItem() != null) &&(lastSelectedItemPopupUse != null))
1210
                                                {
1211
                                                // If the user has select a different item with the mouse, and this is in the Start View State -> change to the Search View State 
1212
                                                        if (!getSelectedItem().equals(lastSelectedItemPopupUse))
1213
                                                        {
1214
                                                                logger.debug("POPUP: NO SON IGUALES");
1215
                                                                
1216
                                                                // Reports about the written text to the model
1217
                                                                if (model.isDynamicSearch())
1218
                                                                {
1219
                                                                        model.setWrittenText(getSelectedItem().toString());
1220
                                                                        logger.debug("Texto que le envia POPUP al modelo: ->" + getSelectedItem().toString() + "<-");
1221
                                                                }
1222
                                                                        
1223
                                                                if (currentShowState == START_VIEW_STATE)
1224
                                                                {
1225
                                                                        model.setStartStateFlag(false);
1226
                                                                        currentShowState = SEARCH_VIEW_STATE;
1227
                                                                }
1228
                                                                logger.debug("Selected index of item: " + lastSelectedItemPopupUse.toString() + " is " + getSelectedIndex());
1229
                                                        }
1230
                                                        else
1231
                                                                logger.debug("POPUP: SON IGUALES");
1232
                                                }
1233
                                        }
1234
                                }
1235
                        }
1236

    
1237
                        /*
1238
                         *  (non-Javadoc)
1239
                         * @see javax.swing.event.PopupMenuListener#popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent)
1240
                         */
1241
                        public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
1242
                                logger.debug("MenuBECOMEVISIBLE");
1243
                                lastSelectedItemPopupUse = getSelectedItem(); // This object is used for know if the user has select a different item with the mouse
1244
                                allowInsertString = false;
1245
                        }                        
1246
                };
1247
        }
1248

    
1249
        /**
1250
         * Configures the component and some of its parts
1251
         */
1252
        private void configure() {
1253
                // Configures the document of the editor of this component
1254
                this.configureDocument();
1255
                
1256
                // Configures the editor (ComboBoxEditor) of this component
1257
                this.configureEditor(this.getEditor());
1258
                
1259
                // Configures the model of this component
1260
                this.configureModel();
1261
                
1262
                // Configures the popup of this component
1263
                this.configurePopUp();
1264
                
1265
                // Configures the text-edition-options popupmenu
1266
                this.configureOptionsEditionByMouse();
1267
        }
1268
        
1269
        /** 
1270
         * Configures the text-edition-options popupmenu
1271
         */
1272
        private void configureOptionsEditionByMouse() {
1273
                this.optionsEditionByMouse.addPropertyChangeListener(editionMenuListener);
1274
        }
1275
        
1276
        /**
1277
         * Configures the popup of this component
1278
         */
1279
        private void configurePopUp() {
1280
                this.addPopupMenuListener(this.popupMenuListener);
1281
        }
1282

    
1283
        /**
1284
         * Configures the model of this component
1285
         */
1286
        private void configureModel() {
1287
                this.model.addListDataListener(this.modelListDataListener);
1288
        }
1289
        
1290
        /**
1291
         * Configures the editor (ComboBoxEditor) of this component
1292
         * 
1293
         * @param newEditor The new editor to configure
1294
         */
1295
        private void configureEditor(ComboBoxEditor newEditor) {
1296
            logger.debug("Configura Editor");
1297
            
1298
        if (newEditor != null) {
1299
                   JTextComponent jTextComponentOfEditor = (JTextComponent) newEditor.getEditorComponent();
1300
                   
1301
                   // Removes some prevous listeners and adds some new others:                
1302
                   
1303
                // Adds the new Key Listener (tries to remove it if it existed before)
1304
                   jTextComponentOfEditor.removeKeyListener(this.editorKeyListener);
1305
                jTextComponentOfEditor.addKeyListener(this.editorKeyListener);
1306

    
1307
            // Disable the focus transversal keys (Example: CTRL+TAB) for enable the TAB key
1308
                jTextComponentOfEditor.setFocusTraversalKeysEnabled(false);
1309
                
1310
            if (this.allowedMouseEditionPopupMenu_Flag)
1311
            {
1312
                        // Adds the new Mouse Listener (tries to remove it if it existed before)
1313
                    jTextComponentOfEditor.removeMouseListener(this.editorMouseListener);
1314
                        jTextComponentOfEditor.addMouseListener(this.editorMouseListener);
1315
            }
1316
             
1317
                // Adds the new Mouse Wheel Listener (tries to remove it if it existed before)
1318
            jTextComponentOfEditor.removeMouseWheelListener(this.editorMouseWheelListener);
1319
                jTextComponentOfEditor.addMouseWheelListener(this.editorMouseWheelListener);
1320
           
1321
                // Adds the new Focus Listener (tries to remove it if it existed before)
1322
                jTextComponentOfEditor.removeFocusListener(this.editorFocusListener);
1323
                jTextComponentOfEditor.addFocusListener(this.editorFocusListener);
1324
 
1325
                   // Adds a caret listener for undo and redo
1326
                jTextComponentOfEditor.addCaretListener(this.caretListener);
1327
                
1328
                // Adds the new document (tries to remove it if it existed before)
1329
                jTextComponentOfEditor.setDocument(this.document);
1330
        }
1331
        }
1332

    
1333
        /**
1334
         * Configures the document of the editor of this component
1335
         */
1336
        private void configureDocument() {
1337
                // Creates the document of the editor of this component
1338
        document = new PlainDocumentTextFormatter();
1339
        document.setJComboBoxItemsSeekerDynamicReference(this);
1340
        
1341
                // Defines and add a Document listener for changes on the document of the editor of this component
1342
                document.addDocumentListener(this.documentListener);
1343
        }
1344
        
1345
        /** 
1346
         * Selects the next item of the popup
1347
         */
1348
        private void selectItemDown() {
1349
                specialSelectionByUserState = true;
1350
                
1351
                if (getItemCount() > 0)
1352
                {
1353
                        if (getSelectedIndex() == (getItemCount()-1))
1354
                                this.setSelectedIndex(0);
1355
                        else
1356
                                this.setSelectedIndex(getSelectedIndex()+1);
1357
                }
1358
        }
1359
        
1360
        /**
1361
         * Selects the previous item of the popup
1362
         */
1363
        private void selectItemUp() {
1364
                specialSelectionByUserState = true;
1365
                
1366
                switch(getSelectedIndex())
1367
                {
1368
                        case -1: case 0:
1369
                                this.setSelectedIndex(getItemCount()-1);
1370
                                break;
1371
                        default:
1372
                                this.setSelectedIndex(getSelectedIndex()-1);
1373
                }
1374
        }
1375
        
1376
        /**
1377
         * This method is invoked when some text has to be removed: With the 'Delete' option of the text-edition-popupmenu or with the 'delete' ('supr'
1378
         *    in spanish keyboard) key
1379
         * 
1380
         * @param editor A reference to the editor component
1381
         */
1382
        private void deleteTextLogic(JTextComponent editor, boolean backSpace_Delete_Mode) {
1383
                // Remove selected text:
1384
                logger.debug("GETMARK: " + editor.getCaret().getMark() + "GETCARETPOSITION" + editor.getCaretPosition());
1385
                int caretPosition = editor.getCaretPosition();
1386
                int markPosition = editor.getCaret().getMark();        
1387
                specialSelectionByUserState = false;
1388
                
1389
                // Get the new text:                
1390
                try {
1391
                        
1392
                        int max_index = Math.max(caretPosition, markPosition);
1393
                        
1394
                        if (caretPosition == markPosition)
1395
                                if (caretPosition == document.getLength()) // If no characters have to be removed
1396
                                        return;
1397
                                else
1398
                                        max_index ++;
1399
                        
1400
                        String newText = document.getText(0, Math.min(caretPosition, markPosition)) + document.getText(max_index, document.getLength() - max_index );
1401
                
1402
                        // Update model and document, and remove character\s
1403
                        switch(currentShowState)
1404
                        {
1405
                                case START_VIEW_STATE :
1406
                                                                        
1407
                                        if (document.getLength() > 0)
1408
                                        {                                                                                
1409
                                                // If dynamic searches:
1410
                                                try {
1411
                                                        // If the search will be dynamic:
1412
                                                        if (isDynamicSearchConfiguration())
1413
                                                        {
1414
                                                                model.setWrittenText(newText);
1415
                                                                logger.debug("Texto que se le env?a delete al modelo desde SUPR: ->" + document.getText(0, document.getLength()) + "<-");                                                
1416
                                                        }
1417
                                                } catch (BadLocationException e) {
1418
                                                        e.printStackTrace();
1419
                                                }        
1420
                                                
1421
                                                model.setStartStateFlag(false);
1422
                                                currentShowState = SEARCH_VIEW_STATE;
1423
                                                
1424
                                                // Remove one or more characters 
1425
                                                characterEliminationLogic(editor, caretPosition, markPosition);                                                
1426
                                        }
1427
                                        break;
1428
                                case SEARCH_VIEW_STATE :
1429
                                        
1430
                                         // If there isn't characters
1431
                                        if (document.getLength() == 0)
1432
                                        {
1433
                                                // This instruction avoids popup could failure when got invisible
1434
                                                hidePopup();
1435
                                                
1436
                                                // If it's a dynamic search
1437
                                                if (isDynamicSearchConfiguration())
1438
                                                {
1439
                                                        model.setWrittenText("");
1440
                                                        logger.debug("Texto que se le env?a delete al modelo desde SUPR: ->\"\"<-");
1441
                                                }
1442
                                                
1443
                                                // Remove one or more characters 
1444
                                                characterEliminationLogic(editor, caretPosition, markPosition);
1445
                                                
1446
                                                // Return to the start view state
1447
                                                model.setStartStateFlag(true);
1448
                                                currentShowState = START_VIEW_STATE;
1449
        
1450
                                                // Select the first Item 
1451
                                                setSelectedIndex(0);
1452
        
1453
                                                if (useHighlight_Flag)
1454
                                                        document.highlightCompletedText(0);
1455
                                        }
1456
                                        else
1457
                                        {                                        
1458
                                                // This instruction avoids popup could failure when got invisible
1459
                                                hidePopup();
1460
                                                
1461
                                                allowInsertString = true;
1462
        
1463
                                        if (lastWasPressedAKeyModifier)
1464
                                        {
1465
                                                logger.debug("PRESSED: " + editor.getText().substring(0));
1466
                                                lastWasPressedAKeyModifier = false;
1467
                                        }
1468
                                                
1469
                                                // If dynamic searches:
1470
                                                try {
1471
                                                        
1472
                                                        // If the search will be dynamic:
1473
                                                        if (isDynamicSearchConfiguration())
1474
                                                        {
1475
                                                                model.setWrittenText(newText);
1476
                                                                logger.debug("Texto que se le env?a delete al modelo desde SUPR: ->" + document.getText(0, document.getLength()) + "<-");                                                
1477
                                                        }
1478
                                                        
1479
                                                        // Remove one or more characters 
1480
                                                        characterEliminationLogic(editor, caretPosition, markPosition);
1481
                                                        
1482
                                                    // Indicate to the model that now is disabled the start view
1483
                                                    if (currentShowState == START_VIEW_STATE)
1484
                                                    {
1485
                                                            model.setStartStateFlag(false);
1486
                                                            currentShowState = SEARCH_VIEW_STATE;
1487
                                                    }
1488
                                                } catch (BadLocationException e) {
1489
                                                        // TODO Auto-generated catch block
1490
                                                        e.printStackTrace();
1491
                                                }
1492
                                        }                                                                        
1493
                                        break;                                                                        
1494
                        }
1495
                
1496
                        updatePopUpView();
1497
                        
1498
                } catch (BadLocationException e1) {
1499
                        // TODO Auto-generated catch block
1500
                        e1.printStackTrace();
1501
                }
1502
        }
1503
        
1504
        /**
1505
         * This method has the logic for remove one or more characters 
1506
         * 
1507
         * @param editor A reference to the editor
1508
         * @param caretPosition Position of the caret in the text
1509
         */
1510
        private void characterEliminationLogic(JTextComponent editor, int caretPosition, int markPosition) {
1511
                // First: Remove character\s (only if hasn't been done a 'cut' mouse operation)
1512
                if (cutOperationDone) {
1513
                        cutOperationDone = false;
1514
                }
1515
                else {
1516
                        try {                        
1517
                                // If no characters are selected
1518
                                if (markPosition == caretPosition) {
1519
                                        // Remove the character which is on the right of the caret position
1520
                                        if (caretPosition < document.getLength())                                                                        
1521
                                                document.remove(caretPosition, 1);                                                                                
1522
                                }
1523
                                else // If there are characters selected
1524
                                {
1525
                                        // Remove the characters which are selected
1526
                                        int length = Math.abs(markPosition - caretPosition);
1527
                                        
1528
                                        // Remove the characters which are selected
1529
                                        document.remove(Math.min(markPosition, caretPosition), length);
1530
                                }
1531
                        } catch (BadLocationException e) {
1532
                                e.printStackTrace();
1533
                        }
1534
                }        
1535
        }
1536

    
1537
        /**
1538
         * Returns true if the model has a dynamic search configuration
1539
         * 
1540
         * @return 'true' if the model has a dynamic searchh configuration, else returns 'false'.
1541
         */
1542
        private boolean isDynamicSearchConfiguration() {
1543
                switch(model.getSearchBehavior())
1544
                {
1545
                        case AbstractDefaultComboBoxItemsSeekerConfigurableModel.MAINTAIN_ORIGINAL_POSITION_DYNAMIC_SEARCH :
1546
                        case AbstractDefaultComboBoxItemsSeekerConfigurableModel.ORDERED_DYNAMIC_SEARCH :
1547
                        case AbstractDefaultComboBoxItemsSeekerConfigurableModel.DISORDERED_DYNAMIC_SEARCH :
1548
                                return true;
1549
                }
1550
                
1551
                return false;
1552
        }
1553
        
1554
        /**
1555
         * Selects the first item added to the model
1556
         */
1557
        public void selectFirstItemAddedToModel() {
1558
                // Select the first Item added
1559
                Object item = model.getFirstItemAdded();
1560
                if (item != null)
1561
                        setSelectedItem(item);
1562
        }
1563

    
1564
    
1565
        /**
1566
     * Updates the popup view, this solves the problem of updating items that are showed, but has the problem that could produce winking
1567
     */
1568
        private void updatePopUpView() {
1569
            // HidePopUp + ShowPopUp to force update the popup list of items
1570
                hidePopup();
1571
                showPopup();
1572
                this.setVisible(true);
1573
        
1574
    }
1575
        
1576
        /**
1577
         * This method has the logic for a "undo" operation
1578
         */
1579
        private void undoOperationLogic() {
1580
                logger.debug("UNDO PRESSED");
1581
                try {
1582
            if (undoManager.canUndo()) {
1583
                    undoManager.undo();
1584
                    
1585
                    String newPattern = document.getText(0, document.getLength());
1586
                            
1587
                                model.setWrittenText(newPattern);
1588
                                
1589
                                document.formatText(document.lookupItem(), 0);
1590
                                
1591
                                if (isPopupVisible())
1592
                                        updatePopUpView();
1593
                    
1594
                    logger.debug("Undo por teclado realizado");
1595
            }
1596
                } catch (BadLocationException e) {
1597
                        e.printStackTrace();
1598
                } catch (CannotUndoException e) {
1599
                e.printStackTrace();
1600
        }
1601
        }
1602
        
1603
        /**
1604
         * This method has the logic for a "redo" operation
1605
         */
1606
        private void redoOperationLogic() {
1607
                logger.debug("REDO PRESSED");
1608
        try {
1609
            if (undoManager.canRedo()) {
1610
                            undoManager.redo();
1611
                            
1612
                     String newPattern = document.getText(0, document.getLength());
1613
                           
1614
                               model.setWrittenText(newPattern);
1615
                               
1616
                               document.formatText(document.lookupItem(), 0);
1617
                               
1618
                               if (isPopupVisible())
1619
                                        updatePopUpView();
1620
                            
1621
                    logger.debug("Redo por teclado realizado");
1622
            }
1623
            } catch (CannotRedoException e) {
1624
                    e.printStackTrace();
1625
            } catch (BadLocationException e) {
1626
                    e.printStackTrace();
1627
            }
1628
        }    
1629
    
1630
    ////// REDEFINITION OF SOME METHODS OF JCOMBOBOX //////
1631

    
1632
        /*
1633
         *  (non-Javadoc)
1634
         * @see javax.swing.JComboBox#actionPerformed(java.awt.event.ActionEvent)
1635
         */
1636
        public void actionPerformed(ActionEvent e)
1637
        {
1638
                super.actionPerformed(e);
1639

    
1640
                // This flag indicates to the 'insertString' method of the PlainDocumentSeeker that the text of the item selected or written by the user
1641
                //  hasn't been written on the TextEditor of ths component
1642
                selecting = false;
1643
        }
1644

    
1645
        /*
1646
     * (non-Javadoc)
1647
     * @see javax.swing.JComboBox#addItem(java.lang.Object)
1648
     */
1649
        public void addItem(Object anObject) {
1650
                // Adds the item to this component                
1651
                model.addElement(anObject);
1652
                
1653
                // Set the last selected item -> by default select the first item:
1654
                // This is used to show the first item that model returns when we add a new item. This also
1655
                //  corrects the 'mistake' produced by 'ComboBoxModel' when is added a new item and there wasn't
1656
                //  any selected -> that the 'ComboBoxModel' selects by default the first added (that in our case 
1657
                //  might not be the same as the first item seen in the popup list)
1658
                if (this.getSelectedIndex() != 0)
1659
                {
1660
                        this.setSelectedIndex(0);
1661
//                        this.selectedItem = this.getSelectedItem();
1662
                }
1663
        }
1664
    
1665
        /*
1666
     * (non-Javadoc)
1667
     * @see javax.swing.JComboBox#removeAllItems()
1668
     */
1669
        public void removeAllItems() {
1670
            // Removes all items from the model
1671
            model.removeAllElements();
1672
            
1673
            currentShowState = BEGINNING_VIEW_STATE;
1674
    }
1675
    
1676
        /*
1677
     * (non-Javadoc)
1678
     * @see javax.swing.JComboBox#removeItem(java.lang.Object)
1679
     */
1680
        public void removeItem(Object anObject) {
1681
            // Removes an object from the model
1682
            model.removeElement(anObject);
1683
            
1684
            if (model.getSize() == 0)
1685
                    currentShowState = BEGINNING_VIEW_STATE;
1686
    }
1687

    
1688
        /*
1689
     * (non-Javadoc)
1690
     * @see javax.swing.JComboBox#removeItemAt(int)
1691
     */
1692
        public void removeItemAt(int anIndex) {
1693
               // Removes an object, which is in a determinated position (index), from the model
1694
            model.removeElementAt(anIndex);
1695
            
1696
            if (model.getSize() == 0)
1697
                    currentShowState = BEGINNING_VIEW_STATE;
1698
    }
1699
    
1700
        /*
1701
     * (non-Javadoc)
1702
     * @see javax.swing.JComboBox#getItemCount()
1703
     */
1704
        public int getItemCount() {
1705
            return model.getSize();
1706
    }
1707
    
1708
        /*
1709
     * (non-Javadoc)
1710
     * @see javax.swing.JComboBox#getItemAt(int)
1711
     */
1712
        public Object getItemAt(int index) {
1713
            return model.getElementAt(index);
1714
    }
1715
    
1716
        /*
1717
     * (non-Javadoc)
1718
     * @see javax.swing.JComboBox#setModel(javax.swing.ComboBoxModel)
1719
     */
1720
        public void setModel(ComboBoxModel aModel) {            
1721
            // Depending on the type of class of the current object, this object will execute different code
1722
            if ( (aModel instanceof ComboBoxSingularItemsSeekerConfigurableModel) || (aModel instanceof ComboBoxItemsSeekerConfigurableModel) )
1723
            {
1724
                    super.setModel(aModel);
1725
                    
1726
                    if (aModel instanceof ComboBoxSingularItemsSeekerConfigurableModel)
1727
                            model = (ComboBoxSingularItemsSeekerConfigurableModel)super.getModel();
1728
                    else
1729
                            model = (ComboBoxItemsSeekerConfigurableModel)super.getModel();
1730
                    
1731
                    // If we insert a model with items -> select by default the first
1732
                    if (aModel.getSize() > 0)
1733
                            this.setSelectedIndex(0);
1734
                    else
1735
                    {
1736
                            // Else -> set the default index (-1) and current showed string ("")
1737
                            this.setSelectedIndex(-1);
1738
                    }
1739
                    
1740
                    this.configureModel();
1741
            }
1742
            else
1743
            {
1744
                    // If it's an instance of DefaultComboBoxModel:
1745
                    super.setModel(aModel);                    
1746
            }                    
1747
     }
1748
    
1749
        /*
1750
     * (non-Javadoc)
1751
     * @see javax.swing.JComboBox#setSelectedIndex(int)
1752
     */
1753
        public void setSelectedIndex(int anIndex) {
1754
            super.setSelectedIndex(anIndex);
1755
    }
1756
    
1757
        /*
1758
     * (non-Javadoc)
1759
     * @see javax.swing.JComboBox#getSelectedIndex()
1760
     */
1761
        public int getSelectedIndex() {
1762
            Object item = this.getSelectedItem();
1763
            
1764
            if (item == null)
1765
                    return -1;
1766
            else
1767
                    return model.getIndexOf(item);
1768
    }
1769
    
1770
        /*
1771
     *  (non-Javadoc)
1772
     * @see javax.swing.JComboBox#setSelectedItem(java.lang.Object)
1773
     */
1774
        public void setSelectedItem(Object anObject) {
1775
            super.setSelectedItem(anObject);
1776
    }
1777
    
1778
    ////// END REDEFINITION OF SOME METHODS OF JCOMBOBOX //////
1779
   
1780
        
1781

    
1782
        ////// METHODS FOR THE BEHAVIOR FLAGS  //////
1783

    
1784
        /**
1785
         * This method tests the configuration of the flags and returns true or false if its ok or not with the
1786
         *   logical behavior of this component
1787
         * 
1788
         * @return boolean True if the configuration of the flags is oks, false if not
1789
         */
1790
        public boolean testFlagsConfigurationOK() {
1791
                return this.model.testFlagsConfigurationOK();
1792
        }
1793
        
1794
        /**
1795
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#getStartBehavior()
1796
         */
1797
        public int getStartBehavior() {
1798
                return this.model.getStartBehavior();
1799
        }
1800
        
1801
        /**
1802
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#setStartBehavior(int)
1803
         */
1804
        public void setStartBehavior(int start_Behavior) {
1805
                this.model.setStartBehavior(start_Behavior);
1806
                
1807
                if (!this.model.testFlagsConfigurationOK())
1808
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1809
        }
1810

    
1811
        /**
1812
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#getSearchBehavior()
1813
         */
1814
        public int getSearchBehavior() {
1815
                return this.model.getSearchBehavior();
1816
        }
1817

    
1818
        /**
1819
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#setSearchBehavior(int)
1820
         */
1821
        public void setSearchBehavior(int search_Behavior) {
1822
                this.model.setSearchBehavior(search_Behavior);
1823
                
1824
                if (!this.model.testFlagsConfigurationOK())
1825
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1826
        }
1827
        
1828
        /**
1829
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#isCaseSensitive_Flag()
1830
         */
1831
        public boolean isCaseSensitive_Flag() {
1832
                return this.model.isCaseSensitive_Flag();
1833
        }
1834
        
1835
        /**
1836
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#setCaseSensitive_Flag(boolean)
1837
         */
1838
        public void setCaseSensitive_Flag(boolean case_Sensitive) {
1839
                this.model.setCaseSensitive_Flag(case_Sensitive);
1840
                
1841
                if (!this.model.testFlagsConfigurationOK())
1842
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1843
        }
1844

    
1845
        /**
1846
         * Returns the 'only_one_color_on_text' configuration value of this component. Configuration values are: 
1847
         *   + true -> always uses black color on text
1848
         *   + 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
1849
         * 
1850
         * @return Only-One-Color-On-Text configuration
1851
         */
1852
        public boolean isOnlyOneColorOnText_Flag() {
1853
                return onlyOneColorOnText_Flag;
1854
        }
1855
        
1856
        /**
1857
         * Sets the 'only_one_color_on_text' configuration value for this component. Configuration values are: 
1858
         *   + true -> always uses black color on text
1859
         *   + 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
1860
         * 
1861
         * @return Only_one_color_on_text configuration
1862
         */
1863
        public void setOnlyOneColorOnText_Flag(boolean only_One_Color) {
1864
                this.onlyOneColorOnText_Flag = only_One_Color;
1865
                
1866
                if (!this.model.testFlagsConfigurationOK())
1867
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1868
        }
1869

    
1870
        /**
1871
         * Returns the 'beep_enabled' configuration value of this component. Configuration values are: 
1872
         *   + true -> a beep-sound is listened when no item matches with the text written.
1873
         *   + false -> no sound is listened.
1874
         * 
1875
         * @return Beep_enabled configuration
1876
         */
1877
        public boolean isBeepEnabled_Flag() {
1878
                return this.beepEnabled_Flag;
1879
        }
1880
        
1881
        /**
1882
         * Sets the 'beep_enabled' configuration value for this component. Configuration values are: 
1883
         *   + true -> a beep-sound is listened when no item matches with the text written.
1884
         *   + false -> no sound is listened.
1885
         * 
1886
         * @return Beep_Enabled configuration
1887
         */
1888
        public void setBeepEnabled_Flag(boolean beep_Enabled) {
1889
                this.beepEnabled_Flag = beep_Enabled;
1890
        }        
1891
        
1892
        /**
1893
         * Returns the 'complete_matched_item' configuration value of this component. Configuration values are: 
1894
         *   + true -> When user writes, shows also the rest of the current matched item that user hasn't written.
1895
         *   + false -> Only shows the text written by the user when user is writting.
1896
         * 
1897
         * @return Complete_matched_item configuration
1898
         */
1899
        public boolean isCompleteMatchedItem_Flag() {
1900
                return this.completeMatchedItem_Flag;
1901
        }
1902
        
1903
        /**
1904
         * Sets the 'complete_matched_item' configuration value for this component. Configuration values are: 
1905
         *   + true -> a beep-sound is listened when no item matches with the text written.
1906
         *   + false -> no sound is listened.
1907
         * 
1908
         * @return Complete_matched_item configuration
1909
         */
1910
        public void setCompleteMatchedItem_Flag(boolean Complete_Matched_Item) {
1911
                this.completeMatchedItem_Flag = Complete_Matched_Item;
1912
        }
1913
        
1914
        /**
1915
         * Returns the 'allowed_repeated_items' configuration value of this component. Configuration values are: 
1916
         * Uses one of the two models according the value of this flag:
1917
     *    + true -> Uses 'ComboBoxItemsSeekerConfigurableModel' as model (this could work slowly).
1918
     *    + false -> Uses 'ComboBoxSingularItemsSeekerConfigurableModel' as model.
1919
     *    
1920
         * @return Allowed_repeated_items configuration
1921
         */
1922
        public boolean isAllowedRepeatedItems_Flag() {
1923
                return this.allowedRepeatedItems_Flag;
1924
        }
1925
        
1926
        /**
1927
         * Sets the 'allowed_repeated_items' configuration value for this component. Configuration values are: 
1928
         * Uses one of the two models according the value of this flag:
1929
     *    + true -> Uses 'ComboBoxItemsSeekerConfigurableModel' as model (this could work slowly).
1930
     *    + false -> Uses 'ComboBoxSingularItemsSeekerConfigurableModel' as model.
1931
         * 
1932
         * @return Allowed_repeated_items configuration
1933
         */
1934
        public void setAllowedRepeatedItems_Flag(boolean allowed_Repeated_Items) {
1935
                this.allowedRepeatedItems_Flag = allowed_Repeated_Items;
1936
                
1937
                try {
1938
                        AbstractDefaultComboBoxItemsSeekerConfigurableModel model_temp;
1939
                        
1940
                        // Add the items to the new model
1941
                        if (allowed_Repeated_Items)
1942
                                model_temp = new ComboBoxItemsSeekerConfigurableModel(model.getParentAllData());
1943
                        else
1944
                                model_temp = new ComboBoxSingularItemsSeekerConfigurableModel(model.getParentAllData());
1945
                                                        
1946
                        // Copy the behavior of the model
1947
                        model_temp.setStartBehavior(this.getStartBehavior());
1948
                        model_temp.setSearchBehavior(this.getSearchBehavior());
1949
                        model_temp.setCaseSensitive_Flag(this.isCaseSensitive_Flag());
1950
                        
1951
                        // Set the new model
1952
                        this.setModel(model_temp);
1953
                }
1954
                catch(Exception e)
1955
                {
1956
                        e.printStackTrace();
1957
                }
1958
        }
1959
        
1960
        /**
1961
         * Returns the 'allowed_mouse_edition_popup_menu' configuration value of this component. Configuration values are: 
1962
         *   + true -> a 'PopupMenu' for text edition that appears when the user clicks on the text-edition-field with the right
1963
         *                button of the mouse.
1964
         *   + false -> that 'PopupMenu' won't appear. 
1965
         * 
1966
         * @return Allowed_mouse_edition_popup_menu configuration
1967
         */
1968
        public boolean isAllowedMouseEditionPopupMenu_Flag() {
1969
                return this.allowedMouseEditionPopupMenu_Flag;
1970
        }
1971

    
1972
        /**
1973
         * Sets the 'allowed_mouse_edition_popup_menu' configuration value for this component. Configuration values are: 
1974
         *   + true -> a 'PopupMenu' for text edition that appears when the user clicks on the text-edition-field with the right
1975
         *                button of the mouse.
1976
         *   + false -> that 'PopupMenu' won't appear. 
1977
         * 
1978
         * @return Allowed_mouse_edition_popup_menu configuration
1979
         */
1980
        public void setAllowedMouseEditionPopupMenu_Flag(boolean allowed_Mouse_Edition_Popup_Menu) {
1981
                JTextComponent editor = (JTextComponent) this.getEditor().getEditorComponent();
1982
                
1983
                if (this.allowedMouseEditionPopupMenu_Flag != allowed_Mouse_Edition_Popup_Menu)
1984
                {
1985
                        // If now is allowed -> adds the mouse listener
1986
                        if (allowed_Mouse_Edition_Popup_Menu)
1987
                    editor.addMouseListener(this.editorMouseListener);
1988
                        else // If now isn't allowed
1989
                                editor.removeMouseListener(this.editorMouseListener);
1990
                }
1991

    
1992
                this.allowedMouseEditionPopupMenu_Flag = allowed_Mouse_Edition_Popup_Menu;
1993
        }
1994

    
1995
        /**
1996
         * Returns the 'to_force_to_only_coincidences_in_the_search' configuration value of this component. Configuration values are: 
1997
         *   + true -> If the user has written some text that doesn't mach with any item, and press the 'Enter' key for close the popup the user will
1998
         *                see written in the text-edition-field the last item which matched with the text written, or the first item of the model if
1999
         *                there wasn't.
2000
         *   + false -> If no item matches with the text written and the user presses the 'Enter' key, no item will be selected.
2001
         * 
2002
         * @return To_force_to_only_coincidences_in_the_search configuration
2003
         */
2004
        public boolean isToForceToOnlyCoincidencesInTheSearch_Flag() {
2005
                return this.toForceToOnlyCoincidencesInTheSearch_Flag;
2006
        }
2007
        
2008
        /**
2009
         * Sets the 'to_force_to_only_coincidences_in_the_search' configuration value for this component. Configuration values are: 
2010
         *   + true -> If the user has written some text that doesn't mach with any item, and press the 'Enter' key for close the popup the user will
2011
         *                see written in the text-edition-field the last item which matched with the text written, or the first item of the model if
2012
         *                there wasn't.
2013
         *   + false -> If no item matches with the text written and the user presses the 'Enter' key, no item will be selected.
2014
         * 
2015
         * @return To_force_to_only_coincidences_in_the_search configuration
2016
         */
2017
        public void setToForceToOnlyCoincidencesInTheSearch_Flag(boolean to_Force_To_Only_Coincidences_In_The_Search) {
2018
                this.toForceToOnlyCoincidencesInTheSearch_Flag = to_Force_To_Only_Coincidences_In_The_Search;
2019
        }
2020

    
2021
        /**
2022
         * Returns the 'use_highlight' configuration value of this component. Configuration values are: 
2023
         *   + true -> marks characters of the text in the text-edition-field with a highlight.
2024
         *   + false -> doesn't do that.
2025
         * 
2026
         * @return Use_highlight configuration
2027
         */
2028
        public boolean isUseHighLight_Flag() {
2029
                return this.useHighlight_Flag;
2030
        }
2031
        
2032
        /**
2033
         * Sets the 'use_highlight' configuration value for this component. Configuration values are: 
2034
         *   + true -> marks characters of the text in the text-edition-field with a highlight.
2035
         *   + false -> doesn't do that.
2036
         * 
2037
         * @return Use_highlight configuration
2038
         */
2039
        public void setUseHighLight_Flag(boolean use_Highlight) {
2040
                this.useHighlight_Flag = use_Highlight;
2041
        }        
2042
        
2043
        ////// END METHODS FOR THE BEHAVIOR FLAGS  //////
2044
        
2045
        
2046
    
2047
    ////// OTHER METHODS //////
2048
        
2049
        /**
2050
     * Sets the limit of actions that can hold the UndoManager of this component
2051
     * 
2052
     * @param limit
2053
     */
2054
        public void setUndoRedoLimitActions(int limit) {
2055
            this.undoRedoLimitActions = limit;
2056
            undoManager.setLimit(undoRedoLimitActions);
2057
    }
2058
    
2059
        /**
2060
     * Gets the limit of actions that can hold the UndoManager:
2061
     * 
2062
     * @return int 
2063
     */
2064
        public int getUndoRedoLimitActions() {
2065
            return this.undoRedoLimitActions;
2066
    }
2067
     
2068
    ////// END OTHER METHODS //////        
2069
        
2070
        
2071
        /**
2072
         * Inner class that inherits of the class PlainDocument, and is used for manipulate the text that has the document of the editor of this component
2073
         * This class is also optimized for items seek, changes the color of the text or sets highlight if it's needed.
2074
         * 
2075
         * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
2076
         */
2077
        private class PlainDocumentTextFormatter extends PlainDocument {
2078
                private static final long serialVersionUID = 4158213349939840209L;
2079
                private JComboBoxItemsSeekerConfigurable comboBoxReference;                
2080

    
2081
                /**
2082
                 * Default Constructor
2083
                 */
2084
                public PlainDocumentTextFormatter() {
2085
                        super();
2086
                        this.initialize();
2087
                }
2088
                
2089
                /**
2090
                 * This method makes some initialize operations 
2091
                 */
2092
                private void initialize() {
2093
                        this.configureUndoManager();
2094
                }
2095
                
2096
                /**
2097
                 * Configures the UndoManager for Undo-Redo operations
2098
                 */
2099
                private void configureUndoManager() {
2100
                // Listen for undo and redo events
2101
                this.addUndoableEditListener(new UndoableEditListener() {
2102
                        /*
2103
                         * (non-Javadoc)
2104
                         * @see javax.swing.event.UndoableEditListener#undoableEditHappened(javax.swing.event.UndoableEditEvent)
2105
                         */
2106
                    public void undoableEditHappened(UndoableEditEvent evt) {
2107
                            logger.debug("UNDOABLE EVENT");
2108
                                        undoManager.addEdit(evt.getEdit());
2109
                    }
2110
                });
2111
                }
2112

    
2113
                /**
2114
                 * Sets a reference of the combo_Box
2115
                 * 
2116
                 * @param combo_Box A reference to the class that contains this.
2117
                 */
2118
                public void setJComboBoxItemsSeekerDynamicReference(JComboBoxItemsSeekerConfigurable combo_Box) {
2119
                        comboBoxReference = combo_Box;
2120
                }
2121
                
2122
                /*
2123
                 *  (non-Javadoc)
2124
                 * @see javax.swing.text.Document#remove(int, int)
2125
                 */
2126
                public void remove(int offs, int len) throws BadLocationException {
2127
                // return immediately when selecting an item
2128
                if (selecting) return;
2129

    
2130
                if (hitBackspace)
2131
                {
2132
                    // user hit backspace => move the selection backwards
2133
                    // old item keeps being selected
2134
                    if (offs>0)
2135
                    {
2136
                        if (hitBackspaceOnSelection)
2137
                                offs--;
2138
                    }
2139
                    else
2140
                    {
2141
                        // User hit backspace with the cursor positioned on the start => beep
2142
                            if (beepEnabled_Flag)
2143
                                    comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
2144
                    }
2145
                    
2146
                    if (useHighlight_Flag)
2147
                                        highlightCompletedText(offs);
2148
                            
2149
                    hitBackspace=false;
2150
                }
2151
                else
2152
                {
2153
                        logger.debug("REMOVES OFFS: " + offs + ", LEN: " + len);
2154
                        super.remove(offs, len);
2155
                }  
2156

    
2157
                formatText(lookupItem(), offs);
2158
            }
2159

    
2160
                /* NUEVA VERSI?N
2161
                 *  (non-Javadoc)
2162
                 * @see javax.swing.text.Document#insertString(int, java.lang.String, javax.swing.text.AttributeSet)
2163
                 */
2164
            public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
2165
                    Object item = lookupItem();
2166
                          
2167
                    // If we have to complete the text: only write the part of the item not written
2168
                        if ((completeMatchedItem_Flag) && (item != null) && (!itemSelectedByMouse)) {                                                    
2169
                                editor.getEditorComponent().setForeground(Color.BLACK);
2170
                                super.insertString(super.getLength(), item.toString().substring(super.getLength(), item.toString().length()), a);
2171
                                
2172
                                if (!specialSelectionByUserState)
2173
                                        offs += Math.min(str.length(), document.getLength());
2174
                        }
2175
                        else {
2176
                                super.insertString(offs, str, a);
2177
                                itemSelectedByMouse = false;
2178
                                offs += str.length();
2179
                        }
2180
//                        offs += Math.min(str.length(), document.getLength());
2181
                        formatText(item, offs);
2182
            }
2183
                
2184
                /**
2185
                 * Marks text since 'start' position to its end on a grey color
2186
                 *  
2187
                 * @param start Start position for mark the text
2188
                 */
2189
                public void highlightCompletedText(int start) {
2190
                    JTextComponent editor = (JTextComponent) getEditor().getEditorComponent();
2191
                    
2192
                editor.setCaretPosition(document.getLength());
2193
                editor.moveCaretPosition(start);
2194
            }
2195
                
2196
                /**
2197
                 * If the pattern doesn't match with the selected/current item changes the color of the text to red if isOnlyOneColorOnText_Flag=true, else 
2198
             *    sets the color of the text black.
2199
                 * 
2200
                 * @param pattern
2201
                 */
2202
                private void formatText(Object item, int offs) {                    
2203
                    if (!comboBoxReference.isOnlyOneColorOnText_Flag()) {
2204
                            if ((item == null) && (currentShowState != START_VIEW_STATE)) {
2205
                                    editor.getEditorComponent().setForeground(Color.RED);
2206
                                    logger.debug("Pone a Rojo Lookup");
2207
                            }
2208
                            else {
2209
                                    editor.getEditorComponent().setForeground(Color.BLACK);
2210
                                    logger.debug("Pone a Negro Lookup");
2211
                            }
2212
                            
2213
                                // If it's necessary, produces a "beep" sound
2214
                                if ((beepEnabled_Flag) && (item == null) && (!lastWasTheBeginningState)) {
2215
                                        comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
2216
                                }
2217
                    }
2218
                    
2219
                    if (useHighlight_Flag) {
2220
                                  
2221
                            // Select
2222
                            highlightCompletedText(offs);
2223
                          }
2224
                }
2225
                
2226
                /**
2227
                 * Returns the current item in the popup of JComboBox or the selected item. If there is no item, returns null
2228
                 * 
2229
                 * @return An object
2230
                 */
2231
                private Object lookupItem() {
2232
                Object item = null;
2233
                    if (model.getSize() > 0) {
2234
                            if (specialSelectionByUserState) {
2235
                                    item = model.getSelectedItem();
2236
                            }
2237
                            else
2238
                                    item = model.getElementAt(0);
2239
                    }
2240
                    
2241
                    return item;
2242
                }
2243
        }
2244
}