]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.spreadsheet.ui/src/org/simantics/spreadsheet/ui/TrackedText.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.spreadsheet.ui / src / org / simantics / spreadsheet / ui / TrackedText.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.spreadsheet.ui;\r
13 \r
14 import java.awt.Color;\r
15 import java.awt.event.ActionEvent;\r
16 import java.awt.event.ActionListener;\r
17 import java.awt.event.ComponentEvent;\r
18 import java.awt.event.ComponentListener;\r
19 import java.awt.event.ContainerEvent;\r
20 import java.awt.event.ContainerListener;\r
21 import java.awt.event.FocusEvent;\r
22 import java.awt.event.FocusListener;\r
23 import java.awt.event.HierarchyBoundsListener;\r
24 import java.awt.event.HierarchyEvent;\r
25 import java.awt.event.HierarchyListener;\r
26 import java.awt.event.InputMethodEvent;\r
27 import java.awt.event.InputMethodListener;\r
28 import java.awt.event.KeyEvent;\r
29 import java.awt.event.KeyListener;\r
30 import java.awt.event.MouseEvent;\r
31 import java.awt.event.MouseListener;\r
32 import java.awt.event.MouseMotionListener;\r
33 import java.awt.event.MouseWheelEvent;\r
34 import java.awt.event.MouseWheelListener;\r
35 import java.beans.PropertyChangeEvent;\r
36 import java.beans.PropertyChangeListener;\r
37 import java.beans.PropertyVetoException;\r
38 import java.beans.VetoableChangeListener;\r
39 \r
40 import javax.swing.JTextField;\r
41 import javax.swing.event.AncestorEvent;\r
42 import javax.swing.event.AncestorListener;\r
43 import javax.swing.event.CaretEvent;\r
44 import javax.swing.event.CaretListener;\r
45 \r
46 import org.eclipse.core.runtime.Assert;\r
47 import org.eclipse.core.runtime.ListenerList;\r
48 import org.eclipse.jface.dialogs.IInputValidator;\r
49 \r
50 /**\r
51  * This is a TrackedTest SWT Text-widget 'decorator'.\r
52  * \r
53  * The widget has 2 main states: editing and inactive.\r
54  * \r
55  * It implements the necessary listeners to achieve the text widget behaviour\r
56  * needed by Simantics. User notification about modifications is provided via\r
57  * {@link TrackedModifyListener}.\r
58  * \r
59  * Examples:\r
60  * \r
61  * <pre>\r
62  * // #1: create new Text internally, use TrackedModifylistener\r
63  * TrackedText trackedText = new TrackedText(parentComposite, style); \r
64  * trackedText.addModifyListener(new TrackedModifyListener() {\r
65  *     public void modifyText(TrackedModifyEvent e) {\r
66  *         // text was modified, do something.\r
67  *     }\r
68  * });\r
69  * \r
70  * // #2: create new Text internally, define the colors for text states.\r
71  * TrackedText trackedText = new TrackedText(text, &lt;instance of ITrackedColorProvider&gt;); \r
72  * </pre>\r
73  * \r
74  * @author Tuukka Lehtonen\r
75  */\r
76 public class TrackedText {\r
77     \r
78     private static final boolean  EVENT_DEBUG = false;\r
79     \r
80     private static final int      EDITING                 = 1 << 0;\r
81     private static final int      MODIFIED_DURING_EDITING = 1 << 1;\r
82 \r
83     /**\r
84      * Used to tell whether or not a mouseDown has occured after a focusGained\r
85      * event to be able to select the whole text field when it is pressed for\r
86      * the first time while the widget holds focus.\r
87      */\r
88     private static final int      MOUSE_DOWN_FIRST_TIME   = 1 << 2;\r
89     private static final int      MOUSE_INSIDE_CONTROL    = 1 << 3;\r
90 \r
91     private int                   state;\r
92 \r
93     private int                   caretPositionBeforeEdit;\r
94 \r
95     private String                textBeforeEdit;\r
96 \r
97     private JTextField            text;\r
98 \r
99     private CompositeListener     listener;\r
100 \r
101     private ListenerList          modifyListeners;\r
102 \r
103     private IInputValidator       validator;\r
104 \r
105     private ITrackedColorProvider colorProvider;\r
106 \r
107     private class DefaultColorProvider implements ITrackedColorProvider {\r
108         \r
109         private Color editingColor = new Color(255, 255, 255);\r
110         \r
111 //        private Color highlightColor = new Color(text.getDisplay(), 254, 255, 197);\r
112 //        private Color inactiveColor = new Color(text.getDisplay(), 245, 246, 190);\r
113 //        private Color invalidInputColor = new Color(text.getDisplay(), 255, 128, 128);\r
114 \r
115         @Override\r
116         public Color getEditingBackground() {\r
117             return editingColor;\r
118         }\r
119 \r
120         @Override\r
121         public Color getHoverBackground() {\r
122             return null;\r
123 //            return highlightColor;\r
124         }\r
125 \r
126         @Override\r
127         public Color getInactiveBackground() {\r
128             return null;\r
129 //            return inactiveColor;\r
130         }\r
131 \r
132         @Override\r
133         public Color getInvalidBackground() {\r
134             return null;\r
135 //            return invalidInputColor;\r
136         }\r
137         \r
138         void dispose() {\r
139 //            highlightColor.dispose();\r
140 //            inactiveColor.dispose();\r
141 //            invalidInputColor.dispose();\r
142         }\r
143     };\r
144     \r
145 //    /**\r
146 //     * A composite of many UI listeners for creating the functionality of this\r
147 //     * class.\r
148 //     */\r
149 //    private class CompositeListener\r
150 //    implements ModifyListener, DisposeListener, KeyListener, MouseTrackListener,\r
151 //            MouseListener, FocusListener\r
152 //    {\r
153 //        // Keyboard/editing events come in the following order:\r
154 //        //   1. keyPressed\r
155 //        //   2. verifyText\r
156 //        //   3. modifyText\r
157 //        //   4. keyReleased\r
158 //        \r
159 //        public void modifyText(ModifyEvent e) {\r
160 //            //System.out.println("modifyText: " + e);\r
161 //            setModified(true);\r
162 //            \r
163 ////            String valid = isTextValid();\r
164 ////            if (valid != null) {\r
165 ////                setBackground(colorProvider.getInvalidBackground());\r
166 ////            } else {\r
167 ////                if (isEditing())\r
168 ////                    setBackground(colorProvider.getEditingBackground());\r
169 ////                else\r
170 ////                    setBackground(colorProvider.getInactiveBackground());\r
171 ////            }\r
172 //        }\r
173 //\r
174 //        public void widgetDisposed(DisposeEvent e) {\r
175 //            getWidget().removeModifyListener(this);\r
176 //        }\r
177 //        \r
178 //        private boolean isMultiLine() {\r
179 //            return false;\r
180 ////            return (text.getStyle() & SWT.MULTI) != 0;\r
181 //        }\r
182 //        \r
183 //        private boolean hasMultiLineCommitModifier(KeyEvent e) {\r
184 //            return (e.stateMask & SWT.CTRL) != 0;\r
185 //        }\r
186 //\r
187 //        public void keyPressed(KeyEvent e) {\r
188 //            //System.out.println("keyPressed: " + e);\r
189 //            if (!isEditing()) {\r
190 //                // ESC, ENTER & keypad ENTER must not start editing \r
191 //                if (e.keyCode == SWT.ESC)\r
192 //                    return;\r
193 //\r
194 //                if (!isMultiLine()) {\r
195 //                    if (e.keyCode == SWT.F2 || e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
196 //                        startEdit(true);\r
197 //                    } else if (e.character != '\0') {\r
198 //                        startEdit(false);\r
199 //                    }\r
200 //                } else {\r
201 //                    // In multi-line mode, TAB must not start editing!\r
202 //                    if (e.keyCode == SWT.F2) {\r
203 //                        startEdit(true);\r
204 //                    } else if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
205 //                        if (hasMultiLineCommitModifier(e)) {\r
206 //                            e.doit = false;\r
207 //                        } else {\r
208 //                            startEdit(false);\r
209 //                        }\r
210 //                    } else if (e.keyCode == SWT.TAB) {\r
211 //                        text.traverse(((e.stateMask & SWT.SHIFT) != 0) ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT);\r
212 //                        e.doit = false;\r
213 //                    } else if (e.character != '\0') {\r
214 //                        startEdit(false);\r
215 //                    }\r
216 //                }\r
217 //            } else {\r
218 //                // ESC reverts any changes made during this edit\r
219 //                if (e.keyCode == SWT.ESC) {\r
220 //                    revertEdit();\r
221 //                }\r
222 //                if (!isMultiLine()) {\r
223 //                    if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
224 //                        applyEdit();\r
225 //                    }\r
226 //                } else {\r
227 //                    if (e.keyCode == SWT.CR || e.keyCode == SWT.KEYPAD_CR) {\r
228 //                        if (hasMultiLineCommitModifier(e)) {\r
229 //                            applyEdit();\r
230 //                            e.doit = false;\r
231 //                        }\r
232 //                    }\r
233 //                }\r
234 //            }\r
235 //        }\r
236 //\r
237 //        public void keyReleased(KeyEvent e) {\r
238 //            //System.out.println("keyReleased: " + e);\r
239 //        }\r
240 //\r
241 //        public void mouseEnter(MouseEvent e) {\r
242 //            //System.out.println("mouseEnter");\r
243 //            if (!isEditing()) {\r
244 //                setBackground(colorProvider.getHoverBackground());\r
245 //            }\r
246 //            setMouseInsideControl(true);\r
247 //        }\r
248 //\r
249 //        public void mouseExit(MouseEvent e) {\r
250 //            //System.out.println("mouseExit");\r
251 //            if (!isEditing()) {\r
252 //                setBackground(colorProvider.getInactiveBackground());\r
253 //            }\r
254 //            setMouseInsideControl(false);\r
255 //        }\r
256 //\r
257 //        public void mouseHover(MouseEvent e) {\r
258 //            //System.out.println("mouseHover");\r
259 //            setMouseInsideControl(true);\r
260 //        }\r
261 //\r
262 //        public void mouseDoubleClick(MouseEvent e) {\r
263 //            //System.out.println("mouseDoubleClick: " + e);\r
264 //            if (e.button == 1) {\r
265 //                getWidget().selectAll();\r
266 //            }\r
267 //        }\r
268 //\r
269 //        public void mouseDown(MouseEvent e) {\r
270 //            //System.out.println("mouseDown: " + e);\r
271 //            if (!isEditing()) {\r
272 //                // In reality we should never get here, since focusGained\r
273 //                // always comes before mouseDown, but let's keep this\r
274 //                // fallback just to be safe.\r
275 //                if (e.button == 1) {\r
276 //                    startEdit(true);\r
277 //                }\r
278 //            } else {\r
279 //                if (e.button == 1 && (state & MOUSE_DOWN_FIRST_TIME) != 0) {\r
280 //                    getWidget().selectAll();\r
281 //                    state &= ~MOUSE_DOWN_FIRST_TIME;\r
282 //                }\r
283 //            }\r
284 //        }\r
285 //\r
286 //        public void mouseUp(MouseEvent e) {\r
287 //        }\r
288 //\r
289 //        public void focusGained(FocusEvent e) {\r
290 //            //System.out.println("focusGained");\r
291 //            if (!isEditing()) {\r
292 //                if (!isMultiLine()) {\r
293 //                    // Always start edit on single line texts when focus is gained\r
294 //                    startEdit(true);\r
295 //                }\r
296 //            }\r
297 //        }\r
298 //\r
299 //        public void focusLost(FocusEvent e) {\r
300 //            //System.out.println("focusLost");\r
301 //            if (isEditing()) {\r
302 //                applyEdit();\r
303 //            }\r
304 //        }\r
305 //    }\r
306     \r
307     public TrackedText(JTextField text) {\r
308         Assert.isNotNull(text);\r
309         this.state = 0;\r
310         this.text = text;\r
311         this.colorProvider = new DefaultColorProvider();\r
312 \r
313         initialize();\r
314     }\r
315     \r
316     public TrackedText(JTextField text, ITrackedColorProvider colorProvider) {\r
317         Assert.isNotNull(text, "text must not be null");\r
318         Assert.isNotNull(colorProvider, "colorProvider must not be null");\r
319         this.state = 0;\r
320         this.text = text;\r
321         this.colorProvider = colorProvider;\r
322 \r
323         initialize();\r
324     }\r
325 \r
326     private class CompositeListener implements ActionListener, CaretListener, AncestorListener, ComponentListener, ContainerListener, FocusListener, HierarchyBoundsListener, HierarchyListener,\r
327         InputMethodListener, KeyListener, MouseListener, MouseMotionListener, MouseWheelListener, PropertyChangeListener, VetoableChangeListener {\r
328 \r
329         @Override\r
330         public void actionPerformed(ActionEvent arg0) {\r
331             if(EVENT_DEBUG) System.out.println("actionPerformed " + arg0);\r
332         }\r
333 \r
334         @Override\r
335         public void caretUpdate(CaretEvent arg0) {\r
336             if(EVENT_DEBUG) System.out.println("caretUpdate " + arg0);\r
337         }\r
338 \r
339         @Override\r
340         public void ancestorAdded(AncestorEvent arg0) {\r
341             if(EVENT_DEBUG) System.out.println("ancestorAdded " + arg0);\r
342         }\r
343 \r
344         @Override\r
345         public void ancestorMoved(AncestorEvent arg0) {\r
346             if(EVENT_DEBUG) System.out.println("ancestorMoved " + arg0);\r
347         }\r
348 \r
349         @Override\r
350         public void ancestorRemoved(AncestorEvent arg0) {\r
351             if(EVENT_DEBUG) System.out.println("ancestorRemoved " + arg0);\r
352         }\r
353 \r
354         @Override\r
355         public void componentHidden(ComponentEvent arg0) {\r
356             if(EVENT_DEBUG) System.out.println("componentHidden " + arg0);\r
357         }\r
358 \r
359         @Override\r
360         public void componentMoved(ComponentEvent arg0) {\r
361             if(EVENT_DEBUG) System.out.println("componentMoved " + arg0);\r
362         }\r
363 \r
364         @Override\r
365         public void componentResized(ComponentEvent arg0) {\r
366             if(EVENT_DEBUG) System.out.println("componentResized " + arg0);\r
367         }\r
368 \r
369         @Override\r
370         public void componentShown(ComponentEvent arg0) {\r
371             if(EVENT_DEBUG) System.out.println("componentShown " + arg0);\r
372         }\r
373 \r
374         @Override\r
375         public void componentAdded(ContainerEvent arg0) {\r
376             if(EVENT_DEBUG) System.out.println("componentAdded " + arg0);\r
377         }\r
378 \r
379         @Override\r
380         public void componentRemoved(ContainerEvent arg0) {\r
381             if(EVENT_DEBUG) System.out.println("componentRemoved " + arg0);\r
382         }\r
383 \r
384         @Override\r
385         public void focusGained(FocusEvent arg0) {\r
386             if(EVENT_DEBUG) System.out.println("focusGained " + arg0);\r
387             if(!isEditing())\r
388                 startEdit(false);\r
389         }\r
390 \r
391         @Override\r
392         public void focusLost(FocusEvent arg0) {\r
393             if(EVENT_DEBUG) System.out.println("focusLost " + arg0);\r
394         }\r
395 \r
396         @Override\r
397         public void ancestorMoved(HierarchyEvent arg0) {\r
398             if(EVENT_DEBUG) System.out.println("ancestorMoved " + arg0);\r
399         }\r
400 \r
401         @Override\r
402         public void ancestorResized(HierarchyEvent arg0) {\r
403             if(EVENT_DEBUG) System.out.println("ancestorResized " + arg0);\r
404         }\r
405 \r
406         @Override\r
407         public void hierarchyChanged(HierarchyEvent arg0) {\r
408             if(EVENT_DEBUG) System.out.println("hierarchyChanged " + arg0);\r
409         }\r
410 \r
411         @Override\r
412         public void caretPositionChanged(InputMethodEvent arg0) {\r
413             if(EVENT_DEBUG) System.out.println("caretPositionChanged " + arg0);\r
414         }\r
415 \r
416         @Override\r
417         public void inputMethodTextChanged(InputMethodEvent arg0) {\r
418             if(EVENT_DEBUG) System.out.println("inputMethodTextChanged " + arg0);\r
419         }\r
420 \r
421         @Override\r
422         public void keyPressed(KeyEvent arg0) {\r
423             if(EVENT_DEBUG) System.out.println("keyPressed " + arg0);\r
424             if(arg0.getKeyCode() == KeyEvent.VK_ESCAPE) {\r
425                 revertEdit();\r
426             }\r
427             if(arg0.getKeyCode() == KeyEvent.VK_ENTER) {\r
428                 applyEdit();\r
429             }\r
430         }\r
431 \r
432         @Override\r
433         public void keyReleased(KeyEvent arg0) {\r
434             if(EVENT_DEBUG) System.out.println("keyReleased " + arg0);\r
435             setModified(true);\r
436             if(!isEditing())\r
437                 startEdit(false);\r
438         }\r
439 \r
440         @Override\r
441         public void keyTyped(KeyEvent arg0) {\r
442             if(EVENT_DEBUG) System.out.println("keyTyped " + arg0);\r
443         }\r
444 \r
445         @Override\r
446         public void mouseClicked(MouseEvent arg0) {\r
447             if(EVENT_DEBUG) System.out.println("mouseClicked " + arg0);\r
448         }\r
449 \r
450         @Override\r
451         public void mouseEntered(MouseEvent arg0) {\r
452             if(EVENT_DEBUG) System.out.println("mouseEntered " + arg0);\r
453         }\r
454 \r
455         @Override\r
456         public void mouseExited(MouseEvent arg0) {\r
457             if(EVENT_DEBUG) System.out.println("mouseExited " + arg0);\r
458         }\r
459 \r
460         @Override\r
461         public void mousePressed(MouseEvent arg0) {\r
462             if(EVENT_DEBUG) System.out.println("mousePressed " + arg0);\r
463         }\r
464 \r
465         @Override\r
466         public void mouseReleased(MouseEvent arg0) {\r
467             if(EVENT_DEBUG) System.out.println("mouseReleased " + arg0);\r
468         }\r
469 \r
470         @Override\r
471         public void mouseDragged(MouseEvent arg0) {\r
472             if(EVENT_DEBUG) System.out.println("mouseDragged " + arg0);\r
473         }\r
474 \r
475         @Override\r
476         public void mouseMoved(MouseEvent arg0) {\r
477             if(EVENT_DEBUG) System.out.println("mouseMoved " + arg0);\r
478         }\r
479 \r
480         @Override\r
481         public void mouseWheelMoved(MouseWheelEvent arg0) {\r
482             if(EVENT_DEBUG) System.out.println("mouseWheelMoved " + arg0);\r
483         }\r
484 \r
485         @Override\r
486         public void propertyChange(PropertyChangeEvent arg0) {\r
487             if(EVENT_DEBUG) System.out.println("propertyChange " + arg0);\r
488         }\r
489 \r
490         @Override\r
491         public void vetoableChange(PropertyChangeEvent arg0) throws PropertyVetoException {\r
492             if(EVENT_DEBUG) System.out.println("vetoableChange " + arg0);\r
493         }\r
494         \r
495     };\r
496     \r
497     /**\r
498      * Common initialization. Assumes that text is already created.\r
499      */\r
500     private void initialize() {\r
501         Assert.isNotNull(text);\r
502         \r
503 //        text.setBackground(colorProvider.getInactiveBackground());\r
504 //        text.setDoubleClickEnabled(false);\r
505         \r
506         listener = new CompositeListener();\r
507 \r
508         text.addActionListener(listener);\r
509         text.addCaretListener(listener);\r
510         text.addAncestorListener(listener);\r
511         text.addComponentListener(listener);\r
512         text.addContainerListener(listener);\r
513         text.addFocusListener(listener);\r
514         text.addHierarchyBoundsListener(listener);\r
515         text.addHierarchyListener(listener);\r
516         text.addInputMethodListener(listener);\r
517         text.addKeyListener(listener);\r
518         text.addMouseListener(listener);\r
519         text.addMouseMotionListener(listener);\r
520         text.addMouseWheelListener(listener);\r
521         text.addPropertyChangeListener(listener);\r
522         text.addVetoableChangeListener(listener);\r
523         \r
524     }\r
525     \r
526     private void startEdit(boolean selectAll) {\r
527         if (isEditing()) {\r
528             // Print some debug incase we end are in an invalid state\r
529             System.out.println("TrackedText: BUG: startEdit called when in editing state");\r
530         }\r
531         //System.out.println("start edit: selectall=" + selectAll + ", text=" + text.getText() + ", caretpos=" + caretPositionBeforeEdit);\r
532 \r
533         // Backup text-field data for reverting purposes\r
534         caretPositionBeforeEdit = text.getCaretPosition();\r
535         textBeforeEdit = text.getText();\r
536 \r
537         // Signal editing state\r
538         setBackground(colorProvider.getEditingBackground());\r
539         \r
540         if (selectAll) {\r
541             text.selectAll();\r
542         }\r
543         state |= EDITING | MOUSE_DOWN_FIRST_TIME;\r
544     }\r
545 \r
546     private void applyEdit() {\r
547         try {\r
548             if (isTextValid() != null) {\r
549                 text.setText(textBeforeEdit);\r
550             } else if (isModified() && !text.getText().equals(textBeforeEdit)) {\r
551                 //System.out.println("apply");\r
552                 if (modifyListeners != null) {\r
553                     TrackedModifyEvent event = new TrackedModifyEvent(text, text.getText());\r
554                     for (Object o : modifyListeners.getListeners()) {\r
555                         ((TrackedModifyListener) o).modifyText(event);\r
556                     }\r
557                 }\r
558             }\r
559         } finally {\r
560             endEdit();\r
561         }\r
562     }\r
563     \r
564     private void endEdit() {\r
565         if (!isEditing()) {\r
566             // Print some debug incase we end are in an invalid state\r
567             //ExceptionUtils.logError(new Exception("BUG: endEdit called when not in editing state"));\r
568         }\r
569         setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
570         //System.out.println("endEdit: " + text.getText() + ", caret: " + text.getCaretLocation() + ", selection: " + text.getSelection());\r
571         // Always move the caret to the end of the string\r
572         text.setCaretPosition(text.getText().length());\r
573         state &= ~(EDITING | MOUSE_DOWN_FIRST_TIME);\r
574         setModified(false);\r
575     }\r
576 \r
577     private void revertEdit() {\r
578         if (!isEditing()) {\r
579             // Print some debug incase we end are in an invalid state\r
580             //ExceptionUtils.logError(new Exception("BUG: revertEdit called when not in editing state"));\r
581             System.out.println("BUG: revertEdit called when not in editing state");\r
582         }\r
583         text.setText(textBeforeEdit);\r
584         text.setCaretPosition(caretPositionBeforeEdit);\r
585         setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
586         state &= ~(EDITING | MOUSE_DOWN_FIRST_TIME);\r
587         setModified(false);\r
588     }\r
589     \r
590     private boolean isEditing() {\r
591         return (state & EDITING) != 0;\r
592     }\r
593     \r
594     private void setModified(boolean modified) {\r
595         if (modified) {\r
596             state |= MODIFIED_DURING_EDITING;\r
597         } else {\r
598             state &= ~MODIFIED_DURING_EDITING;\r
599         }\r
600     }\r
601     \r
602     private boolean isMouseInsideControl() {\r
603         return (state & MOUSE_INSIDE_CONTROL) != 0;\r
604     }\r
605     \r
606     private void setMouseInsideControl(boolean inside) {\r
607         if (inside)\r
608             state |= MOUSE_INSIDE_CONTROL;\r
609         else\r
610             state &= ~MOUSE_INSIDE_CONTROL;\r
611     }\r
612     \r
613     private boolean isModified() {\r
614         return (state & MODIFIED_DURING_EDITING) != 0;\r
615     }\r
616     \r
617     public void setEditable(boolean editable) {\r
618         if (editable) {\r
619             text.setEditable(true);\r
620             setBackground(isMouseInsideControl() ? colorProvider.getHoverBackground() : colorProvider.getInactiveBackground());\r
621         } else {\r
622             text.setEditable(false);\r
623             text.setBackground(null);\r
624         }\r
625     }\r
626     \r
627     public void setText(String text) {\r
628         this.text.setText(text);\r
629     }\r
630     \r
631     public void setTextWithoutNotify(String text) {\r
632 //        this.text.removeModifyListener(listener);\r
633         setText(text);\r
634 //        this.text.addModifyListener(listener);\r
635     }\r
636 \r
637     public JTextField getWidget() {\r
638         return text;\r
639     }\r
640     \r
641     public synchronized void addModifyListener(TrackedModifyListener listener) {\r
642         if (modifyListeners == null) {\r
643             modifyListeners = new ListenerList(ListenerList.IDENTITY);\r
644         }\r
645         modifyListeners.add(listener);\r
646     }\r
647     \r
648     public synchronized void removeModifyListener(TrackedModifyListener listener) {\r
649         if (modifyListeners == null)\r
650             return;\r
651         modifyListeners.remove(listener);\r
652     }\r
653     \r
654     public void setInputValidator(IInputValidator validator) {\r
655         if (validator != this.validator) {\r
656             this.validator = validator;\r
657         }\r
658     }\r
659     \r
660     private String isTextValid() {\r
661         if (validator != null) {\r
662             return validator.isValid(getWidget().getText());\r
663         }\r
664         return null;\r
665     }\r
666     \r
667     public void setColorProvider(ITrackedColorProvider provider) {\r
668         Assert.isNotNull(provider);\r
669         this.colorProvider = provider;\r
670     }\r
671     \r
672     private void setBackground(Color background) {\r
673         if (!text.isEditable()) {\r
674             // Do not alter background when the widget is not editable.\r
675             return;\r
676         }\r
677         text.setBackground(background);\r
678     }\r
679     \r
680 }\r