78
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2005, 2008 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 * Brad Reynolds (bug 135446)
|
|
11 * Brad Reynolds - bug 164653
|
|
12 *******************************************************************************/
|
|
13 module org.eclipse.jface.internal.databinding.swt.TextObservableValue;
|
|
14
|
|
15 import java.lang.all;
|
|
16
|
|
17 import org.eclipse.core.databinding.observable.Diffs;
|
|
18 import org.eclipse.core.databinding.observable.IObservable;
|
|
19 import org.eclipse.core.databinding.observable.Realm;
|
|
20 import org.eclipse.jface.databinding.swt.SWTObservables;
|
|
21 import org.eclipse.jface.internal.databinding.provisional.swt.AbstractSWTVetoableValue;
|
|
22 import org.eclipse.swt.SWT;
|
|
23 import org.eclipse.swt.events.VerifyEvent;
|
|
24 import org.eclipse.swt.events.VerifyListener;
|
|
25 import org.eclipse.swt.widgets.Event;
|
|
26 import org.eclipse.swt.widgets.Listener;
|
|
27 import org.eclipse.swt.widgets.Text;
|
|
28
|
|
29 /**
|
|
30 * {@link IObservable} implementation that wraps a {@link Text} widget. The time
|
|
31 * at which listeners should be notified about changes to the text is specified
|
|
32 * on construction.
|
|
33 *
|
|
34 * <dl>
|
|
35 * <dt>Events:</dt>
|
|
36 * <dd> If the update event type (specified on construction) is
|
|
37 * <code>SWT.Modify</code> a value change event will be fired on every key
|
|
38 * stroke. If the update event type is <code>SWT.FocusOut</code> a value
|
|
39 * change event will be fired on focus out. When in either mode if the user is
|
|
40 * entering text and presses [Escape] the value will be reverted back to the
|
|
41 * last value set using doSetValue(). Regardless of the update event type a
|
|
42 * value changing event will fire on verify to enable vetoing of changes.</dd>
|
|
43 * </dl>
|
|
44 *
|
|
45 * @since 1.0
|
|
46 */
|
|
47 public class TextObservableValue : AbstractSWTVetoableValue {
|
|
48
|
|
49 /**
|
|
50 * {@link Text} widget that this is being observed.
|
|
51 */
|
|
52 private final Text text;
|
|
53
|
|
54 /**
|
|
55 * Flag to track when the model is updating the widget. When
|
|
56 * <code>true</code> the handlers for the SWT events should not process
|
|
57 * the event as this would cause an infinite loop.
|
|
58 */
|
|
59 private bool updating = false;
|
|
60
|
|
61 /**
|
|
62 * SWT event that on firing this observable will fire change events to its
|
|
63 * listeners.
|
|
64 */
|
|
65 private final int updateEventType;
|
|
66
|
|
67 /**
|
|
68 * Valid types for the {@link #updateEventType}.
|
|
69 */
|
|
70 private static const int[] validUpdateEventTypes = [ SWT.Modify,
|
|
71 SWT.FocusOut, SWT.None ];
|
|
72
|
|
73 /**
|
|
74 * Previous value of the Text.
|
|
75 */
|
|
76 private String oldValue;
|
|
77
|
|
78 private Listener updateListener = new class() Listener {
|
|
79 public void handleEvent(Event event) {
|
|
80 if (!updating) {
|
|
81 String newValue = text.getText();
|
|
82
|
|
83 if (!newValue.equals(oldValue)) {
|
|
84 fireValueChange(Diffs.createValueDiff(oldValue, newValue));
|
|
85 oldValue = newValue;
|
|
86 }
|
|
87 }
|
|
88 }
|
|
89 };
|
|
90
|
|
91 private VerifyListener verifyListener;
|
|
92
|
|
93 /**
|
|
94 * Constructs a new instance bound to the given <code>text</code> widget
|
|
95 * and configured to fire change events to its listeners at the time of the
|
|
96 * <code>updateEventType</code>.
|
|
97 *
|
|
98 * @param text
|
|
99 * @param updateEventType
|
|
100 * SWT event constant as to what SWT event to update the model in
|
|
101 * response to. Appropriate values are: <code>SWT.Modify</code>,
|
|
102 * <code>SWT.FocusOut</code>, <code>SWT.None</code>.
|
|
103 * @throws IllegalArgumentException
|
|
104 * if <code>updateEventType</code> is an incorrect type.
|
|
105 */
|
|
106 public this(Text text, int updateEventType) {
|
|
107 this(SWTObservables.getRealm(text.getDisplay()), text, updateEventType);
|
|
108 }
|
|
109
|
|
110 /**
|
|
111 * Constructs a new instance.
|
|
112 *
|
|
113 * @param realm can not be <code>null</code>
|
|
114 * @param text
|
|
115 * @param updateEventType
|
|
116 */
|
|
117 public this(Realm realm, Text text, int updateEventType) {
|
|
118 super(realm, text);
|
|
119
|
|
120 bool eventValid = false;
|
|
121 for (int i = 0; !eventValid && i < validUpdateEventTypes.length; i++) {
|
|
122 eventValid = (updateEventType is validUpdateEventTypes[i]);
|
|
123 }
|
|
124 if (!eventValid) {
|
|
125 throw new IllegalArgumentException(
|
|
126 "UpdateEventType [" + updateEventType + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$
|
|
127 }
|
|
128 this.text = text;
|
|
129 this.updateEventType = updateEventType;
|
|
130 if (updateEventType !is SWT.None) {
|
|
131 text.addListener(updateEventType, updateListener);
|
|
132 }
|
|
133
|
|
134 oldValue = text.getText();
|
|
135
|
|
136 verifyListener = new class() VerifyListener {
|
|
137 public void verifyText(VerifyEvent e) {
|
|
138 if (!updating) {
|
|
139 String currentText = text
|
|
140 .getText();
|
|
141 String newText = currentText.substring(0, e.start) + e.text
|
|
142 + currentText.substring(e.end);
|
|
143 if (!fireValueChanging(Diffs.createValueDiff(currentText,
|
|
144 newText))) {
|
|
145 e.doit = false;
|
|
146 }
|
|
147 }
|
|
148 }
|
|
149 };
|
|
150 text.addVerifyListener(verifyListener);
|
|
151 }
|
|
152
|
|
153 /**
|
|
154 * Sets the bound {@link Text Text's} text to the passed <code>value</code>.
|
|
155 *
|
|
156 * @param value
|
|
157 * new value, String expected
|
|
158 * @see org.eclipse.core.databinding.observable.value.AbstractVetoableValue#doSetApprovedValue(java.lang.Object)
|
|
159 * @throws ClassCastException
|
|
160 * if the value is anything other than a String
|
|
161 */
|
|
162 protected void doSetApprovedValue(Object value) {
|
|
163 try {
|
|
164 updating = true;
|
|
165 text.setText(value is null ? "" : value.toString()); //$NON-NLS-1$
|
|
166 oldValue = text.getText();
|
|
167 } finally {
|
|
168 updating = false;
|
|
169 }
|
|
170 }
|
|
171
|
|
172 /**
|
|
173 * Returns the current value of the {@link Text}.
|
|
174 *
|
|
175 * @see org.eclipse.core.databinding.observable.value.AbstractVetoableValue#doGetValue()
|
|
176 */
|
|
177 public Object doGetValue() {
|
|
178 return oldValue = text.getText();
|
|
179 }
|
|
180
|
|
181 /**
|
|
182 * Returns the type of the value from {@link #doGetValue()}, i.e.
|
|
183 * String.class
|
|
184 *
|
|
185 * @see org.eclipse.core.databinding.observable.value.IObservableValue#getValueType()
|
|
186 */
|
|
187 public Object getValueType() {
|
|
188 return String.classinfo;
|
|
189 }
|
|
190
|
|
191 public void dispose() {
|
|
192 if (!text.isDisposed()) {
|
|
193 if (updateEventType !is SWT.None) {
|
|
194 text.removeListener(updateEventType, updateListener);
|
|
195 }
|
|
196 text.removeVerifyListener(verifyListener);
|
|
197 }
|
|
198 super.dispose();
|
|
199 }
|
|
200 }
|