Subversion Repositories eFlore/Applications.cel

Rev

Rev 2607 | 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
 
2640 aurelien 136
				if(event.getNativeKeyCode() == KeyCodes.KEY_DOWN) {
137
					// Un appui sur flèche bas permet de demander toute la liste
138
					if(!sgd.isSuggestionListShowing()) {
139
						requeteToutesSuggestions();
140
					}
141
				}
142
 
2602 aurelien 143
				// Tout autre frappe d'un caractère "normal" déclenche le timer d'autocomplétion
144
				if(!KeyDownEvent.isArrow(event.getNativeKeyCode())) {
145
					gererTimer();
146
				}
147
		    }
148
 
149
		});
150
 
151
		requeteOracle = new SuggestOracle.Request();
152
		callBackOracle = new SuggestOracle.Callback() {
153
 
154
			public void onSuggestionsReady(SuggestOracle.Request request, SuggestOracle.Response response) {
155
				suggestions.showSuggestionList();
156
			}
157
	    };
158
 
159
	    suggestions.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>(){
160
			@Override
161
			public void onSelection(SelectionEvent<Suggestion> event) {
162
				onSelectionValeur();
163
			}
164
		});
165
 
166
	    suggestions.addValueChangeHandler(new ValueChangeHandler<String>() {
167
			@Override
168
			public void onValueChange(ValueChangeEvent<String> event) {
169
				onModificationValeur();
170
			}
171
		});
172
 
173
	    surCopierColler = new Callback<String, String>() {
174
			@Override
175
			public void onSuccess(String result) {
176
				gererTimer();
177
			}
178
 
179
			@Override
180
			public void onFailure(String reason) {
181
				// rien à faire ça n'échoue jamais
182
			}
183
		};
184
 
185
		addListener(new PanelListenerAdapter() {
186
 
187
			@Override
188
			public void onResize(BoxComponent component, int adjWidth, int adjHeight,
189
					int rawWidth, int rawHeight) {
190
				redimensionner(rawWidth);
191
			}
192
		});
193
	}
194
 
195
	public void redimensionner(final int largeur) {
196
		suggestions.setWidth((largeur - label.getOffsetWidth() - 13)+"px");
197
	}
198
 
199
	public void gererTimer() {
200
		if(suggestionTimer == null) {
201
			suggestionTimer = new Timer() {
202
				public void run() {
203
					requeteSuggestions();
204
				}
205
			};
206
			suggestionTimer.schedule(tempsAvantRequete);
207
		} else {
208
			suggestionTimer.schedule(tempsAvantRequete);
209
		}
210
	}
211
 
212
	public void setTempsAvantRequete(int temps) {
213
		tempsAvantRequete = temps;
214
	}
215
 
216
	public int getTempsAvantRequete(int temps) {
217
		return tempsAvantRequete;
218
	}
219
 
2640 aurelien 220
	public void requeteToutesSuggestions() {
221
		// Cette méthode permet de demander l'autocomplétion même si
222
		// la valeur saisie est vide (cas de l'appui sur flèche bas)
223
		envoyerRequeteSuggestions("*");
224
	}
225
 
2602 aurelien 226
	public void requeteSuggestions() {
227
		// Suppression des espaces et caractères inutiles
2603 aurelien 228
		String valeur = suggestions.getValue().trim().isEmpty() ? null : suggestions.getValue().trim();
2602 aurelien 229
 
230
		// ceci permet au composant qui utilise l'autocomplétion
2603 aurelien 231
		// d'annuler une requete et également d'éviter de faire une requête lors du vidage du champ
2607 aurelien 232
		if(valeur == null) {
2602 aurelien 233
			return;
234
		}
2640 aurelien 235
		envoyerRequeteSuggestions(valeur);
236
	}
237
 
238
	private void envoyerRequeteSuggestions(final String valeur) {
2607 aurelien 239
		final String urlRequeteFmt = preTraiterUrlRequete(urlRequete, valeur);
240
		RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, urlRequeteFmt) ;
2602 aurelien 241
		try {
242
			rb.sendRequest(null, new RequestCallback() {
243
				public void onError(final Request request, final Throwable exception) {
244
					// TODO Auto-generated method stub
245
				}
246
 
247
				public void onResponseReceived(final Request request,
248
						final Response response) {
2640 aurelien 249
					surReponseRequete(valeur, response);
2602 aurelien 250
				}
251
			}) ;
252
 
253
		} catch (RequestException e) {
254
			// TODO Auto-generated catch block
255
			e.printStackTrace();
256
		}
257
	}
258
 
259
	public void surReponseRequete(String requete, Response response) {
260
		possibilites = parserResultatRequete(response);
261
		msu.clear();
262
		Iterator<String> it = possibilites.keySet().iterator();
263
	    while (it.hasNext()) {
264
	    	msu.add(possibilites.get(it.next()));
265
	    }
266
 
267
		requeteOracle.setQuery(requete);
2640 aurelien 268
		if(requete.equals("*")) {
269
			// TODO : il y a peut être une méthode plus simple
270
			// mais ceci permet d'afficher les suggestions en cas d'appui
271
			// sur bas lorsque la liste est vide
272
			msu.setDefaultSuggestionsFromText(possibilites.values());
273
			SuggestOracle.Request rq = new SuggestOracle.Request();
274
			rq.setQuery(null);
275
			msu.requestDefaultSuggestions(rq, callBackOracle);
276
		} else {
277
			msu.requestSuggestions(requeteOracle, callBackOracle);
278
		}
2602 aurelien 279
	}
280
 
281
	public String getText() {
282
		return suggestions.getText();
283
	}
284
 
285
	public String getRawValue() {
286
		return suggestions.getText();
287
	}
288
 
289
	public void setValue(String texte) {
290
		suggestions.setText(texte);
291
	}
292
 
293
	public void reset() {
294
		suggestions.setValue("");
295
	}
296
 
297
	public void setTabIndex(int index) {
298
		suggestions.setTabIndex(index);
299
	}
300
 
2603 aurelien 301
	public String getLabelText() {
302
		return label.getText();
303
	}
304
 
305
	public int getFieldWidth() {
306
		return suggestions.getOffsetWidth();
307
	}
308
 
309
	public int getLabelWidth() {
310
		return label.getOffsetWidth();
311
	}
312
 
313
	public void agrandirChamp(int largeur) {
314
		suggestions.setWidth(largeur+"px");
315
	}
316
 
2607 aurelien 317
	protected String preTraiterValeurAvantAffichage(String valeur) {
318
		return valeur;
319
	}
320
	protected String preTraiterUrlRequete(String urlRequete, String valeur) {
321
		return urlRequete+URL.encodeQueryString(valeur);
322
	}
2602 aurelien 323
	protected abstract Map<String, String> parserResultatRequete(Response response);
324
	protected abstract void onModificationValeur();
325
	protected abstract void onSelectionValeur();
326
	protected abstract void onValidationSaisie();
327
}