Statistics
| Revision:

svn-gvsig-desktop / tags / v1_0_2_Build_912 / libraries / libUI / src / org / gvsig / gui / beans / comboBoxItemsSeeker / JComboBoxItemsSeekerConfigurable.java @ 11422

History | View | Annotate | Download (81.2 KB)

1 6721 ppiqueras
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 6793 ppiqueras
import java.awt.event.MouseAdapter;
12
import java.awt.event.MouseEvent;
13 8765 jjdelcerro
import java.awt.event.MouseWheelEvent;
14
import java.awt.event.MouseWheelListener;
15 6721 ppiqueras
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 8765 jjdelcerro
import javax.swing.event.CaretListener;
23 6721 ppiqueras
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 6793 ppiqueras
import javax.swing.event.UndoableEditEvent;
30
import javax.swing.event.UndoableEditListener;
31 6721 ppiqueras
import javax.swing.text.AttributeSet;
32
import javax.swing.text.BadLocationException;
33
import javax.swing.text.JTextComponent;
34
import javax.swing.text.PlainDocument;
35 6816 ppiqueras
import javax.swing.undo.CannotRedoException;
36
import javax.swing.undo.CannotUndoException;
37 6793 ppiqueras
import javax.swing.undo.UndoManager;
38 6721 ppiqueras
39 6732 ppiqueras
import org.apache.log4j.Logger;
40 7244 cesar
import org.gvsig.gui.beans.Messages;
41 6816 ppiqueras
import org.gvsig.gui.beans.optionsEditionByMousePopupMenu.JOptionsEditionByMousePopupMenu;
42 6721 ppiqueras
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 8765 jjdelcerro
/** ?? 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 9089 ppiqueras
 * There are 11 configuration flags/attributes: 3 for the Model and the others for the Control and/or View.
93 8765 jjdelcerro
 *    ? 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 9089 ppiqueras
 *         - Select An Item When Loses Focus:
120
 *              + true -> If user or an application makes component lose its focus, an item will be selected.
121
 *              + false -> If user or an application makes component lose its focus, the component will stay as it was
122 8765 jjdelcerro
 *    . Control and Model flag (can be 'true' or 'false'):
123
 *         - Allowed Repeated Items -> Uses one of the two models according the value of this flag:
124
 *              + true -> Uses 'ComboBoxItemsSeekerConfigurableModel' as model (this could work slowly).
125
 *              + false -> Uses 'ComboBoxSingularItemsSeekerConfigurableModel' as model.
126
 *
127
 * By default the configuration is:
128
 *     - Start_Behavior = MAINTAIN_ORIGINAL_POSITION_START
129
 *     - Search_Behavior = ORDERED_DYNAMIC_SEARCH
130
 *     - Case_Sensitive = false
131
 *     - Only_One_Color_On_Text = false
132
 *     - Complete_Matched_Item = true
133
 *     - Beep_Enabled = true
134
 *     - Allowed_Repeated_Items = false
135
 *     - Allowed_Mouse_Edition_Popup_Menu = true
136
 *     - To_Force_To_Only_Coincidences_In_The_Search = true
137
 *     - Use_Highlight = true
138 9089 ppiqueras
 *     - Select_An_Item_When_Loses_Focus = false
139 8765 jjdelcerro
 *
140
 * Other functionality:
141
 *     - Similar functionality as JComboBox:
142
 *         + Select an item from the inner popup using the mouse
143
 *         + Show item/items that match in the inner popup
144
 *         + Similar edition operations: Right, left, ...
145
 *         + ...
146
 *     - With the keyboard the user can do the same operations as with the "edition popup menu" :
147
 *         CTRL + A -> Select all text
148
 *         CTRL + Z -> Undo
149
 *         CTRL + SHIFT + Z -> Redo
150
 *         CTRL + C -> Copy selected text
151
 *         CTRL + X -> Cut selected text
152
 *         CTRL + V -> Paste on selected text/position
153
 *         DELETE (SUPR in Spanish Keyboard) -> Remove selected text
154
 *     - ESC key -> Sets the component to its initial state (that user can estimate)
155
 *
156
 * Special-Warning characteristics
157
 *     - In same inherit states the view could don't match with the model (this states aren't final states)
158
 *
159
 * Limitations:
160
 *     - Items of the model of this component must have a "string" value returned by "toString()" method
161
 *     - If the model of the component has lot of items, this could work slowly.
162
 *     - If the model has repeated items -> set true the flag 'allowedRepeatedItems', this will use the 'ComboBoxItemsSeekerConfigurableModel' model,
163
 *         and will work more slowly than the 'ComboBoxSingularItemsSeekerConfigurableModel' model; more as more items had the model.
164
 *     - It's possible that some combination of configuration would be unmanageable.
165
 *     - It's possible that some configuration or some operation fail !!
166
 *
167
 * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
168
 */
169 6721 ppiqueras
public class JComboBoxItemsSeekerConfigurable extends JComboBox implements java.io.Serializable {
170 9098 ppiqueras
        private static final long serialVersionUID = 6581895116338237598L;
171
172 8765 jjdelcerro
        // CONSTANTS FOR THE CURRENT STATE OF THE COMPONENT
173 6721 ppiqueras
        private final int BEGINNING_VIEW_STATE = 0;
174
        private final int START_VIEW_STATE = 1;
175
        private final int SEARCH_VIEW_STATE = 2;
176 8765 jjdelcerro
        // END CONSTANTS FOR THE CURRENT STATE OF THE COMPONENT
177
178
        // ATTRIBUTE FOR THE CURRENT STATE
179 6721 ppiqueras
        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
180 8765 jjdelcerro
        // END ATTRIBUTE FOR THE CURRENT STATE
181 6721 ppiqueras
182 8765 jjdelcerro
        // CONSTANTS FOR CONFIGURE THE BEHAVIOR
183
        public static final boolean DEFAULT_ONLY_ONE_COLOR_ON_TEXT_CONFIGURATION = false;
184
        public static final boolean DEFAULT_COMPLETE_MATCHED_ITEM_CONFIGURATION = true;
185
        public static final boolean DEFAULT_BEEP_ENABLED_CONFIGURATION = true;
186
        public static final boolean DEFAULT_ALLOWED_REPEATED_ITEMS_CONFIGURATION = false;
187
        public static final boolean DEFAULT_ALLOWED_MOUSE_EDITION_POPUP_MENU_CONFIGURATION = true;
188
        public static final boolean DEFAULT_TO_FORCE_TO_ONLY_COINCIDENCES_IN_THE_SEARCH_CONFIGURATION = true;
189
        public static final boolean DEFAULT_USE_HIGHLIGHT_CONFIGURATION = true;
190 9089 ppiqueras
        public static final boolean DEFAULT_SELECT_AN_ITEM_WHEN_LOSES_FOCUS_CONFIGURATION = false;
191 8765 jjdelcerro
        // END CONSTANTS FOR CONFIGURE THE BEHAVIOR
192 6721 ppiqueras
193
        // CONFIGURATION FLAGS
194 8765 jjdelcerro
        private boolean onlyOneColorOnText_Flag;
195
        private boolean completeMatchedItem_Flag;
196
        private boolean beepEnabled_Flag;
197
        private boolean allowedRepeatedItems_Flag;
198
        private boolean allowedMouseEditionPopupMenu_Flag;
199
        private boolean toForceToOnlyCoincidencesInTheSearch_Flag;
200
        private boolean useHighlight_Flag;
201 9089 ppiqueras
        private boolean selectAnItemWhenLosesFocus_Flag;
202 6721 ppiqueras
        // END FLAGS
203
204 8765 jjdelcerro
        // STORE THE SELECTED ITEM AND THE LAST SELECTED ITEM
205
        private Object lastSelectedItemPopupUse; // This is used for only update (refresh) de popup when a different item is selected
206
    // END STORE THE SELECTED ITEM AND THE LAST SELECTED ITEM
207 6721 ppiqueras
208 8765 jjdelcerro
        private int num = 0; //sobra -> se usan en el log -> ?? SE PUEDE BORRAR !!
209 6721 ppiqueras
210 8765 jjdelcerro
        // NUMBER OF ITEMS SHOWED AT THE SAME TIME IN THE POPUP
211 6721 ppiqueras
        private final int POPUP_LIST_ITEMS_HEIGHT = 8;
212 8765 jjdelcerro
    // END NUMBER OF ITEMS SHOWED AT THE SAME TIME IN THE POPUP
213 6721 ppiqueras
214 8765 jjdelcerro
        // MODEL REFERENCE
215 6755 ppiqueras
        private AbstractDefaultComboBoxItemsSeekerConfigurableModel model;
216 8765 jjdelcerro
        // END MODEL REFERENCE
217 6721 ppiqueras
218 8765 jjdelcerro
        // LISTENERS
219 6721 ppiqueras
        private KeyListener editorKeyListener;
220 6793 ppiqueras
        private MouseAdapter editorMouseListener;
221 8765 jjdelcerro
        private MouseWheelListener editorMouseWheelListener;
222 6721 ppiqueras
        private FocusListener editorFocusListener;
223
        private DocumentListener documentListener;
224
        private ListDataListener modelListDataListener;
225
        private PopupMenuListener popupMenuListener;
226 6793 ppiqueras
        private PropertyChangeListener editionMenuListener;
227 8765 jjdelcerro
        private CaretListener caretListener;
228
        // END LISTENERS
229 6721 ppiqueras
230 8765 jjdelcerro
        // EDITOR DOCUMENT REFERENCE
231
        private PlainDocumentTextFormatter document;
232
        // END EDITOR DOCUMENT REFERENCE
233 6721 ppiqueras
234 8765 jjdelcerro
        // OTHER FLAGS
235
        private boolean allowInsertString;
236 6721 ppiqueras
        private boolean lastWasTheBeginningState;
237 6756 ppiqueras
        private boolean lastWasPressedAKeyModifier;
238
        private boolean popupWillBeVisible;
239 6793 ppiqueras
        private boolean optionsEditorWasVisible;
240 8765 jjdelcerro
        private boolean selecting;
241 6721 ppiqueras
        private boolean hidePopupOnFocusLoss;
242 6791 ppiqueras
        private boolean hitBackspace;
243 6721 ppiqueras
        private boolean hitBackspaceOnSelection;
244 8765 jjdelcerro
        private boolean addUndoableEditEvent;
245
        private boolean firstTimeItGainsFocusWithData;
246
        private boolean specialSelectionByUserState; // In this state it's possible that model couldn't match with view (the selected item)
247
        private boolean cutOperationDone;
248
        private boolean itemSelectedByMouse;
249
        // OTHER FLAGS
250 6732 ppiqueras
251 6793 ppiqueras
        // TRACE - DEBUG
252 6733 ppiqueras
        private Logger logger = Logger.getLogger(JComboBoxItemsSeekerConfigurable.class.getClass());
253 6793 ppiqueras
        // END TRACE - DEBUG
254 6721 ppiqueras
255 8765 jjdelcerro
        // A POPUPMENU FOR EDITION OPTIONS
256 6816 ppiqueras
        private JOptionsEditionByMousePopupMenu optionsEditionByMouse;
257 8765 jjdelcerro
    // END A POPUPMENU FOR EDITION OPTIONS
258 6793 ppiqueras
259
        // UNDO-REDO
260 6816 ppiqueras
        private UndoManager undoManager;
261
        private int undoRedoLimitActions;
262 6793 ppiqueras
        // END UNDO-REDO
263
264 6721 ppiqueras
        /**
265 8765 jjdelcerro
         * Default Constructor without parameters
266 6721 ppiqueras
         */
267
        public JComboBoxItemsSeekerConfigurable() {
268
                // Invokes to the parent class constructor
269
                super();
270
271
                // Create attributes and set initial values
272
                this.initialize();
273
274
                // Set the default values of the flags
275 8765 jjdelcerro
                this.setDefaultBehaviorFlagsConfiguration();
276 6721 ppiqueras
277
                // Other configuration tasks
278
                this.createDefaultListeners();
279
                this.configure();
280
        }
281
282
        /**
283 8765 jjdelcerro
         * Default Constructor with 3 parameters: for the behavior of the Model
284 6721 ppiqueras
         *
285 9089 ppiqueras
         * @param 'start_Behavior' Start behavior of the Model.
286
         * @param 'search_Behavior' Search behavior of the Model.
287
         * @param 'case_Sensitive' Case sensitive behavior of the Model.
288 6721 ppiqueras
         */
289 6756 ppiqueras
        public JComboBoxItemsSeekerConfigurable(int start_Behavior, int search_Behavior, boolean case_Sensitive)        {
290 6721 ppiqueras
                // Invokes to the parent class constructor
291 8765 jjdelcerro
                super();
292
293
                // Set the default values of the flags
294
                this.setDefaultBehaviorFlagsConfiguration();
295
296 6721 ppiqueras
                // Create attributes and set initial values
297
                this.initialize();
298
299
                // Sets the options selected by the user
300
                this.model.setStartBehavior(start_Behavior);
301
                this.model.setStartBehavior(search_Behavior);
302 8765 jjdelcerro
                this.model.setCaseSensitive_Flag(case_Sensitive);
303 6721 ppiqueras
304
                if (!testFlagsConfigurationOK())
305 7244 cesar
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
306 6721 ppiqueras
                else
307 8765 jjdelcerro
                {
308
                        // Other configuration tasks
309
                        this.createDefaultListeners();
310 6721 ppiqueras
                        this.configure();
311 8765 jjdelcerro
                }
312 6721 ppiqueras
        }
313
314
        /**
315 9089 ppiqueras
          * Default Constructor with 11 parameters
316 6721 ppiqueras
         *
317 9089 ppiqueras
         * @param 'start_Behavior', Start behavior of the Model.
318
         * @param 'search_Behavior', Search behavior of the Model.
319
         * @param 'case_Sensitive', Case sensitive behavior of the Model.
320
         * @param 'only_One_Color_On_Text', Text color, behavior of the Control/View.
321
         * @param 'complete_Matched_Item', Complete matched item, behavior of the Control/View.
322
         * @param 'use_Beep Use beep', behavior of the Control.
323
         * @param 'allowed_Repeated_Items', Allowed repeated items, behavior of the Control/Model.
324
         * @param 'allowed_Mouse_Edition_Popup_Menu', Allowed mouse edition popupmenu, behavior of the Control/View.
325
         * @param 'to_Force_To_Only_Coincidences_In_The_Search', To force to only coincidences in the search, behavior of the Control/View.
326
         * @param 'use_Highlight', Use highlight behavior of the Control/View.
327
         * @param 'select_An_Item_When_Loses_Focus', behavior of the Control/View
328 6721 ppiqueras
         */
329 9089 ppiqueras
        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, boolean select_An_Item_When_Loses_Focus_Flag) {
330 6721 ppiqueras
                // Invokes to the parent class constructor
331 8765 jjdelcerro
                super();
332
333
                this.onlyOneColorOnText_Flag = only_One_Color_On_Text;
334
                this.completeMatchedItem_Flag = complete_Matched_Item;
335
                this.beepEnabled_Flag = use_Beep;
336
                this.allowedRepeatedItems_Flag = allowed_Repeated_Items;
337
                this.allowedMouseEditionPopupMenu_Flag = allowed_Mouse_Edition_Popup_Menu;
338
                this.toForceToOnlyCoincidencesInTheSearch_Flag = to_Force_To_Only_Coincidences_In_The_Search;
339
                this.useHighlight_Flag = use_Highlight;
340 9089 ppiqueras
                this.selectAnItemWhenLosesFocus_Flag = select_An_Item_When_Loses_Focus_Flag;
341 6721 ppiqueras
342
                // Create attributes and set initial values
343
                this.initialize();
344 8765 jjdelcerro
345 6721 ppiqueras
                // Sets the options selected by the user
346
                this.model.setStartBehavior(start_Behavior);
347 8765 jjdelcerro
                this.model.setSearchBehavior(search_Behavior);
348
                this.model.setCaseSensitive_Flag(case_Sensitive);
349 6721 ppiqueras
350
                if (!testFlagsConfigurationOK())
351 7244 cesar
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
352 6721 ppiqueras
                else
353 8765 jjdelcerro
                {
354
                        // Other configuration tasks
355
                        this.createDefaultListeners();
356 6721 ppiqueras
                        this.configure();
357 8765 jjdelcerro
                }
358 6721 ppiqueras
        }
359
360
        /**
361 8765 jjdelcerro
         *  Sets the default values of the flags
362 6721 ppiqueras
         */
363 8765 jjdelcerro
        private void setDefaultBehaviorFlagsConfiguration() {
364
                this.onlyOneColorOnText_Flag = DEFAULT_ONLY_ONE_COLOR_ON_TEXT_CONFIGURATION;
365
                this.completeMatchedItem_Flag = DEFAULT_COMPLETE_MATCHED_ITEM_CONFIGURATION;
366
                this.beepEnabled_Flag = DEFAULT_BEEP_ENABLED_CONFIGURATION;
367
                this.allowedRepeatedItems_Flag = DEFAULT_ALLOWED_REPEATED_ITEMS_CONFIGURATION;
368
                this.allowedMouseEditionPopupMenu_Flag = DEFAULT_ALLOWED_MOUSE_EDITION_POPUP_MENU_CONFIGURATION;
369
                this.toForceToOnlyCoincidencesInTheSearch_Flag = DEFAULT_TO_FORCE_TO_ONLY_COINCIDENCES_IN_THE_SEARCH_CONFIGURATION;
370
                this.useHighlight_Flag = DEFAULT_USE_HIGHLIGHT_CONFIGURATION;
371 9089 ppiqueras
                this.selectAnItemWhenLosesFocus_Flag = DEFAULT_SELECT_AN_ITEM_WHEN_LOSES_FOCUS_CONFIGURATION;
372 8765 jjdelcerro
        }
373
374
        /**
375 9089 ppiqueras
         * This method sets the start values of inner attributes and creates the necessary inner objects
376 8765 jjdelcerro
         */
377 6721 ppiqueras
        private void initialize() {
378 8765 jjdelcerro
                // Attributes for highlight selection
379
                selecting = false;
380
                hitBackspace = false;
381 6721 ppiqueras
382
                // Creates the model for this component and gets it reference
383 8765 jjdelcerro
                if (this.allowedRepeatedItems_Flag)
384 6755 ppiqueras
                {
385
                        super.setModel(new ComboBoxItemsSeekerConfigurableModel());
386
                        this.model = (ComboBoxItemsSeekerConfigurableModel) super.getModel();
387
                }
388
                else
389
                {
390
                        super.setModel(new ComboBoxSingularItemsSeekerConfigurableModel());
391
                        this.model = (ComboBoxSingularItemsSeekerConfigurableModel) super.getModel();
392
                }
393 6721 ppiqueras
394
        // Allows user to edit on the combobox
395
                super.setEditable(true);
396
397
                // By default the last state of showign items was showing all the items (at the beginning of this component)
398
                currentShowState = BEGINNING_VIEW_STATE;
399
400
                // Set the last selected item -> if there isn't any item -> -1; else -> this will be 0
401
                super.setSelectedIndex(-1);
402
403
                // By default any text key has been pressed
404 8765 jjdelcerro
                allowInsertString = false;
405 6721 ppiqueras
406 8765 jjdelcerro
                // Attribute for allow composed characters: examples: ?, ?, ?
407 6756 ppiqueras
                lastWasPressedAKeyModifier = false;
408 6721 ppiqueras
409 6756 ppiqueras
                // By default popup won't be visible when gained the focus the editor associated
410
                popupWillBeVisible = false;
411
412 8765 jjdelcerro
                // Text options edition popupmenu initialization
413 6816 ppiqueras
                optionsEditionByMouse = new JOptionsEditionByMousePopupMenu();
414 6793 ppiqueras
                optionsEditorWasVisible = false;
415
416 8765 jjdelcerro
                // Undo-Redo initialization
417
                addUndoableEditEvent = false; // By default don't add undoable edit events
418 6816 ppiqueras
                undoManager = new UndoManager();
419
                undoRedoLimitActions = 10; // By default is 1
420
                undoManager.setLimit(undoRedoLimitActions);
421
422 8765 jjdelcerro
                // By default this flag will be 'true'
423
                firstTimeItGainsFocusWithData = true;
424 6721 ppiqueras
425 8765 jjdelcerro
                // By default this component won't be in the "SpecialSelectionByUser" state
426
                specialSelectionByUserState = false;
427 6721 ppiqueras
428 8765 jjdelcerro
                // By default no 'cut' operation has been done
429
                cutOperationDone = false;
430 6793 ppiqueras
431 8765 jjdelcerro
                // By default no item items has been selected by mouse
432
                itemSelectedByMouse = false;
433 6721 ppiqueras
        }
434
435
        /**
436 8765 jjdelcerro
         * Creation of default listeneres that will use the component
437 6721 ppiqueras
         */
438
        private void createDefaultListeners() {
439 8765 jjdelcerro
                // Defines a listener for the PopupMenu of text edition options: when a change is produced in that component, it fires an event
440
                //   and this listener captures it
441 6793 ppiqueras
                this.defineEditionMenuPropertyChangeListener(this);
442
443 8765 jjdelcerro
        // Defines a key listener for the editor of this component
444 6721 ppiqueras
        this.defineEditorKeyListener(this);
445
446 8765 jjdelcerro
        // Defines a focus listener for the editor of this component
447 6721 ppiqueras
        this.defineEditorFocusListener(this);
448
449 8765 jjdelcerro
        // Defines a mouse listener for the editor of this component
450 6793 ppiqueras
        this.defineEditorMouseListener(this);
451
452 8765 jjdelcerro
        // Defines a mouse wheel listener for the editor of this component
453
        this.defineEditorMouseWheelListener();
454
455
        // Defines a document listener for changes of text
456 6721 ppiqueras
        this.defineDocumentListener();
457
458 8765 jjdelcerro
                // Defines a list data listener for the model of this component
459 6721 ppiqueras
        this.defineModelListDataListener();
460
461 8765 jjdelcerro
        // Defines a popup menu listener for the popup of this component
462
        this.definePopUpMenuListener();
463 6721 ppiqueras
        }
464
465 8765 jjdelcerro
466 6816 ppiqueras
        /**
467 8765 jjdelcerro
         * Defines a listener for the PopupMenu of text edition options: when a change is produced in that component, it fires an event
468
         *    and this listener captures and treats it
469
         *
470
         * @param combo_Box A reference of this component
471 6816 ppiqueras
         */
472 6793 ppiqueras
        private void defineEditionMenuPropertyChangeListener(JComboBoxItemsSeekerConfigurable combo_Box) {
473
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
474 8765 jjdelcerro
475 6793 ppiqueras
                editionMenuListener = new PropertyChangeListener() {
476 8765 jjdelcerro
                        /*
477
                         * (non-Javadoc)
478
                         * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
479
                         */
480 6793 ppiqueras
                        public void propertyChange(PropertyChangeEvent arg0) {
481 6816 ppiqueras
                                if (arg0.getPropertyName().equals(JOptionsEditionByMousePopupMenu.SELECTEDOPTION)) {
482 6793 ppiqueras
                            JTextComponent editor = (JTextComponent) comboBoxReference.getEditor().getEditorComponent();
483
484
                            logger.debug("PropertyChanged: " + arg0.getNewValue().toString());
485
486
                                  switch(Integer.parseInt(arg0.getNewValue().toString()))
487 8765 jjdelcerro
                                  {
488 6816 ppiqueras
                                          case JOptionsEditionByMousePopupMenu.UNDO:
489 8765 jjdelcerro
                                                  undoOperationLogic();
490 6793 ppiqueras
                                                  break;
491 6816 ppiqueras
                                          case JOptionsEditionByMousePopupMenu.REDO:
492 8765 jjdelcerro
                                                  redoOperationLogic();
493 6793 ppiqueras
                                                  break;
494 6816 ppiqueras
                                          case JOptionsEditionByMousePopupMenu.CUT:
495
                                                  editor.cut();
496 8765 jjdelcerro
                                                  cutOperationDone = true;
497
                                                  deleteTextLogic(editor, false);
498 6793 ppiqueras
                                                  break;
499 6816 ppiqueras
                                          case JOptionsEditionByMousePopupMenu.COPY:
500
                                                  editor.copy();
501 6793 ppiqueras
                                                  break;
502 6816 ppiqueras
                                          case JOptionsEditionByMousePopupMenu.PASTE:
503
                                                  editor.paste();
504 8765 jjdelcerro
505
                                                  try {
506
                                                          String newPattern = document.getText(0, document.getLength());
507
                                                          model.setWrittenText(newPattern);
508
                                                          updatePopUpView();
509
                                                  } catch (BadLocationException e) {
510
                                                          e.printStackTrace();
511
                                                  }
512 6793 ppiqueras
                                                  break;
513 6816 ppiqueras
                                          case JOptionsEditionByMousePopupMenu.DELETE:
514 8765 jjdelcerro
                                                  deleteTextLogic(editor, false);
515 6793 ppiqueras
                                                  break;
516 6816 ppiqueras
                                          case JOptionsEditionByMousePopupMenu.SELECT_ALL:
517 6793 ppiqueras
                                                  editor.selectAll();
518
                                                  break;
519
                                          default: // do anything
520
                                  }
521
                                }
522
                                else
523
                                {
524 6816 ppiqueras
                                        if (arg0.getPropertyName().equals(JOptionsEditionByMousePopupMenu.VISIBILITYCHANGED))
525 6793 ppiqueras
                                        {
526
                                                logger.debug("PropertyChanged: " + arg0.getNewValue().toString());
527
528
                                                // First True, after False (when false -> optionsEditorWasVisible = true)
529
                                                if (!optionsEditionByMouse.isVisible())
530
                                                        optionsEditorWasVisible = true;
531
                                                else
532
                                                        optionsEditorWasVisible = false;
533
                                        }
534
                                }
535
                        }
536
                };
537 8765 jjdelcerro
        }
538 6793 ppiqueras
539 6721 ppiqueras
        /**
540 8765 jjdelcerro
         *  Defines a document listener for changes of text
541 6721 ppiqueras
         */
542
        private void defineDocumentListener() {
543 8765 jjdelcerro
       documentListener = new DocumentListener() {
544
               /*
545
                * (non-Javadoc)
546
                * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
547
                */
548
               public void changedUpdate(DocumentEvent arg0) {
549
               }
550 6721 ppiqueras
551 8765 jjdelcerro
               /*
552
                * (non-Javadoc)
553
                * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
554
                */
555
               public void insertUpdate(DocumentEvent arg0) {
556
                       logger.debug("NUM: " + num + " DocumentListener->insertUpdate");
557
                       num++;
558 6756 ppiqueras
559 8765 jjdelcerro
                       // Indicate to the model that now is disabled the start view
560
                       // 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
561
                       if (currentShowState == BEGINNING_VIEW_STATE)
562
                       {
563
                               currentShowState = START_VIEW_STATE;
564
                               lastWasTheBeginningState = true;
565
                               logger.debug("Pasa al estado 1 (de vista inicial)");
566
                       }
567
               }
568 6721 ppiqueras
569 8765 jjdelcerro
               /*
570
                * (non-Javadoc)
571
                * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
572
                */
573
               public void removeUpdate(DocumentEvent arg0) {
574
                       logger.debug("NUM: " + num + " DocumentListener->removeUpdate");
575
                       num++;
576
               }
577
       };
578 6721 ppiqueras
        }
579
580
        /**
581 8765 jjdelcerro
         * Defines a list data listener for the model of this component
582 6721 ppiqueras
         */
583 8765 jjdelcerro
        private void defineModelListDataListener() {
584 6721 ppiqueras
                this.modelListDataListener = new ListDataListener()        {
585 8765 jjdelcerro
                        /*
586
                         * (non-Javadoc)
587
                         * @see javax.swing.event.ListDataListener#contentsChanged(javax.swing.event.ListDataEvent)
588
                         */
589 6721 ppiqueras
                        public void contentsChanged(ListDataEvent e) {
590
                                // This flag indicates to the 'insertString' and 'remove' methods of the PlainDocumentSeeker that the text of the item selected or written by the user
591
                                //  hasn't been written on the TextEditor of ths component
592
                                selecting = false;
593
                        }
594
595 8765 jjdelcerro
                        /*
596
                         * (non-Javadoc)
597
                         * @see javax.swing.event.ListDataListener#intervalAdded(javax.swing.event.ListDataEvent)
598
                         */
599 6721 ppiqueras
                        public void intervalAdded(ListDataEvent e) {
600
                        }
601
602 8765 jjdelcerro
                        /*
603
                         * (non-Javadoc)
604
                         * @see javax.swing.event.ListDataListener#intervalRemoved(javax.swing.event.ListDataEvent)
605
                         */
606 6721 ppiqueras
                        public void intervalRemoved(ListDataEvent e) {
607 8765 jjdelcerro
                        }
608 6721 ppiqueras
                };
609
    }
610
611
        /**
612 8765 jjdelcerro
         * Defines and add a property change listener for this component (AT MOMENT NOT USED!!)
613 6721 ppiqueras
         */
614
        private void defineAndAddPropertyChangeListener() {
615
                // Define and add a Listener for changes on the editor or the model of the JComboBox
616
        super.addPropertyChangeListener(new PropertyChangeListener() {
617
            public void propertyChange(PropertyChangeEvent ev) {
618
                if (ev.getPropertyName().equals("editor"))
619
                        configureEditor((ComboBoxEditor) ev.getNewValue());
620
                if (ev.getPropertyName().equals("model"))
621 6755 ppiqueras
                {
622 8765 jjdelcerro
                        if (isAllowedRepeatedItems_Flag())
623 6755 ppiqueras
                                model = (ComboBoxItemsSeekerConfigurableModel) ev.getNewValue();
624
                        else
625
                                model = (ComboBoxSingularItemsSeekerConfigurableModel) ev.getNewValue();
626
                }
627 6721 ppiqueras
            }
628
        });
629
        }
630
631
        /**
632 8765 jjdelcerro
         * Defines a focus listener for the editor of this component
633
         *
634
         * @param combo_Box A reference of this component
635 6721 ppiqueras
         */
636
        private void defineEditorFocusListener(JComboBoxItemsSeekerConfigurable combo_Box) {
637 6756 ppiqueras
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
638 6721 ppiqueras
639 8765 jjdelcerro
                // Bug 5100422 on Java 1.5: Editable JComboBox won't hide popup when tabbing out
640 6756 ppiqueras
                hidePopupOnFocusLoss=System.getProperty("java.version").startsWith("1.5");
641 8765 jjdelcerro
642 6721 ppiqueras
                // Highlight whole text when gaining focus
643
                editorFocusListener = new FocusAdapter() {
644 8765 jjdelcerro
                        /*
645
                         * (non-Javadoc)
646
                         * @see java.awt.event.FocusAdapter#focusGained(java.awt.event.FocusEvent)
647
                         */
648 6721 ppiqueras
                        public void focusGained(FocusEvent e) {
649 6793 ppiqueras
                                if (!optionsEditorWasVisible)
650 6756 ppiqueras
                                {
651 6793 ppiqueras
                                        logger.debug("currentShowState: " + currentShowState);
652
                                        logger.debug("EDITOR FOCUS GAINED");
653
654 8765 jjdelcerro
                                        // This is used for set the text value of the first item added highlighted the first time the component gets the focus
655
                                        if (firstTimeItGainsFocusWithData) {
656
                                                if (model.getSize() > 0) {
657
                                                        if (useHighlight_Flag)
658
                                                                document.highlightCompletedText(0);
659
                                                        firstTimeItGainsFocusWithData = false;
660
                                                }
661
                                        }
662
663
                                        // This is used when the component has lost the focus, the popup was in show state and is restored the focus -> update the popup
664 6793 ppiqueras
                                        if (popupWillBeVisible)
665
                                        {
666
                                                logger.debug("UPDATE POPUP DESDE EL FOCUSGAINED");
667
                                                comboBoxReference.updatePopUpView();
668
                                        }
669 6756 ppiqueras
                                }
670 6721 ppiqueras
                        }
671
672 8765 jjdelcerro
                        /*
673
                         * (non-Javadoc)
674
                         * @see java.awt.event.FocusAdapter#focusLost(java.awt.event.FocusEvent)
675
                         */
676 6721 ppiqueras
                        public void focusLost(FocusEvent e) {
677 6756 ppiqueras
                                logger.debug("EDITOR FOCUS LOST");
678
679 9089 ppiqueras
                                // If it has to select an item always it loses its focus:
680
                                if (selectAnItemWhenLosesFocus_Flag) {
681
                                        // Similar code as the ENTER key code
682
                                        if (getSelectedItem() == null)
683
                                                logger.debug("SELECTED ITEM: NULL");
684
                                        else
685
                                                logger.debug("SELECTED ITEM: " + getSelectedItem().toString());
686
687
                                        try {
688
                                                String newText = "";
689
690
                                                Object moreSimilarItemToLastWrittenText = model.getMoreSimilarItemToLastWrittenText();
691
692
                                                // If the last item selected was null -> select the first
693
                                                if (moreSimilarItemToLastWrittenText == null) {
694
                                                        setSelectedItem(model.getParentElementAt(0));
695
                                                }
696
                                                else {
697
                                                        if (specialSelectionByUserState) {
698
                                                                setSelectedItem(model.getSelectedItem());
699
                                                        }
700
                                                        else {
701
                                                                // Else -> select the last
702
                                                                setSelectedItem(moreSimilarItemToLastWrittenText);
703
                                                        }
704
                                                }
705
706
                                                newText = getSelectedItem().toString();
707
708
                                                // Reports about the written text to the model
709
                                            if (model.isDynamicSearch())
710
                                                    model.setWrittenText(newText);
711
712
                                                specialSelectionByUserState = false;
713
714
                                                document.replace(0, document.getLength(), newText, null);
715
                                        }
716
                                        catch (BadLocationException e1) {
717
                                            e1.printStackTrace();
718
                                    }
719
720
//                                    // Indicate to the model that now is disabled the start view
721
//                                        if (currentShowState == START_VIEW_STATE)
722
//                                        {
723
//                                                model.setStartStateFlag(false);
724
//                                                currentShowState = SEARCH_VIEW_STATE;
725
//                                        }
726
                                        hidePopup();
727
728
                                        // Sets the caret position of the text in the document to the end:
729
                                        ((JTextComponent) comboBoxReference.getEditor().getEditorComponent()).setCaretPosition(document.getLength());
730
                                }
731
                                else { // Else -> Default bevabior
732
                                        if (isPopupVisible())
733
                                                popupWillBeVisible = true;
734
                                        else
735
                                                popupWillBeVisible = false;
736
                                }
737 6756 ppiqueras
738 6721 ppiqueras
                                // Workaround for Bug 5100422 - Hide Popup on focus loss
739 9089 ppiqueras
                                if (hidePopupOnFocusLoss)
740
                                        comboBoxReference.setPopupVisible(false);
741 6721 ppiqueras
                        }
742
                };
743
        }
744 8765 jjdelcerro
745
        /**
746
         * Defines a mouse listener for the editor of this component
747
         *
748
         * @param combo_Box A reference of this component
749
         */
750 6793 ppiqueras
        private void defineEditorMouseListener(JComboBoxItemsSeekerConfigurable combo_Box) {
751
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
752
753 8765 jjdelcerro
                editorMouseListener = new MouseAdapter() {
754
                        /*
755
                         * (non-Javadoc)
756
                         * @see java.awt.event.MouseAdapter#mouseClicked(java.awt.event.MouseEvent)
757
                         */
758 6816 ppiqueras
                        public void mouseClicked(MouseEvent e) {
759
                                logger.debug("MOUSE-LISTENER : MOUSE-mouseClicked!" + e.getButton());
760
                                logger.debug("MOUSE-LISTENER : MOUSE-mouseClicked!" +e.isPopupTrigger());
761 8765 jjdelcerro
762 6816 ppiqueras
                                if (e.getButton() == MouseEvent.BUTTON3) {
763 6793 ppiqueras
                            JTextComponent editor = (JTextComponent) comboBoxReference.getEditor().getEditorComponent();
764
765
                            // By default disable all options
766
                            optionsEditionByMouse.setEnabledAllOptions(false);
767
768 6816 ppiqueras
                            // Enable the "Undo" option if there is any previous state to restore
769
                            if (undoManager.canUndo())
770
                                    optionsEditionByMouse.setEnabledUndoOption(true);
771
772
                            // Enable the "Redo" option if there is any later state to restore
773
                            if (undoManager.canRedo())
774
                                    optionsEditionByMouse.setEnabledRedoOption(true);
775
776
                            // Enable the "Copy", "Cut" and "Delete" options if there is text selected
777 6793 ppiqueras
                            if (editor.getCaretPosition() != editor.getCaret().getMark())
778 6816 ppiqueras
                            {
779
                                    optionsEditionByMouse.setEnabledCopyOption(true);
780
                                    optionsEditionByMouse.setEnabledCutOption(true);
781 6793 ppiqueras
                                    optionsEditionByMouse.setEnabledDeleteOption(true);
782 6816 ppiqueras
                            }
783 6793 ppiqueras
784 6816 ppiqueras
                            // Enable the "Paste" option if there is text on the system's clipboard
785
                            if ( getToolkit().getSystemClipboard().getContents(this).toString().length() > 0 )
786
                                    optionsEditionByMouse.setEnabledPasteOption(true);
787
788 6793 ppiqueras
                            // Enable the "Select-All" option (by default it's always enabled)
789
                            optionsEditionByMouse.setEnabledSelectAllOption(true);
790
791
                                        optionsEditionByMouse.setLocation((int)comboBoxReference.getLocationOnScreen().getX() + e.getX(), (int)comboBoxReference.getLocationOnScreen().getY() + e.getY());
792
                            optionsEditionByMouse.setInvoker(comboBoxReference);
793
                            optionsEditionByMouse.setVisible(true);
794
                    }
795
                }
796
                };
797
        }
798
799 6721 ppiqueras
        /**
800 8765 jjdelcerro
         * Defines a mouse wheel listener for the editor of this component
801
         */
802
        private void defineEditorMouseWheelListener() {
803
                editorMouseWheelListener = new MouseWheelListener() {
804
                        /*
805
                         * (non-Javadoc)
806
                         * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
807
                         */
808
                        public void mouseWheelMoved(MouseWheelEvent e) {
809
                                specialSelectionByUserState = true;
810
811
                        if (e.getWheelRotation() < 0)
812
                                selectItemUp();
813
                        else
814
                                selectItemDown();
815
                        }
816
                };
817
        }
818
819
        /**
820
         * Defines a key listener for the editor of this component
821
         * This method is another important difference from the JComboBox; and could work badly with some keymaps
822 6721 ppiqueras
         *
823 8765 jjdelcerro
         * @param combo_Box A reference of this component
824 6721 ppiqueras
         */
825
        private void defineEditorKeyListener(JComboBoxItemsSeekerConfigurable combo_Box) {
826
                final JComboBoxItemsSeekerConfigurable comboBoxReference = combo_Box;
827
828 8765 jjdelcerro
                editorKeyListener = new KeyAdapter() {
829
                        /*
830
                         * (non-Javadoc)
831
                         * @see java.awt.event.KeyAdapter#keyPressed(java.awt.event.KeyEvent)
832
                         */
833 6721 ppiqueras
                        public void keyPressed(KeyEvent ke)  // Executed on the Start view state or Search view state
834
                        {
835 6756 ppiqueras
                                logger.debug("Tecla apretada: ->" + ke.getKeyChar() + "<- ; Su keyCode es: " + ke.getKeyCode() + " TIPO: " + Character.getType(ke.getKeyChar()));
836
837 6721 ppiqueras
                                if (model.getParentSize() == 0)
838
                                {
839 8765 jjdelcerro
                                        if (beepEnabled_Flag)
840 6721 ppiqueras
                                                comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
841
                                }
842
                                else
843 6791 ppiqueras
                                {
844 6721 ppiqueras
                                        // This flag indicates to the 'insertString' and 'remove' methods of the PlainDocumentSeeker that the text of the item selected or written by the user
845
                                        //  hasn't been written on the TextEditor of ths component
846
                                        selecting = false;
847
848
                                        // 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
849
                                        //  aren't seen
850
                                        if (lastWasTheBeginningState)
851
                                        {
852
                                                // This maintains visible the popup
853
                                                if (comboBoxReference.isDisplayable())
854
                                                        comboBoxReference.setPopupVisible(true);
855
                                                lastWasTheBeginningState = false;
856
                                        }
857
858 6756 ppiqueras
                                        if (Character.isLetterOrDigit(ke.getKeyChar())) {
859
                                                logger.debug("IS LETTER OR DIGIT");
860
                                        }
861
                                        else
862
                                                logger.debug("ISN'T LETTER OR DIGIT");
863
864 6721 ppiqueras
                                        JTextComponent editor = (JTextComponent) comboBoxReference.getEditor().getEditorComponent();
865
866 8765 jjdelcerro
                                        // COPY, CUT, PASTE, SELECT ALL, UNDO AND REDO WITH THE KEYBOARD (Combination of keys; REMOVE is implemented after: KV_DELETE (supr spanish key))
867
                                        if (ke.isControlDown())
868
                                        {
869
                                                // COPY
870
                                            if (ke.getKeyCode() == KeyEvent.VK_C) {
871
                                                editor.copy();
872
                                                    return;
873
                                            }
874
875
                                            // CUT
876
                                            if (ke.getKeyCode() == KeyEvent.VK_X) {
877
                                                      editor.cut();
878
879
                                                  cutOperationDone = true;
880
                                                  deleteTextLogic(editor, false);
881
                                                    return;
882
                                            }
883
884
                                            // PASTE
885
                                            if (ke.getKeyCode() == KeyEvent.VK_V) {
886
                                                    editor.paste();
887
888
                                          try {
889
                                                  String newPattern = document.getText(0, document.getLength());
890
                                                  model.setWrittenText(newPattern);
891
                                                  updatePopUpView();
892
                                          } catch (BadLocationException e) {
893
                                                  e.printStackTrace();
894
                                          }
895
                                                    return;
896
                                            }
897
898
                                            // SELECT ALL
899
                                            if (ke.getKeyCode() == KeyEvent.VK_A) {
900
                                                    editor.selectAll();
901
                                                    return;
902
                                            }
903
904
                                            // UNDO OR REDO
905
                                            if (ke.getKeyCode() == KeyEvent.VK_Z) {
906
                                                    if (ke.isShiftDown()) // REDO
907
                                                            redoOperationLogic();
908
                                                    else //UNDO
909
                                                            undoOperationLogic();
910
911
                                                    return;
912
                                             }
913
                                        }
914 6756 ppiqueras
915 8765 jjdelcerro
                                        // According the key pressed, do some actions or others
916
                                        switch (ke.getKeyCode())
917
                                        {
918
                                                // determine if the pressed key is backspace (needed by the remove method)
919
                                                case KeyEvent.VK_BACK_SPACE :
920
                                                                 if (useHighlight_Flag)
921
                                                                {
922
                                                                         hitBackspace = true;
923
                                                                         hitBackspaceOnSelection=editor.getSelectionStart()!=editor.getSelectionEnd();
924
                                                                }
925
                                                                 else
926
                                                                         deleteTextLogic(editor, true);
927
                                                        break;
928
929
                                                case KeyEvent.VK_DELETE : // 'supr' key in spanish keyboard
930
                                                                specialSelectionByUserState = true;
931
932
                                                        deleteTextLogic(editor, false);
933
                                                        break;
934
935
                                                case KeyEvent.VK_ENTER :
936
                                                        logger.debug("ENTRA EN EL C?DIGO DE ENTER");
937
938
                                                        if (getSelectedItem() == null)
939
                                                                logger.debug("SELECTED ITEM: NULL");
940
                                                        else
941
                                                                logger.debug("SELECTED ITEM: " + getSelectedItem().toString());
942 6721 ppiqueras
943 8765 jjdelcerro
                                                        try {
944
                                                                String newText = "";
945 6756 ppiqueras
946 8765 jjdelcerro
                                                                Object moreSimilarItemToLastWrittenText = model.getMoreSimilarItemToLastWrittenText();
947
948
                                                                // If the last item selected was null -> select the first
949
                                                                if (moreSimilarItemToLastWrittenText == null) {
950
                                                                        setSelectedItem(model.getParentElementAt(0));
951 6754 ppiqueras
                                                                }
952 8765 jjdelcerro
                                                                else {
953
                                                                        if (specialSelectionByUserState) {
954
                                                                                setSelectedItem(model.getSelectedItem());
955 6754 ppiqueras
                                                                        }
956 8765 jjdelcerro
                                                                        else {
957
                                                                                // Else -> select the last
958
                                                                                setSelectedItem(moreSimilarItemToLastWrittenText);
959
                                                                        }
960
                                                                }
961 6721 ppiqueras
962 8765 jjdelcerro
                                                                newText = getSelectedItem().toString();
963 6721 ppiqueras
964 8765 jjdelcerro
                                                                // Reports about the written text to the model
965
                                                            if (model.isDynamicSearch())
966
                                                                    model.setWrittenText(newText);
967 6756 ppiqueras
968 8765 jjdelcerro
                                                                specialSelectionByUserState = false;
969 6756 ppiqueras
970 8765 jjdelcerro
                                                                document.replace(0, document.getLength(), newText, null);
971
                                                        }
972
                                                        catch (BadLocationException e1) {
973
                                                            e1.printStackTrace();
974
                                                    }
975
976
                                                    // Indicate to the model that now is disabled the start view
977
                                                        if (currentShowState == START_VIEW_STATE)
978
                                                        {
979
                                                                model.setStartStateFlag(false);
980
                                                                currentShowState = SEARCH_VIEW_STATE;
981
                                                        }
982
                                                        hidePopup();
983
984
                                                        // Sets the caret position of the text in the document to the end:
985
                                                        editor.setCaretPosition(document.getLength());
986
                                                        break;
987
988
                                                case KeyEvent.VK_DOWN :
989
                                                        selectItemDown();
990
                                                        showPopup();
991
                                                        break;
992
993
                                                case KeyEvent.VK_UP :
994
                                                        selectItemUp();
995
                                                        showPopup();
996
                                                        break;
997
998
                                                case KeyEvent.VK_LEFT :
999
                                                        // Move the caret to left
1000
                                                        int caretPosition = editor.getCaretPosition();
1001
                                                        if (caretPosition > 0)
1002
                                                        {
1003
                                                                if (useHighlight_Flag) {
1004
                                                                        editor.setCaretPosition(document.getLength());
1005
                                                                        editor.moveCaretPosition(caretPosition - 1);
1006 6721 ppiqueras
                                                                }
1007 8765 jjdelcerro
                                                                else
1008
                                                                        editor.setCaretPosition(caretPosition - 1);
1009
                                                        }
1010
                                                        else
1011
                                                        {
1012
                                                // User hit backspace with the cursor positioned on the start => beep
1013
                                                    if (beepEnabled_Flag)
1014
                                                            getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
1015
                                                        }
1016
1017
                                                        break;
1018
1019
                                                case  KeyEvent.VK_RIGHT :
1020
                                                        // Move the caret to right
1021
                                                        caretPosition = editor.getCaretPosition();
1022
                                                        if (caretPosition < document.getLength()) {
1023
                                                                if (useHighlight_Flag) {
1024
                                                                        editor.setCaretPosition(document.getLength());
1025
                                                                        editor.moveCaretPosition(caretPosition + 1);
1026
                                                                }
1027
                                                                else
1028
                                                                        editor.setCaretPosition(caretPosition + 1);
1029
                                                        }
1030
                                                        else
1031
                                                        {
1032
                                                            // User hit backspace with the cursor positioned on the start => beep
1033
                                                                if (beepEnabled_Flag)
1034
                                                                        getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
1035
                                                        }
1036
1037
                                                        break;
1038
1039
                                                case  KeyEvent.VK_PAGE_DOWN :
1040
                                                        if (getItemCount() > 0)
1041
                                                        {
1042
                                                                int index;
1043
                                                                specialSelectionByUserState = true;
1044 6721 ppiqueras
1045 8765 jjdelcerro
                                                                if (getSelectedIndex() == -1)
1046
                                                                        index = 0;
1047
                                                                else
1048
                                                                        index = getSelectedIndex() + POPUP_LIST_ITEMS_HEIGHT;
1049 6721 ppiqueras
1050 8765 jjdelcerro
                                                                if (index < getItemCount())
1051
                                                                        setSelectedIndex(index);
1052
                                                                else
1053
                                                                        setSelectedIndex(getItemCount()-1);
1054
                                                        }
1055
                                                        break;
1056
1057
                                                case KeyEvent.VK_PAGE_UP :
1058
                                                        if (getItemCount() > 0)
1059
                                                        {
1060
                                                                int index;
1061
                                                                specialSelectionByUserState = true;
1062 6793 ppiqueras
1063 8765 jjdelcerro
                                                                if (getSelectedIndex() == -1)
1064
                                                                        index = getItemCount() - 1;
1065
                                                                else
1066
                                                                        index = getSelectedIndex() - POPUP_LIST_ITEMS_HEIGHT;
1067 6721 ppiqueras
1068 8765 jjdelcerro
                                                                if (index > -1)
1069
                                                                        setSelectedIndex(index);
1070
                                                                else
1071
                                                                        setSelectedIndex(0);
1072
                                                        }
1073
                                                        break;
1074
1075
                                                case KeyEvent.VK_HOME : // 'Inicio' key on the spanish keyboard
1076
                                                        editor.setCaretPosition(0);
1077
                                                        break;
1078
1079
                                                case KeyEvent.VK_END :  // 'Fin' key on the spanish keyboard
1080
                                                        editor.setCaretPosition(document.getLength());
1081
                                                        break;
1082
1083
                                                case KeyEvent.VK_TAB :
1084
                                                        // This avoids that popup listener could report about it detected item
1085
                                                        allowInsertString = true;
1086
1087
                                                        if (model.getParentSize() > 0)
1088
                                                        {
1089
                                                                Object selectedItem;
1090 6721 ppiqueras
1091 8765 jjdelcerro
                                                                if (specialSelectionByUserState)
1092
                                                                        selectedItem = getSelectedItem();
1093
                                                                else
1094 8996 ppiqueras
                                                                        selectedItem = model.getParentElementAt(0);
1095 6721 ppiqueras
1096 8765 jjdelcerro
                                                                String selectedItemName = "";
1097 6756 ppiqueras
1098
                                                                try {
1099 8765 jjdelcerro
1100
                                                                        if (selectedItem == null)
1101
                                                                                selectedItemName = model.getFirstItemAdded().toString();
1102 6756 ppiqueras
                                                                        else
1103 8765 jjdelcerro
                                                                                selectedItemName = selectedItem.toString();
1104
1105
                                                                                document.replace(0, document.getLength(), selectedItemName, null);
1106 6756 ppiqueras
                                                                } catch (BadLocationException e) {
1107
                                                                        e.printStackTrace();
1108
                                                                }
1109 6721 ppiqueras
1110 8765 jjdelcerro
                                                                if (model.isDynamicSearch()) {
1111
                                                                        model.setWrittenText(selectedItemName);
1112
                                                                        logger.debug("Texto que se le env?a al modelo: ->" + selectedItemName + "<-");
1113
                                                                }
1114 6756 ppiqueras
1115 8765 jjdelcerro
                                                                if (currentShowState == START_VIEW_STATE)
1116 6756 ppiqueras
                                                                {
1117 8765 jjdelcerro
                                                                        model.setStartStateFlag(false);
1118
                                                                        currentShowState = SEARCH_VIEW_STATE;
1119 6756 ppiqueras
                                                                }
1120 8765 jjdelcerro
1121
                                                                // 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
1122
                                                                comboBoxReference.getEditor().getEditorComponent().setForeground(Color.BLACK);
1123
1124 6756 ppiqueras
                                                                updatePopUpView();
1125 8765 jjdelcerro
                                                        }
1126
                                                        break;
1127 6721 ppiqueras
1128 8765 jjdelcerro
                                                case KeyEvent.VK_ESCAPE :
1129
                                                        specialSelectionByUserState = false;
1130
1131
                                                        // Force update the popup
1132
                                                        if (isPopupVisible())
1133
                                                                hidePopup();
1134 6721 ppiqueras
1135 8765 jjdelcerro
                                                        model.setWrittenText("");
1136
1137
                                                        if (currentShowState == SEARCH_VIEW_STATE)
1138
                                                        {
1139
                                                                try {
1140
                                                                        document.remove(0, document.getLength());
1141
                                                                } catch (BadLocationException e) {
1142
                                                                        e.printStackTrace();
1143 6721 ppiqueras
                                                                }
1144
1145 8765 jjdelcerro
                                                                // Return to the start view state
1146
                                                                model.setStartStateFlag(true);
1147
                                                                currentShowState = START_VIEW_STATE;
1148
1149
                                                                // Select the first Item
1150
                                                                setSelectedIndex(0);
1151 6721 ppiqueras
1152 8765 jjdelcerro
                                                                if (useHighlight_Flag)
1153
                                                                        document.highlightCompletedText(0);
1154 6721 ppiqueras
                                                        }
1155 8765 jjdelcerro
                                                        else
1156
                                                        {
1157
                                                                // Select the first Item
1158
                                                                setSelectedIndex(0);
1159
1160
                                                                if (useHighlight_Flag)
1161
                                                                        document.highlightCompletedText(0);
1162
                                                        }
1163
                                                        updatePopUpView();
1164
                                                        break;
1165
1166
                                                case KeyEvent.VK_SHIFT : // Do nothing
1167
                                                        break;
1168
1169
                                                case KeyEvent.VK_ALT_GRAPH : // Do nothing
1170
                                                        break;
1171
1172
                                                case KeyEvent.VK_ALT : // Do nothing
1173
                                                        break;
1174
1175
                                                case KeyEvent.VK_CONTROL : // Do nothing
1176
                                                        break;
1177
1178
                                                case KeyEvent.VK_NUM_LOCK : // Do nothing
1179
                                                        break;
1180
1181
                                                case KeyEvent.VK_CAPS_LOCK : // Do nothing
1182
                                                        break;
1183
1184
                                                default:
1185
                                                        logger.debug("Actualiza view flag a false");
1186
1187
                                                        logger.debug("LASTITEM1 :" + lastSelectedItemPopupUse);
1188 6721 ppiqueras
1189 8765 jjdelcerro
                                                        logger.debug("GETMARK: " + editor.getCaret().getMark() + "GETCARETPOSITION" + editor.getCaretPosition());
1190 6793 ppiqueras
1191 8765 jjdelcerro
                                                        specialSelectionByUserState = false;
1192
1193
                                                        // If it has been pressed a modifier key (Examples: ^ ` ? ?), not consume the key pressed
1194
                                                        if ((Character.getType(ke.getKeyChar()) == Character.MODIFIER_LETTER) || (Character.getType(ke.getKeyChar()) == Character.MODIFIER_SYMBOL))
1195
                                                        {
1196
                                                                logger.debug("CAR?CTER MODIFICADOR");
1197
                                                                lastWasPressedAKeyModifier = true;
1198
                                                        }
1199
                                                        else
1200
                                                        {
1201
                                                                logger.debug("CAR?CTER NO MODIFICADOR");
1202
                                                                allowInsertString = true;
1203 6793 ppiqueras
1204 8765 jjdelcerro
                                                        if (lastWasPressedAKeyModifier)
1205
                                                        {
1206
                                                                logger.debug("PRESSED: " + editor.getText().substring(0));
1207
                                                                lastWasPressedAKeyModifier = false;
1208
                                                        }
1209
1210
                                                        if (model.isDynamicSearch())
1211
                                                        {
1212
1213
                                                                String text;
1214
                                                                if (editor.getCaretPosition() == editor.getCaret().getMark())
1215
                                                                        text = editor.getText().substring(0, editor.getCaretPosition()) + ke.getKeyChar() + editor.getText().substring(editor.getCaretPosition(), editor.getText().length());
1216
                                                                else
1217
                                                                {
1218
                                                                        text = "" + editor.getText().substring(0, (int) Math.min(editor.getCaretPosition(), editor.getCaret().getMark())) + ke.getKeyChar();
1219
                                                                        text += editor.getText().substring((int) Math.max(editor.getCaretPosition(), editor.getCaret().getMark()), editor.getText().length());
1220
                                                                }
1221
1222
                                                                    // Reports about the written text to the model
1223
                                                                           logger.debug("Texto que se le env?a KEY al modelo: ->" + text + "<-");
1224
                                                                    model.setWrittenText(text);
1225
1226
                                                                    // Indicate to the model that now is disabled the start view
1227
                                                                    if (currentShowState == START_VIEW_STATE)
1228
                                                                    {
1229
                                                                            model.setStartStateFlag(false);
1230
                                                                            currentShowState = SEARCH_VIEW_STATE;
1231
                                                                    }
1232
1233
                                                        }
1234
1235
                                                updatePopUpView();
1236
1237
                                                        logger.debug("Key Pressed:" + ke.getKeyCode());
1238 6793 ppiqueras
                                                }
1239
                                        }
1240
1241 8765 jjdelcerro
                                        // Consume the key event for not to use the handler of the keyboard of other components
1242
                                        // Only if it has been pressed a modifier key, not consume the key pressed
1243
                                        if (!lastWasPressedAKeyModifier)
1244
                                                ke.consume();
1245
                    }
1246
                        }
1247
                };
1248 6793 ppiqueras
        }
1249
1250 6721 ppiqueras
        /**
1251 8765 jjdelcerro
         * Defines a popup menu listener for the popup of this component
1252 6721 ppiqueras
         */
1253 8765 jjdelcerro
        private void definePopUpMenuListener() {
1254 6721 ppiqueras
                        this.popupMenuListener = new PopupMenuListener() {
1255
1256
                        /*
1257
                         *  (non-Javadoc)
1258
                         * @see javax.swing.event.PopupMenuListener#popupMenuCanceled(javax.swing.event.PopupMenuEvent)
1259
                         */
1260
                        public void popupMenuCanceled(PopupMenuEvent e) {
1261 6732 ppiqueras
                                logger.debug("MenuCANCELED");
1262 6721 ppiqueras
                        }
1263
1264
                        /*
1265
                         *  (non-Javadoc)
1266
                         * @see javax.swing.event.PopupMenuListener#popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent)
1267
                         */
1268
                        public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
1269 6732 ppiqueras
                                logger.debug("MenuBECOMEINVISIBLE");
1270 8765 jjdelcerro
1271
                                if (!allowInsertString)
1272 6721 ppiqueras
                                {
1273 8765 jjdelcerro
                                        if (!specialSelectionByUserState) {
1274
                                                if ((getSelectedItem() != null) &&(lastSelectedItemPopupUse != null))
1275 6721 ppiqueras
                                                {
1276 8765 jjdelcerro
                                                // 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
1277
                                                        if (!getSelectedItem().equals(lastSelectedItemPopupUse))
1278 6721 ppiqueras
                                                        {
1279 8765 jjdelcerro
                                                                logger.debug("POPUP: NO SON IGUALES");
1280 6721 ppiqueras
1281 8765 jjdelcerro
                                                                // Reports about the written text to the model
1282
                                                                if (model.isDynamicSearch())
1283
                                                                {
1284
                                                                        model.setWrittenText(getSelectedItem().toString());
1285
                                                                        logger.debug("Texto que le envia POPUP al modelo: ->" + getSelectedItem().toString() + "<-");
1286
                                                                }
1287
1288
                                                                if (currentShowState == START_VIEW_STATE)
1289
                                                                {
1290
                                                                        model.setStartStateFlag(false);
1291
                                                                        currentShowState = SEARCH_VIEW_STATE;
1292
                                                                }
1293
                                                                logger.debug("Selected index of item: " + lastSelectedItemPopupUse.toString() + " is " + getSelectedIndex());
1294 6721 ppiqueras
                                                        }
1295 8765 jjdelcerro
                                                        else
1296
                                                                logger.debug("POPUP: SON IGUALES");
1297 6721 ppiqueras
                                                }
1298
                                        }
1299
                                }
1300
                        }
1301
1302
                        /*
1303
                         *  (non-Javadoc)
1304
                         * @see javax.swing.event.PopupMenuListener#popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent)
1305
                         */
1306
                        public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
1307 6732 ppiqueras
                                logger.debug("MenuBECOMEVISIBLE");
1308 8765 jjdelcerro
                                lastSelectedItemPopupUse = getSelectedItem(); // This object is used for know if the user has select a different item with the mouse
1309
                                allowInsertString = false;
1310 6721 ppiqueras
                        }
1311
                };
1312 8765 jjdelcerro
        }
1313 6721 ppiqueras
1314 8765 jjdelcerro
        /**
1315
         * Configures the component and some of its parts
1316
         */
1317
        private void configure() {
1318
                // Configures the document of the editor of this component
1319
                this.configureDocument();
1320
1321
                // Configures the editor (ComboBoxEditor) of this component
1322
                this.configureEditor(this.getEditor());
1323
1324
                // Configures the model of this component
1325
                this.configureModel();
1326
1327
                // Configures the popup of this component
1328
                this.configurePopUp();
1329
1330
                // Configures the text-edition-options popupmenu
1331
                this.configureOptionsEditionByMouse();
1332 6721 ppiqueras
        }
1333
1334 8765 jjdelcerro
        /**
1335
         * Configures the text-edition-options popupmenu
1336
         */
1337
        private void configureOptionsEditionByMouse() {
1338
                this.optionsEditionByMouse.addPropertyChangeListener(editionMenuListener);
1339
        }
1340 6721 ppiqueras
1341
        /**
1342 8765 jjdelcerro
         * Configures the popup of this component
1343 6721 ppiqueras
         */
1344 8765 jjdelcerro
        private void configurePopUp() {
1345
                this.addPopupMenuListener(this.popupMenuListener);
1346 6721 ppiqueras
        }
1347 8765 jjdelcerro
1348
        /**
1349
         * Configures the model of this component
1350
         */
1351
        private void configureModel() {
1352
                this.model.addListDataListener(this.modelListDataListener);
1353
        }
1354 6721 ppiqueras
1355 8765 jjdelcerro
        /**
1356
         * Configures the editor (ComboBoxEditor) of this component
1357
         *
1358
         * @param newEditor The new editor to configure
1359
         */
1360 6721 ppiqueras
        private void configureEditor(ComboBoxEditor newEditor) {
1361 8765 jjdelcerro
            logger.debug("Configura Editor");
1362 6721 ppiqueras
1363
        if (newEditor != null) {
1364 8765 jjdelcerro
                   JTextComponent jTextComponentOfEditor = (JTextComponent) newEditor.getEditorComponent();
1365
1366
                   // Removes some prevous listeners and adds some new others:
1367
1368
                // Adds the new Key Listener (tries to remove it if it existed before)
1369
                   jTextComponentOfEditor.removeKeyListener(this.editorKeyListener);
1370
                jTextComponentOfEditor.addKeyListener(this.editorKeyListener);
1371 6816 ppiqueras
1372 8765 jjdelcerro
            // Disable the focus transversal keys (Example: CTRL+TAB) for enable the TAB key
1373
                jTextComponentOfEditor.setFocusTraversalKeysEnabled(false);
1374
1375
            if (this.allowedMouseEditionPopupMenu_Flag)
1376
            {
1377
                        // Adds the new Mouse Listener (tries to remove it if it existed before)
1378
                    jTextComponentOfEditor.removeMouseListener(this.editorMouseListener);
1379
                        jTextComponentOfEditor.addMouseListener(this.editorMouseListener);
1380
            }
1381
1382
                // Adds the new Mouse Wheel Listener (tries to remove it if it existed before)
1383
            jTextComponentOfEditor.removeMouseWheelListener(this.editorMouseWheelListener);
1384
                jTextComponentOfEditor.addMouseWheelListener(this.editorMouseWheelListener);
1385
1386
                // Adds the new Focus Listener (tries to remove it if it existed before)
1387
                jTextComponentOfEditor.removeFocusListener(this.editorFocusListener);
1388
                jTextComponentOfEditor.addFocusListener(this.editorFocusListener);
1389
1390
                   // Adds a caret listener for undo and redo
1391
                jTextComponentOfEditor.addCaretListener(this.caretListener);
1392
1393
                // Adds the new document (tries to remove it if it existed before)
1394
                jTextComponentOfEditor.setDocument(this.document);
1395 6721 ppiqueras
        }
1396 8765 jjdelcerro
        }
1397
1398
        /**
1399
         * Configures the document of the editor of this component
1400
         */
1401
        private void configureDocument() {
1402
                // Creates the document of the editor of this component
1403
        document = new PlainDocumentTextFormatter();
1404
        document.setJComboBoxItemsSeekerDynamicReference(this);
1405 6793 ppiqueras
1406 8765 jjdelcerro
                // Defines and add a Document listener for changes on the document of the editor of this component
1407
                document.addDocumentListener(this.documentListener);
1408 6721 ppiqueras
        }
1409
1410 8765 jjdelcerro
        /**
1411
         * Selects the next item of the popup
1412
         */
1413
        private void selectItemDown() {
1414
                specialSelectionByUserState = true;
1415
1416
                if (getItemCount() > 0)
1417
                {
1418
                        if (getSelectedIndex() == (getItemCount()-1))
1419
                                this.setSelectedIndex(0);
1420
                        else
1421
                                this.setSelectedIndex(getSelectedIndex()+1);
1422
                }
1423
        }
1424
1425 6721 ppiqueras
        /**
1426 8765 jjdelcerro
         * Selects the previous item of the popup
1427 6721 ppiqueras
         */
1428 8765 jjdelcerro
        private void selectItemUp() {
1429
                specialSelectionByUserState = true;
1430
1431
                switch(getSelectedIndex())
1432
                {
1433
                        case -1: case 0:
1434
                                this.setSelectedIndex(getItemCount()-1);
1435
                                break;
1436
                        default:
1437
                                this.setSelectedIndex(getSelectedIndex()-1);
1438
                }
1439
        }
1440
1441
        /**
1442
         * 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'
1443
         *    in spanish keyboard) key
1444
         *
1445
         * @param editor A reference to the editor component
1446
         */
1447
        private void deleteTextLogic(JTextComponent editor, boolean backSpace_Delete_Mode) {
1448
                // Remove selected text:
1449
                logger.debug("GETMARK: " + editor.getCaret().getMark() + "GETCARETPOSITION" + editor.getCaretPosition());
1450
                int caretPosition = editor.getCaretPosition();
1451
                int markPosition = editor.getCaret().getMark();
1452
                specialSelectionByUserState = false;
1453
1454
                // Get the new text:
1455
                try {
1456
1457
                        int max_index = Math.max(caretPosition, markPosition);
1458
1459
                        if (caretPosition == markPosition)
1460
                                if (caretPosition == document.getLength()) // If no characters have to be removed
1461
                                        return;
1462
                                else
1463
                                        max_index ++;
1464
1465
                        String newText = document.getText(0, Math.min(caretPosition, markPosition)) + document.getText(max_index, document.getLength() - max_index );
1466
1467
                        // Update model and document, and remove character\s
1468
                        switch(currentShowState)
1469
                        {
1470
                                case START_VIEW_STATE :
1471
1472
                                        if (document.getLength() > 0)
1473
                                        {
1474
                                                // If dynamic searches:
1475
                                                try {
1476
                                                        // If the search will be dynamic:
1477
                                                        if (isDynamicSearchConfiguration())
1478
                                                        {
1479
                                                                model.setWrittenText(newText);
1480
                                                                logger.debug("Texto que se le env?a delete al modelo desde SUPR: ->" + document.getText(0, document.getLength()) + "<-");
1481
                                                        }
1482
                                                } catch (BadLocationException e) {
1483
                                                        e.printStackTrace();
1484
                                                }
1485
1486
                                                model.setStartStateFlag(false);
1487
                                                currentShowState = SEARCH_VIEW_STATE;
1488
1489
                                                // Remove one or more characters
1490
                                                characterEliminationLogic(editor, caretPosition, markPosition);
1491
                                        }
1492
                                        break;
1493
                                case SEARCH_VIEW_STATE :
1494
1495
                                         // If there isn't characters
1496
                                        if (document.getLength() == 0)
1497
                                        {
1498
                                                // This instruction avoids popup could failure when got invisible
1499
                                                hidePopup();
1500
1501
                                                // If it's a dynamic search
1502
                                                if (isDynamicSearchConfiguration())
1503
                                                {
1504
                                                        model.setWrittenText("");
1505
                                                        logger.debug("Texto que se le env?a delete al modelo desde SUPR: ->\"\"<-");
1506
                                                }
1507
1508
                                                // Remove one or more characters
1509
                                                characterEliminationLogic(editor, caretPosition, markPosition);
1510
1511
                                                // Return to the start view state
1512
                                                model.setStartStateFlag(true);
1513
                                                currentShowState = START_VIEW_STATE;
1514
1515
                                                // Select the first Item
1516
                                                setSelectedIndex(0);
1517
1518
                                                if (useHighlight_Flag)
1519
                                                        document.highlightCompletedText(0);
1520
                                        }
1521
                                        else
1522
                                        {
1523
                                                // This instruction avoids popup could failure when got invisible
1524
                                                hidePopup();
1525
1526
                                                allowInsertString = true;
1527
1528
                                        if (lastWasPressedAKeyModifier)
1529
                                        {
1530
                                                logger.debug("PRESSED: " + editor.getText().substring(0));
1531
                                                lastWasPressedAKeyModifier = false;
1532
                                        }
1533
1534
                                                // If dynamic searches:
1535
                                                try {
1536
1537
                                                        // If the search will be dynamic:
1538
                                                        if (isDynamicSearchConfiguration())
1539
                                                        {
1540
                                                                model.setWrittenText(newText);
1541
                                                                logger.debug("Texto que se le env?a delete al modelo desde SUPR: ->" + document.getText(0, document.getLength()) + "<-");
1542
                                                        }
1543
1544
                                                        // Remove one or more characters
1545
                                                        characterEliminationLogic(editor, caretPosition, markPosition);
1546
1547
                                                    // Indicate to the model that now is disabled the start view
1548
                                                    if (currentShowState == START_VIEW_STATE)
1549
                                                    {
1550
                                                            model.setStartStateFlag(false);
1551
                                                            currentShowState = SEARCH_VIEW_STATE;
1552
                                                    }
1553
                                                } catch (BadLocationException e) {
1554
                                                        // TODO Auto-generated catch block
1555
                                                        e.printStackTrace();
1556
                                                }
1557
                                        }
1558
                                        break;
1559
                        }
1560
1561
                        updatePopUpView();
1562
1563
                } catch (BadLocationException e1) {
1564
                        // TODO Auto-generated catch block
1565
                        e1.printStackTrace();
1566
                }
1567
        }
1568
1569
        /**
1570
         * This method has the logic for remove one or more characters
1571
         *
1572
         * @param editor A reference to the editor
1573
         * @param caretPosition Position of the caret in the text
1574
         */
1575
        private void characterEliminationLogic(JTextComponent editor, int caretPosition, int markPosition) {
1576
                // First: Remove character\s (only if hasn't been done a 'cut' mouse operation)
1577
                if (cutOperationDone) {
1578
                        cutOperationDone = false;
1579
                }
1580
                else {
1581
                        try {
1582
                                // If no characters are selected
1583
                                if (markPosition == caretPosition) {
1584
                                        // Remove the character which is on the right of the caret position
1585
                                        if (caretPosition < document.getLength())
1586
                                                document.remove(caretPosition, 1);
1587
                                }
1588
                                else // If there are characters selected
1589
                                {
1590
                                        // Remove the characters which are selected
1591
                                        int length = Math.abs(markPosition - caretPosition);
1592
1593
                                        // Remove the characters which are selected
1594
                                        document.remove(Math.min(markPosition, caretPosition), length);
1595
                                }
1596
                        } catch (BadLocationException e) {
1597
                                e.printStackTrace();
1598
                        }
1599
                }
1600
        }
1601
1602
        /**
1603
         * Returns true if the model has a dynamic search configuration
1604
         *
1605
         * @return 'true' if the model has a dynamic searchh configuration, else returns 'false'.
1606
         */
1607
        private boolean isDynamicSearchConfiguration() {
1608
                switch(model.getSearchBehavior())
1609
                {
1610
                        case AbstractDefaultComboBoxItemsSeekerConfigurableModel.MAINTAIN_ORIGINAL_POSITION_DYNAMIC_SEARCH :
1611
                        case AbstractDefaultComboBoxItemsSeekerConfigurableModel.ORDERED_DYNAMIC_SEARCH :
1612
                        case AbstractDefaultComboBoxItemsSeekerConfigurableModel.DISORDERED_DYNAMIC_SEARCH :
1613
                                return true;
1614
                }
1615
1616
                return false;
1617
        }
1618
1619
        /**
1620
         * Selects the first item added to the model
1621
         */
1622
        public void selectFirstItemAddedToModel() {
1623
                // Select the first Item added
1624
                Object item = model.getFirstItemAdded();
1625
                if (item != null)
1626
                        setSelectedItem(item);
1627
        }
1628
1629 6721 ppiqueras
1630 8765 jjdelcerro
        /**
1631
     * Updates the popup view, this solves the problem of updating items that are showed, but has the problem that could produce winking
1632 6721 ppiqueras
     */
1633 8765 jjdelcerro
        private void updatePopUpView() {
1634 6721 ppiqueras
            // HidePopUp + ShowPopUp to force update the popup list of items
1635
                hidePopup();
1636
                showPopup();
1637
                this.setVisible(true);
1638 8765 jjdelcerro
1639 6721 ppiqueras
    }
1640 8765 jjdelcerro
1641
        /**
1642
         * This method has the logic for a "undo" operation
1643
         */
1644
        private void undoOperationLogic() {
1645
                logger.debug("UNDO PRESSED");
1646
                try {
1647
            if (undoManager.canUndo()) {
1648
                    undoManager.undo();
1649
1650
                    String newPattern = document.getText(0, document.getLength());
1651
1652
                                model.setWrittenText(newPattern);
1653
1654
                                document.formatText(document.lookupItem(), 0);
1655
1656
                                if (isPopupVisible())
1657
                                        updatePopUpView();
1658
1659
                    logger.debug("Undo por teclado realizado");
1660
            }
1661
                } catch (BadLocationException e) {
1662
                        e.printStackTrace();
1663
                } catch (CannotUndoException e) {
1664
                e.printStackTrace();
1665
        }
1666
        }
1667
1668
        /**
1669
         * This method has the logic for a "redo" operation
1670
         */
1671
        private void redoOperationLogic() {
1672
                logger.debug("REDO PRESSED");
1673
        try {
1674
            if (undoManager.canRedo()) {
1675
                            undoManager.redo();
1676
1677
                     String newPattern = document.getText(0, document.getLength());
1678
1679
                               model.setWrittenText(newPattern);
1680
1681
                               document.formatText(document.lookupItem(), 0);
1682
1683
                               if (isPopupVisible())
1684
                                        updatePopUpView();
1685
1686
                    logger.debug("Redo por teclado realizado");
1687
            }
1688
            } catch (CannotRedoException e) {
1689
                    e.printStackTrace();
1690
            } catch (BadLocationException e) {
1691
                    e.printStackTrace();
1692
            }
1693
        }
1694 6721 ppiqueras
1695 8765 jjdelcerro
    ////// REDEFINITION OF SOME METHODS OF JCOMBOBOX //////
1696 6721 ppiqueras
1697
        /*
1698
         *  (non-Javadoc)
1699
         * @see javax.swing.JComboBox#actionPerformed(java.awt.event.ActionEvent)
1700
         */
1701
        public void actionPerformed(ActionEvent e)
1702
        {
1703
                super.actionPerformed(e);
1704
1705
                // This flag indicates to the 'insertString' method of the PlainDocumentSeeker that the text of the item selected or written by the user
1706
                //  hasn't been written on the TextEditor of ths component
1707
                selecting = false;
1708
        }
1709
1710 8765 jjdelcerro
        /*
1711 6721 ppiqueras
     * (non-Javadoc)
1712
     * @see javax.swing.JComboBox#addItem(java.lang.Object)
1713
     */
1714 8765 jjdelcerro
        public void addItem(Object anObject) {
1715 6721 ppiqueras
                // Adds the item to this component
1716
                model.addElement(anObject);
1717
1718
                // Set the last selected item -> by default select the first item:
1719
                // This is used to show the first item that model returns when we add a new item. This also
1720
                //  corrects the 'mistake' produced by 'ComboBoxModel' when is added a new item and there wasn't
1721
                //  any selected -> that the 'ComboBoxModel' selects by default the first added (that in our case
1722
                //  might not be the same as the first item seen in the popup list)
1723
                if (this.getSelectedIndex() != 0)
1724
                {
1725
                        this.setSelectedIndex(0);
1726 8765 jjdelcerro
//                        this.selectedItem = this.getSelectedItem();
1727 6721 ppiqueras
                }
1728
        }
1729
1730 8765 jjdelcerro
        /*
1731 6721 ppiqueras
     * (non-Javadoc)
1732
     * @see javax.swing.JComboBox#removeAllItems()
1733
     */
1734 8765 jjdelcerro
        public void removeAllItems() {
1735 6721 ppiqueras
            // Removes all items from the model
1736
            model.removeAllElements();
1737
1738
            currentShowState = BEGINNING_VIEW_STATE;
1739
    }
1740
1741 8765 jjdelcerro
        /*
1742 6721 ppiqueras
     * (non-Javadoc)
1743
     * @see javax.swing.JComboBox#removeItem(java.lang.Object)
1744
     */
1745 8765 jjdelcerro
        public void removeItem(Object anObject) {
1746 6721 ppiqueras
            // Removes an object from the model
1747
            model.removeElement(anObject);
1748
1749
            if (model.getSize() == 0)
1750
                    currentShowState = BEGINNING_VIEW_STATE;
1751
    }
1752
1753 8765 jjdelcerro
        /*
1754 6721 ppiqueras
     * (non-Javadoc)
1755
     * @see javax.swing.JComboBox#removeItemAt(int)
1756
     */
1757 8765 jjdelcerro
        public void removeItemAt(int anIndex) {
1758 6721 ppiqueras
               // Removes an object, which is in a determinated position (index), from the model
1759
            model.removeElementAt(anIndex);
1760
1761
            if (model.getSize() == 0)
1762
                    currentShowState = BEGINNING_VIEW_STATE;
1763
    }
1764
1765 8765 jjdelcerro
        /*
1766 6721 ppiqueras
     * (non-Javadoc)
1767
     * @see javax.swing.JComboBox#getItemCount()
1768
     */
1769 8765 jjdelcerro
        public int getItemCount() {
1770 6721 ppiqueras
            return model.getSize();
1771
    }
1772
1773 8765 jjdelcerro
        /*
1774 6721 ppiqueras
     * (non-Javadoc)
1775
     * @see javax.swing.JComboBox#getItemAt(int)
1776
     */
1777 8765 jjdelcerro
        public Object getItemAt(int index) {
1778 6721 ppiqueras
            return model.getElementAt(index);
1779
    }
1780
1781 8765 jjdelcerro
        /*
1782 6721 ppiqueras
     * (non-Javadoc)
1783
     * @see javax.swing.JComboBox#setModel(javax.swing.ComboBoxModel)
1784
     */
1785 8765 jjdelcerro
        public void setModel(ComboBoxModel aModel) {
1786 6721 ppiqueras
            // Depending on the type of class of the current object, this object will execute different code
1787 6755 ppiqueras
            if ( (aModel instanceof ComboBoxSingularItemsSeekerConfigurableModel) || (aModel instanceof ComboBoxItemsSeekerConfigurableModel) )
1788 6721 ppiqueras
            {
1789
                    super.setModel(aModel);
1790
1791 6755 ppiqueras
                    if (aModel instanceof ComboBoxSingularItemsSeekerConfigurableModel)
1792
                            model = (ComboBoxSingularItemsSeekerConfigurableModel)super.getModel();
1793
                    else
1794
                            model = (ComboBoxItemsSeekerConfigurableModel)super.getModel();
1795
1796 6721 ppiqueras
                    // If we insert a model with items -> select by default the first
1797
                    if (aModel.getSize() > 0)
1798
                            this.setSelectedIndex(0);
1799
                    else
1800
                    {
1801
                            // Else -> set the default index (-1) and current showed string ("")
1802
                            this.setSelectedIndex(-1);
1803
                    }
1804
1805
                    this.configureModel();
1806
            }
1807
            else
1808
            {
1809
                    // If it's an instance of DefaultComboBoxModel:
1810
                    super.setModel(aModel);
1811
            }
1812
     }
1813
1814 8765 jjdelcerro
        /*
1815 6721 ppiqueras
     * (non-Javadoc)
1816
     * @see javax.swing.JComboBox#setSelectedIndex(int)
1817
     */
1818 8765 jjdelcerro
        public void setSelectedIndex(int anIndex) {
1819 6721 ppiqueras
            super.setSelectedIndex(anIndex);
1820
    }
1821
1822 8765 jjdelcerro
        /*
1823 6721 ppiqueras
     * (non-Javadoc)
1824
     * @see javax.swing.JComboBox#getSelectedIndex()
1825
     */
1826 8765 jjdelcerro
        public int getSelectedIndex() {
1827 6721 ppiqueras
            Object item = this.getSelectedItem();
1828
1829
            if (item == null)
1830
                    return -1;
1831
            else
1832
                    return model.getIndexOf(item);
1833
    }
1834
1835 8765 jjdelcerro
        /*
1836 6721 ppiqueras
     *  (non-Javadoc)
1837
     * @see javax.swing.JComboBox#setSelectedItem(java.lang.Object)
1838
     */
1839 8765 jjdelcerro
        public void setSelectedItem(Object anObject) {
1840 6721 ppiqueras
            super.setSelectedItem(anObject);
1841
    }
1842
1843
    ////// END REDEFINITION OF SOME METHODS OF JCOMBOBOX //////
1844 8765 jjdelcerro
1845 6721 ppiqueras
1846 8765 jjdelcerro
1847 6721 ppiqueras
        ////// METHODS FOR THE BEHAVIOR FLAGS  //////
1848
1849
        /**
1850
         * This method tests the configuration of the flags and returns true or false if its ok or not with the
1851
         *   logical behavior of this component
1852
         *
1853
         * @return boolean True if the configuration of the flags is oks, false if not
1854
         */
1855
        public boolean testFlagsConfigurationOK() {
1856
                return this.model.testFlagsConfigurationOK();
1857
        }
1858
1859 8765 jjdelcerro
        /**
1860
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#getStartBehavior()
1861
         */
1862 6721 ppiqueras
        public int getStartBehavior() {
1863
                return this.model.getStartBehavior();
1864
        }
1865
1866 8765 jjdelcerro
        /**
1867
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#setStartBehavior(int)
1868
         */
1869 6721 ppiqueras
        public void setStartBehavior(int start_Behavior) {
1870
                this.model.setStartBehavior(start_Behavior);
1871
1872
                if (!this.model.testFlagsConfigurationOK())
1873 7244 cesar
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1874 6721 ppiqueras
        }
1875
1876 8765 jjdelcerro
        /**
1877
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#getSearchBehavior()
1878
         */
1879 6721 ppiqueras
        public int getSearchBehavior() {
1880
                return this.model.getSearchBehavior();
1881
        }
1882
1883 8765 jjdelcerro
        /**
1884
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#setSearchBehavior(int)
1885
         */
1886 6721 ppiqueras
        public void setSearchBehavior(int search_Behavior) {
1887
                this.model.setSearchBehavior(search_Behavior);
1888
1889
                if (!this.model.testFlagsConfigurationOK())
1890 7244 cesar
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1891 6721 ppiqueras
        }
1892
1893
        /**
1894 8765 jjdelcerro
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#isCaseSensitive_Flag()
1895 6721 ppiqueras
         */
1896 8765 jjdelcerro
        public boolean isCaseSensitive_Flag() {
1897
                return this.model.isCaseSensitive_Flag();
1898 6721 ppiqueras
        }
1899
1900
        /**
1901 8765 jjdelcerro
         * @see AbstractDefaultComboBoxItemsSeekerConfigurableModel#setCaseSensitive_Flag(boolean)
1902 6721 ppiqueras
         */
1903 8765 jjdelcerro
        public void setCaseSensitive_Flag(boolean case_Sensitive) {
1904
                this.model.setCaseSensitive_Flag(case_Sensitive);
1905 6721 ppiqueras
1906
                if (!this.model.testFlagsConfigurationOK())
1907 7244 cesar
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1908 6721 ppiqueras
        }
1909
1910
        /**
1911 9089 ppiqueras
         * Returns the 'only_One_Color_On_Text' configuration value of this component. Configuration values are:
1912 8765 jjdelcerro
         *   + true -> always uses black color on text
1913
         *   + 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
1914 6721 ppiqueras
         *
1915 9089 ppiqueras
         * @return 'only_One_Color_On_Text' configuration
1916 6721 ppiqueras
         */
1917 8765 jjdelcerro
        public boolean isOnlyOneColorOnText_Flag() {
1918
                return onlyOneColorOnText_Flag;
1919 6721 ppiqueras
        }
1920
1921
        /**
1922 9089 ppiqueras
         * Sets the 'only_One_Color_On_Text' configuration value for this component. Configuration values are:
1923 8765 jjdelcerro
         *   + true -> always uses black color on text
1924
         *   + 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
1925 6721 ppiqueras
         *
1926 9089 ppiqueras
         * @oaram A boolean value for 'only_One_Color_On_Text' configuration flag
1927 6721 ppiqueras
         */
1928 8765 jjdelcerro
        public void setOnlyOneColorOnText_Flag(boolean only_One_Color) {
1929
                this.onlyOneColorOnText_Flag = only_One_Color;
1930 6721 ppiqueras
1931
                if (!this.model.testFlagsConfigurationOK())
1932 7244 cesar
                        JOptionPane.showMessageDialog(this, Messages.getText("errorMessageJComboBoxItemsSeekerConfigurable"), Messages.getText("exportJOP2Title"), JOptionPane.ERROR_MESSAGE);
1933 6721 ppiqueras
        }
1934
1935 8765 jjdelcerro
        /**
1936 9089 ppiqueras
         * Returns the 'beep_Enabled' configuration value of this component. Configuration values are:
1937 8765 jjdelcerro
         *   + true -> a beep-sound is listened when no item matches with the text written.
1938
         *   + false -> no sound is listened.
1939
         *
1940 9089 ppiqueras
         * @return 'beep_Enabled' configuration
1941 8765 jjdelcerro
         */
1942
        public boolean isBeepEnabled_Flag() {
1943
                return this.beepEnabled_Flag;
1944 6721 ppiqueras
        }
1945
1946 8765 jjdelcerro
        /**
1947 9089 ppiqueras
         * Sets the 'beep_Enabled' configuration value for this component. Configuration values are:
1948 8765 jjdelcerro
         *   + true -> a beep-sound is listened when no item matches with the text written.
1949
         *   + false -> no sound is listened.
1950
         *
1951 9089 ppiqueras
         * @oaram A boolean value for 'beep_Enabled' configuration flag
1952 8765 jjdelcerro
         */
1953
        public void setBeepEnabled_Flag(boolean beep_Enabled) {
1954
                this.beepEnabled_Flag = beep_Enabled;
1955
        }
1956
1957
        /**
1958 9089 ppiqueras
         * Returns the 'complete_Matched_Item' configuration value of this component. Configuration values are:
1959 8765 jjdelcerro
         *   + true -> When user writes, shows also the rest of the current matched item that user hasn't written.
1960
         *   + false -> Only shows the text written by the user when user is writting.
1961
         *
1962 9089 ppiqueras
         * @return 'complete_Matched_Item' configuration
1963 8765 jjdelcerro
         */
1964
        public boolean isCompleteMatchedItem_Flag() {
1965
                return this.completeMatchedItem_Flag;
1966 6732 ppiqueras
        }
1967
1968 8765 jjdelcerro
        /**
1969 9089 ppiqueras
         * Sets the 'complete_Matched_Item' configuration value for this component. Configuration values are:
1970 8765 jjdelcerro
         *   + true -> a beep-sound is listened when no item matches with the text written.
1971
         *   + false -> no sound is listened.
1972
         *
1973 9089 ppiqueras
         * @oaram A boolean value for 'complete_Matched_Item' configuration flag
1974 8765 jjdelcerro
         */
1975
        public void setCompleteMatchedItem_Flag(boolean Complete_Matched_Item) {
1976
                this.completeMatchedItem_Flag = Complete_Matched_Item;
1977 6732 ppiqueras
        }
1978
1979 8765 jjdelcerro
        /**
1980 9089 ppiqueras
         * Returns the 'allowed_Repeated_Items' configuration value of this component. Configuration values are:
1981 8765 jjdelcerro
         * Uses one of the two models according the value of this flag:
1982
     *    + true -> Uses 'ComboBoxItemsSeekerConfigurableModel' as model (this could work slowly).
1983
     *    + false -> Uses 'ComboBoxSingularItemsSeekerConfigurableModel' as model.
1984
     *
1985 9089 ppiqueras
         * @return 'allowed_Repeated_Items' configuration
1986 8765 jjdelcerro
         */
1987
        public boolean isAllowedRepeatedItems_Flag() {
1988
                return this.allowedRepeatedItems_Flag;
1989 6732 ppiqueras
        }
1990
1991 8765 jjdelcerro
        /**
1992 9089 ppiqueras
         * Sets the 'allowed_Repeated_Items' configuration value for this component. Configuration values are:
1993 8765 jjdelcerro
         * Uses one of the two models according the value of this flag:
1994
     *    + true -> Uses 'ComboBoxItemsSeekerConfigurableModel' as model (this could work slowly).
1995
     *    + false -> Uses 'ComboBoxSingularItemsSeekerConfigurableModel' as model.
1996
         *
1997 9089 ppiqueras
         * @oaram A boolean value for 'allowed_Repeated_Items' configuration flag
1998 8765 jjdelcerro
         */
1999
        public void setAllowedRepeatedItems_Flag(boolean allowed_Repeated_Items) {
2000
                this.allowedRepeatedItems_Flag = allowed_Repeated_Items;
2001 6755 ppiqueras
2002
                try {
2003
                        AbstractDefaultComboBoxItemsSeekerConfigurableModel model_temp;
2004 8765 jjdelcerro
2005
                        // Add the items to the new model
2006
                        if (allowed_Repeated_Items)
2007
                                model_temp = new ComboBoxItemsSeekerConfigurableModel(model.getParentAllData());
2008
                        else
2009
                                model_temp = new ComboBoxSingularItemsSeekerConfigurableModel(model.getParentAllData());
2010
2011
                        // Copy the behavior of the model
2012
                        model_temp.setStartBehavior(this.getStartBehavior());
2013
                        model_temp.setSearchBehavior(this.getSearchBehavior());
2014
                        model_temp.setCaseSensitive_Flag(this.isCaseSensitive_Flag());
2015
2016
                        // Set the new model
2017
                        this.setModel(model_temp);
2018 6755 ppiqueras
                }
2019
                catch(Exception e)
2020
                {
2021
                        e.printStackTrace();
2022
                }
2023
        }
2024
2025 8765 jjdelcerro
        /**
2026 9089 ppiqueras
         * Returns the 'allowed_Mouse_Edition_Popup_Menu' configuration value of this component. Configuration values are:
2027 8765 jjdelcerro
         *   + true -> a 'PopupMenu' for text edition that appears when the user clicks on the text-edition-field with the right
2028
         *                button of the mouse.
2029
         *   + false -> that 'PopupMenu' won't appear.
2030
         *
2031 9089 ppiqueras
         * @return 'allowed_Mouse_Edition_Popup_Menu' configuration
2032 8765 jjdelcerro
         */
2033
        public boolean isAllowedMouseEditionPopupMenu_Flag() {
2034
                return this.allowedMouseEditionPopupMenu_Flag;
2035
        }
2036
2037
        /**
2038 9089 ppiqueras
         * Sets the 'allowed_Mouse_Edition_Popup_Menu' configuration value for this component. Configuration values are:
2039 8765 jjdelcerro
         *   + true -> a 'PopupMenu' for text edition that appears when the user clicks on the text-edition-field with the right
2040
         *                button of the mouse.
2041
         *   + false -> that 'PopupMenu' won't appear.
2042
         *
2043 9089 ppiqueras
         * @oaram A boolean value for 'allowed_Mouse_Edition_Popup_Menu' configuration flag
2044 8765 jjdelcerro
         */
2045
        public void setAllowedMouseEditionPopupMenu_Flag(boolean allowed_Mouse_Edition_Popup_Menu) {
2046
                JTextComponent editor = (JTextComponent) this.getEditor().getEditorComponent();
2047
2048
                if (this.allowedMouseEditionPopupMenu_Flag != allowed_Mouse_Edition_Popup_Menu)
2049
                {
2050
                        // If now is allowed -> adds the mouse listener
2051
                        if (allowed_Mouse_Edition_Popup_Menu)
2052
                    editor.addMouseListener(this.editorMouseListener);
2053
                        else // If now isn't allowed
2054
                                editor.removeMouseListener(this.editorMouseListener);
2055
                }
2056
2057
                this.allowedMouseEditionPopupMenu_Flag = allowed_Mouse_Edition_Popup_Menu;
2058
        }
2059
2060
        /**
2061 9089 ppiqueras
         * Returns the 'to_Force_To_Only_Coincidences_In_The_Search' configuration value of this component. Configuration values are:
2062 8765 jjdelcerro
         *   + 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
2063
         *                see written in the text-edition-field the last item which matched with the text written, or the first item of the model if
2064
         *                there wasn't.
2065
         *   + false -> If no item matches with the text written and the user presses the 'Enter' key, no item will be selected.
2066
         *
2067 9089 ppiqueras
         * @return 'to_Force_To_Only_Coincidences_In_The_Search' configuration
2068 8765 jjdelcerro
         */
2069
        public boolean isToForceToOnlyCoincidencesInTheSearch_Flag() {
2070
                return this.toForceToOnlyCoincidencesInTheSearch_Flag;
2071
        }
2072 6755 ppiqueras
2073 8765 jjdelcerro
        /**
2074 9089 ppiqueras
         * Sets the 'to_Force_To_Only_Coincidences_In_The_Search' configuration value for this component. Configuration values are:
2075 8765 jjdelcerro
         *   + 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
2076
         *                see written in the text-edition-field the last item which matched with the text written, or the first item of the model if
2077
         *                there wasn't.
2078
         *   + false -> If no item matches with the text written and the user presses the 'Enter' key, no item will be selected.
2079
         *
2080 9089 ppiqueras
         * @oaram A boolean value for 'to_Force_To_Only_Coincidences_In_The_Search' configuration flag
2081 8765 jjdelcerro
         */
2082
        public void setToForceToOnlyCoincidencesInTheSearch_Flag(boolean to_Force_To_Only_Coincidences_In_The_Search) {
2083
                this.toForceToOnlyCoincidencesInTheSearch_Flag = to_Force_To_Only_Coincidences_In_The_Search;
2084
        }
2085
2086
        /**
2087
         * Returns the 'use_highlight' configuration value of this component. Configuration values are:
2088
         *   + true -> marks characters of the text in the text-edition-field with a highlight.
2089
         *   + false -> doesn't do that.
2090
         *
2091 9089 ppiqueras
         * @return 'use_Highlight' configuration
2092 8765 jjdelcerro
         */
2093
        public boolean isUseHighLight_Flag() {
2094
                return this.useHighlight_Flag;
2095
        }
2096 6755 ppiqueras
2097 8765 jjdelcerro
        /**
2098
         * Sets the 'use_highlight' configuration value for this component. Configuration values are:
2099
         *   + true -> marks characters of the text in the text-edition-field with a highlight.
2100
         *   + false -> doesn't do that.
2101
         *
2102 9089 ppiqueras
         * @oaram A boolean value for 'use_Highlight' configuration flag
2103 8765 jjdelcerro
         */
2104
        public void setUseHighLight_Flag(boolean use_Highlight) {
2105
                this.useHighlight_Flag = use_Highlight;
2106 9089 ppiqueras
        }
2107
2108
        /**
2109
         * Returns the 'select_An_Item_When_Loses_Focus' configuration value of this component. Configuration values are:
2110
     *   + true -> If user or an application makes component lose its focus, an item will be selected.
2111
     *   + false -> If user or an application makes component lose its focus, the component will stay as it was.
2112
     *
2113
     * @return 'select_An_Item_When_Loses_Focus' configuration
2114
         */
2115
        public boolean isSelectAnItemWhenLosesFocus_Flag() {
2116
                return this.selectAnItemWhenLosesFocus_Flag;
2117
        }
2118 8765 jjdelcerro
2119 9089 ppiqueras
        /**
2120
         *  Sets the 'select_An_Item_When_Loses_Focus' configuration value for this component. Configuration values are:
2121
     *   + true -> If user or an application makes component lose its focus, an item will be selected.
2122
     *   + false -> If user or an application makes component lose its focus, the component will stay as it was.
2123
         *
2124
         * @oaram A boolean value for 'select_An_Item_When_Loses_Focus' configuration flag
2125
         */
2126
        public void setSelectAnItemWhenLosesFocus_Flag(boolean select_An_Item_When_Loses_Focus) {
2127
                this.selectAnItemWhenLosesFocus_Flag = select_An_Item_When_Loses_Focus;
2128
        }
2129
2130 6721 ppiqueras
        ////// END METHODS FOR THE BEHAVIOR FLAGS  //////
2131
2132
2133 8765 jjdelcerro
2134
    ////// OTHER METHODS //////
2135
2136
        /**
2137
     * Sets the limit of actions that can hold the UndoManager of this component
2138
     *
2139
     * @param limit
2140
     */
2141
        public void setUndoRedoLimitActions(int limit) {
2142
            this.undoRedoLimitActions = limit;
2143
            undoManager.setLimit(undoRedoLimitActions);
2144
    }
2145
2146
        /**
2147
     * Gets the limit of actions that can hold the UndoManager:
2148
     *
2149
     * @return int
2150
     */
2151
        public int getUndoRedoLimitActions() {
2152
            return this.undoRedoLimitActions;
2153
    }
2154
2155
    ////// END OTHER METHODS //////
2156
2157
2158
        /**
2159
         * 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
2160
         * This class is also optimized for items seek, changes the color of the text or sets highlight if it's needed.
2161 6721 ppiqueras
         *
2162
         * @author Pablo Piqueras Bartolom? (p_queras@hotmail.com)
2163
         */
2164 8765 jjdelcerro
        private class PlainDocumentTextFormatter extends PlainDocument {
2165
                private static final long serialVersionUID = 4158213349939840209L;
2166
                private JComboBoxItemsSeekerConfigurable comboBoxReference;
2167 6721 ppiqueras
2168
                /**
2169
                 * Default Constructor
2170
                 */
2171 8765 jjdelcerro
                public PlainDocumentTextFormatter() {
2172 6721 ppiqueras
                        super();
2173 8765 jjdelcerro
                        this.initialize();
2174
                }
2175
2176
                /**
2177
                 * This method makes some initialize operations
2178
                 */
2179
                private void initialize() {
2180 6816 ppiqueras
                        this.configureUndoManager();
2181 6721 ppiqueras
                }
2182
2183
                /**
2184 8765 jjdelcerro
                 * Configures the UndoManager for Undo-Redo operations
2185 6816 ppiqueras
                 */
2186
                private void configureUndoManager() {
2187
                // Listen for undo and redo events
2188
                this.addUndoableEditListener(new UndoableEditListener() {
2189 8765 jjdelcerro
                        /*
2190
                         * (non-Javadoc)
2191
                         * @see javax.swing.event.UndoableEditListener#undoableEditHappened(javax.swing.event.UndoableEditEvent)
2192
                         */
2193 6816 ppiqueras
                    public void undoableEditHappened(UndoableEditEvent evt) {
2194 8765 jjdelcerro
                            logger.debug("UNDOABLE EVENT");
2195
                                        undoManager.addEdit(evt.getEdit());
2196 6816 ppiqueras
                    }
2197
                });
2198
                }
2199
2200
                /**
2201 6721 ppiqueras
                 * Sets a reference of the combo_Box
2202
                 *
2203 8765 jjdelcerro
                 * @param combo_Box A reference to the class that contains this.
2204 6721 ppiqueras
                 */
2205
                public void setJComboBoxItemsSeekerDynamicReference(JComboBoxItemsSeekerConfigurable combo_Box) {
2206 6816 ppiqueras
                        comboBoxReference = combo_Box;
2207 6721 ppiqueras
                }
2208
2209 8765 jjdelcerro
                /*
2210 6721 ppiqueras
                 *  (non-Javadoc)
2211
                 * @see javax.swing.text.Document#remove(int, int)
2212
                 */
2213
                public void remove(int offs, int len) throws BadLocationException {
2214
                // return immediately when selecting an item
2215
                if (selecting) return;
2216
2217
                if (hitBackspace)
2218
                {
2219
                    // user hit backspace => move the selection backwards
2220
                    // old item keeps being selected
2221
                    if (offs>0)
2222
                    {
2223
                        if (hitBackspaceOnSelection)
2224
                                offs--;
2225
                    }
2226
                    else
2227
                    {
2228
                        // User hit backspace with the cursor positioned on the start => beep
2229 8765 jjdelcerro
                            if (beepEnabled_Flag)
2230 6816 ppiqueras
                                    comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
2231 6721 ppiqueras
                    }
2232
2233 8765 jjdelcerro
                    if (useHighlight_Flag)
2234
                                        highlightCompletedText(offs);
2235
2236 6791 ppiqueras
                    hitBackspace=false;
2237 6721 ppiqueras
                }
2238
                else
2239
                {
2240 8765 jjdelcerro
                        logger.debug("REMOVES OFFS: " + offs + ", LEN: " + len);
2241
                        super.remove(offs, len);
2242
                }
2243 6760 ppiqueras
2244 8765 jjdelcerro
                formatText(lookupItem(), offs);
2245 6721 ppiqueras
            }
2246 8765 jjdelcerro
2247
                /* NUEVA VERSI?N
2248 6721 ppiqueras
                 *  (non-Javadoc)
2249
                 * @see javax.swing.text.Document#insertString(int, java.lang.String, javax.swing.text.AttributeSet)
2250
                 */
2251
            public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
2252 8765 jjdelcerro
                    Object item = lookupItem();
2253
2254
                    // If we have to complete the text: only write the part of the item not written
2255
                        if ((completeMatchedItem_Flag) && (item != null) && (!itemSelectedByMouse)) {
2256
                                editor.getEditorComponent().setForeground(Color.BLACK);
2257
                                super.insertString(super.getLength(), item.toString().substring(super.getLength(), item.toString().length()), a);
2258
2259
                                if (!specialSelectionByUserState)
2260
                                        offs += Math.min(str.length(), document.getLength());
2261
                        }
2262
                        else {
2263
                                super.insertString(offs, str, a);
2264
                                itemSelectedByMouse = false;
2265
                                offs += str.length();
2266
                        }
2267
//                        offs += Math.min(str.length(), document.getLength());
2268
                        formatText(item, offs);
2269 6721 ppiqueras
            }
2270 8765 jjdelcerro
2271
                /**
2272
                 * Marks text since 'start' position to its end on a grey color
2273
                 *
2274
                 * @param start Start position for mark the text
2275
                 */
2276
                public void highlightCompletedText(int start) {
2277
                    JTextComponent editor = (JTextComponent) getEditor().getEditorComponent();
2278 6721 ppiqueras
2279 8765 jjdelcerro
                editor.setCaretPosition(document.getLength());
2280
                editor.moveCaretPosition(start);
2281 6721 ppiqueras
            }
2282 8765 jjdelcerro
2283
                /**
2284
                 * If the pattern doesn't match with the selected/current item changes the color of the text to red if isOnlyOneColorOnText_Flag=true, else
2285
             *    sets the color of the text black.
2286
                 *
2287
                 * @param pattern
2288
                 */
2289
                private void formatText(Object item, int offs) {
2290
                    if (!comboBoxReference.isOnlyOneColorOnText_Flag()) {
2291
                            if ((item == null) && (currentShowState != START_VIEW_STATE)) {
2292
                                    editor.getEditorComponent().setForeground(Color.RED);
2293
                                    logger.debug("Pone a Rojo Lookup");
2294
                            }
2295
                            else {
2296
                                    editor.getEditorComponent().setForeground(Color.BLACK);
2297
                                    logger.debug("Pone a Negro Lookup");
2298
                            }
2299
2300
                                // If it's necessary, produces a "beep" sound
2301
                                if ((beepEnabled_Flag) && (item == null) && (!lastWasTheBeginningState)) {
2302
                                        comboBoxReference.getToolkit().beep(); // when available use: UIManager.getLookAndFeel().provideErrorFeedback(comboBox);
2303
                                }
2304
                    }
2305
2306
                    if (useHighlight_Flag) {
2307
2308
                            // Select
2309
                            highlightCompletedText(offs);
2310
                          }
2311
                }
2312
2313
                /**
2314
                 * Returns the current item in the popup of JComboBox or the selected item. If there is no item, returns null
2315
                 *
2316
                 * @return An object
2317
                 */
2318
                private Object lookupItem() {
2319
                Object item = null;
2320
                    if (model.getSize() > 0) {
2321
                            if (specialSelectionByUserState) {
2322
                                    item = model.getSelectedItem();
2323 6760 ppiqueras
                            }
2324
                            else
2325 8765 jjdelcerro
                                    item = model.getElementAt(0);
2326
                    }
2327
2328
                    return item;
2329
                }
2330 6721 ppiqueras
        }
2331
}