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 | } |