Subversion Repositories eFlore/Applications.cel

Rev

Rev 2603 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2602 aurelien 1
package org.tela_botanica.client.util.autocompletion;
2
 
3
import java.util.ArrayList;
4
import java.util.Iterator;
5
import java.util.List;
6
import java.util.Map;
7
 
8
import org.tela_botanica.client.cel2;
9
import org.tela_botanica.client.modeles.objets.Utilisateur;
10
 
11
import com.google.gwt.core.client.Callback;
12
import com.google.gwt.core.client.JavaScriptObject;
13
import com.google.gwt.event.dom.client.KeyCodes;
14
import com.google.gwt.event.dom.client.KeyDownEvent;
15
import com.google.gwt.event.dom.client.KeyDownHandler;
16
import com.google.gwt.event.dom.client.KeyPressEvent;
17
import com.google.gwt.event.dom.client.KeyPressHandler;
18
import com.google.gwt.event.logical.shared.SelectionEvent;
19
import com.google.gwt.event.logical.shared.SelectionHandler;
20
import com.google.gwt.event.logical.shared.ValueChangeEvent;
21
import com.google.gwt.event.logical.shared.ValueChangeHandler;
22
import com.google.gwt.http.client.Request;
23
import com.google.gwt.http.client.RequestBuilder;
24
import com.google.gwt.http.client.RequestCallback;
25
import com.google.gwt.http.client.RequestException;
26
import com.google.gwt.http.client.Response;
27
import com.google.gwt.http.client.URL;
28
import com.google.gwt.user.client.Event;
29
import com.google.gwt.user.client.Timer;
30
import com.google.gwt.user.client.Window;
31
import com.google.gwt.user.client.ui.ChangeListener;
32
import com.google.gwt.user.client.ui.Label;
33
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
34
import com.google.gwt.user.client.ui.SuggestBox;
35
import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
36
import com.google.gwt.user.client.ui.TextBox;
37
import com.google.gwt.user.client.ui.SuggestBox.SuggestionDisplay;
38
import com.google.gwt.user.client.ui.SuggestOracle;
39
import com.google.gwt.user.client.ui.Widget;
40
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
41
import com.gwtext.client.widgets.BoxComponent;
42
import com.gwtext.client.widgets.Component;
43
import com.gwtext.client.widgets.Container;
44
import com.gwtext.client.widgets.Panel;
45
import com.gwtext.client.widgets.event.PanelListener;
46
import com.gwtext.client.widgets.event.PanelListenerAdapter;
47
import com.gwtext.client.widgets.layout.FitLayout;
48
 
49
@SuppressWarnings("unchecked")
50
public abstract class AutoCompletionComboBox extends Panel {
51
 
52
	Label label = null;
53
	MultiWordSuggestOracle msu = null;
54
	SuggestBox suggestions = null;
55
	DefaultSuggestionDisplay sgd = null;
56
 
57
	Callback<String, String> surCopierColler = null;
58
 
59
	SuggestOracle.Request requeteOracle;
60
    SuggestOracle.Callback callBackOracle;
61
 
62
	Timer suggestionTimer = null;
63
    int tempsAvantRequete = 500;
64
 
65
    Map<String, String> possibilites = null;
66
 
67
    String urlRequete = "";
68
 
69
	public AutoCompletionComboBox(String nomLabel, String urlRequete) {
70
 
71
		this.setStyleName("champAutoComplete");
72
 
73
		this.label = new Label(nomLabel+":");
74
		this.urlRequete = urlRequete;
75
 
76
		sgd = new SuggestBox.DefaultSuggestionDisplay();
77
		msu = new MultiWordSuggestOracle() {
78
			@Override
79
			public void requestSuggestions(Request request, Callback callback) {
80
				List<MultiWordSuggestion> retenus = new ArrayList<MultiWordSuggestion>();
81
				Iterator<String> it = possibilites.keySet().iterator();
82
			    while (it.hasNext()) {
83
			    	String cle = it.next();
2607 aurelien 84
			    	String cleAffichee = preTraiterValeurAvantAffichage(possibilites.get(cle));
85
					MultiWordSuggestion muWoSug = new MultiWordSuggestion(possibilites.get(cle), cleAffichee);
2602 aurelien 86
					retenus.add(muWoSug);
87
			    }
88
 
89
				Response reponse = new Response(retenus);
90
				callback.onSuggestionsReady(request, reponse);
91
			}
92
		};
93
 
94
		suggestions = new SuggestBox(msu, new TextBox(), sgd) {
95
			public void onBrowserEvent(Event event) {
96
			    switch (event.getTypeInt()) {
97
			        case Event.ONPASTE: {
98
			        	if(surCopierColler != null) {
99
			        		surCopierColler.onSuccess(suggestions.getValueBox().getValue());
100
			        	}
101
			        }
102
			        break;
103
			        default:
104
			        	super.onBrowserEvent(event);
105
			    }
106
 
107
			}
108
		};
109
 
110
		suggestions.setAutoSelectEnabled(false);
111
		setLayout(new FitLayout());
112
		add(label);
113
		add(suggestions);
114
		gererEvenements();
115
	}
116
 
117
	public void gererEvenements() {
118
		suggestions.addKeyDownHandler(new KeyDownHandler() {
119
 
120
		    @Override
121
		    public void onKeyDown(KeyDownEvent event) {
122
		    	// Lorsque la liste de suggestions est ouverte, une frappe sur entrée selectionne la valeur
123
		    	// Si elle est fermée, elle déclenche la fonction abstraite de validation (utile pour les champs
124
		    	// du genre station, milieu etc... et la saisie d'obs rapide
125
				if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
126
					if((sgd == null || !sgd.isSuggestionListShowing())) {
127
						onValidationSaisie();
128
						event.stopPropagation();
129
						return;
130
					} else {
131
						// Dans les autres cas, un appui sur entrée ne doit pas redéclencher l'autcomplétion
132
						return;
133
					}
134
				}
135
 
136
				// Tout autre frappe d'un caractère "normal" déclenche le timer d'autocomplétion
137
				if(!KeyDownEvent.isArrow(event.getNativeKeyCode())) {
138
					gererTimer();
139
				}
140
		    }
141
 
142
		});
143
 
144
		requeteOracle = new SuggestOracle.Request();
145
		callBackOracle = new SuggestOracle.Callback() {
146
 
147
			public void onSuggestionsReady(SuggestOracle.Request request, SuggestOracle.Response response) {
148
				suggestions.showSuggestionList();
149
			}
150
	    };
151
 
152
	    suggestions.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>(){
153
			@Override
154
			public void onSelection(SelectionEvent<Suggestion> event) {
155
				onSelectionValeur();
156
			}
157
		});
158
 
159
	    suggestions.addValueChangeHandler(new ValueChangeHandler<String>() {
160
			@Override
161
			public void onValueChange(ValueChangeEvent<String> event) {
162
				onModificationValeur();
163
			}
164
		});
165
 
166
	    surCopierColler = new Callback<String, String>() {
167
			@Override
168
			public void onSuccess(String result) {
169
				gererTimer();
170
			}
171
 
172
			@Override
173
			public void onFailure(String reason) {
174
				// rien à faire ça n'échoue jamais
175
			}
176
		};
177
 
178
		addListener(new PanelListenerAdapter() {
179
 
180
			@Override
181
			public void onResize(BoxComponent component, int adjWidth, int adjHeight,
182
					int rawWidth, int rawHeight) {
183
				redimensionner(rawWidth);
184
			}
185
		});
186
	}
187
 
188
	public void redimensionner(final int largeur) {
189
		suggestions.setWidth((largeur - label.getOffsetWidth() - 13)+"px");
190
	}
191
 
192
	public void gererTimer() {
193
		if(suggestionTimer == null) {
194
			suggestionTimer = new Timer() {
195
				public void run() {
196
					requeteSuggestions();
197
				}
198
			};
199
			suggestionTimer.schedule(tempsAvantRequete);
200
		} else {
201
			suggestionTimer.schedule(tempsAvantRequete);
202
		}
203
	}
204
 
205
	public void setTempsAvantRequete(int temps) {
206
		tempsAvantRequete = temps;
207
	}
208
 
209
	public int getTempsAvantRequete(int temps) {
210
		return tempsAvantRequete;
211
	}
212
 
213
	public void requeteSuggestions() {
214
 
215
		// Suppression des espaces et caractères inutiles
2603 aurelien 216
		String valeur = suggestions.getValue().trim().isEmpty() ? null : suggestions.getValue().trim();
2602 aurelien 217
 
218
		// ceci permet au composant qui utilise l'autocomplétion
2603 aurelien 219
		// d'annuler une requete et également d'éviter de faire une requête lors du vidage du champ
2607 aurelien 220
		if(valeur == null) {
2602 aurelien 221
			return;
222
		}
223
 
2607 aurelien 224
		final String urlRequeteFmt = preTraiterUrlRequete(urlRequete, valeur);
225
		RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, urlRequeteFmt) ;
2602 aurelien 226
		try {
227
			rb.sendRequest(null, new RequestCallback() {
228
				public void onError(final Request request, final Throwable exception) {
229
					// TODO Auto-generated method stub
230
				}
231
 
232
				public void onResponseReceived(final Request request,
233
						final Response response) {
2607 aurelien 234
					surReponseRequete(urlRequeteFmt, response);
2602 aurelien 235
				}
236
			}) ;
237
 
238
		} catch (RequestException e) {
239
			// TODO Auto-generated catch block
240
			e.printStackTrace();
241
		}
242
	}
243
 
244
	public void surReponseRequete(String requete, Response response) {
245
		possibilites = parserResultatRequete(response);
246
		msu.clear();
247
		Iterator<String> it = possibilites.keySet().iterator();
248
	    while (it.hasNext()) {
249
	    	msu.add(possibilites.get(it.next()));
250
	    }
251
 
252
		requeteOracle.setQuery(requete);
253
		msu.requestSuggestions(requeteOracle, callBackOracle);
254
	}
255
 
256
	public String getText() {
257
		return suggestions.getText();
258
	}
259
 
260
	public String getRawValue() {
261
		return suggestions.getText();
262
	}
263
 
264
	public void setValue(String texte) {
265
		suggestions.setText(texte);
266
	}
267
 
268
	public void reset() {
269
		suggestions.setValue("");
270
	}
271
 
272
	public void setTabIndex(int index) {
273
		suggestions.setTabIndex(index);
274
	}
275
 
2603 aurelien 276
	public String getLabelText() {
277
		return label.getText();
278
	}
279
 
280
	public int getFieldWidth() {
281
		return suggestions.getOffsetWidth();
282
	}
283
 
284
	public int getLabelWidth() {
285
		return label.getOffsetWidth();
286
	}
287
 
288
	public void agrandirChamp(int largeur) {
289
		suggestions.setWidth(largeur+"px");
290
	}
291
 
2607 aurelien 292
	protected String preTraiterValeurAvantAffichage(String valeur) {
293
		return valeur;
294
	}
295
	protected String preTraiterUrlRequete(String urlRequete, String valeur) {
296
		return urlRequete+URL.encodeQueryString(valeur);
297
	}
2602 aurelien 298
	protected abstract Map<String, String> parserResultatRequete(Response response);
299
	protected abstract void onModificationValeur();
300
	protected abstract void onSelectionValeur();
301
	protected abstract void onValidationSaisie();
302
}