New file |
0,0 → 1,327 |
package org.tela_botanica.client.util.autocompletion; |
|
import java.util.ArrayList; |
import java.util.Iterator; |
import java.util.List; |
import java.util.Map; |
|
import org.tela_botanica.client.cel2; |
import org.tela_botanica.client.modeles.objets.Utilisateur; |
|
import com.google.gwt.core.client.Callback; |
import com.google.gwt.core.client.JavaScriptObject; |
import com.google.gwt.event.dom.client.KeyCodes; |
import com.google.gwt.event.dom.client.KeyDownEvent; |
import com.google.gwt.event.dom.client.KeyDownHandler; |
import com.google.gwt.event.dom.client.KeyPressEvent; |
import com.google.gwt.event.dom.client.KeyPressHandler; |
import com.google.gwt.event.logical.shared.SelectionEvent; |
import com.google.gwt.event.logical.shared.SelectionHandler; |
import com.google.gwt.event.logical.shared.ValueChangeEvent; |
import com.google.gwt.event.logical.shared.ValueChangeHandler; |
import com.google.gwt.http.client.Request; |
import com.google.gwt.http.client.RequestBuilder; |
import com.google.gwt.http.client.RequestCallback; |
import com.google.gwt.http.client.RequestException; |
import com.google.gwt.http.client.Response; |
import com.google.gwt.http.client.URL; |
import com.google.gwt.user.client.Event; |
import com.google.gwt.user.client.Timer; |
import com.google.gwt.user.client.Window; |
import com.google.gwt.user.client.ui.ChangeListener; |
import com.google.gwt.user.client.ui.Label; |
import com.google.gwt.user.client.ui.MultiWordSuggestOracle; |
import com.google.gwt.user.client.ui.SuggestBox; |
import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay; |
import com.google.gwt.user.client.ui.TextBox; |
import com.google.gwt.user.client.ui.SuggestBox.SuggestionDisplay; |
import com.google.gwt.user.client.ui.SuggestOracle; |
import com.google.gwt.user.client.ui.Widget; |
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion; |
import com.gwtext.client.widgets.BoxComponent; |
import com.gwtext.client.widgets.Component; |
import com.gwtext.client.widgets.Container; |
import com.gwtext.client.widgets.Panel; |
import com.gwtext.client.widgets.event.PanelListener; |
import com.gwtext.client.widgets.event.PanelListenerAdapter; |
import com.gwtext.client.widgets.layout.FitLayout; |
|
@SuppressWarnings("unchecked") |
public abstract class AutoCompletionComboBox extends Panel { |
|
Label label = null; |
MultiWordSuggestOracle msu = null; |
SuggestBox suggestions = null; |
DefaultSuggestionDisplay sgd = null; |
|
Callback<String, String> surCopierColler = null; |
|
SuggestOracle.Request requeteOracle; |
SuggestOracle.Callback callBackOracle; |
|
Timer suggestionTimer = null; |
int tempsAvantRequete = 500; |
|
Map<String, String> possibilites = null; |
|
String urlRequete = ""; |
|
public AutoCompletionComboBox(String nomLabel, String urlRequete) { |
|
this.setStyleName("champAutoComplete"); |
|
this.label = new Label(nomLabel+":"); |
this.urlRequete = urlRequete; |
|
sgd = new SuggestBox.DefaultSuggestionDisplay(); |
msu = new MultiWordSuggestOracle() { |
@Override |
public void requestSuggestions(Request request, Callback callback) { |
List<MultiWordSuggestion> retenus = new ArrayList<MultiWordSuggestion>(); |
Iterator<String> it = possibilites.keySet().iterator(); |
while (it.hasNext()) { |
String cle = it.next(); |
String cleAffichee = preTraiterValeurAvantAffichage(possibilites.get(cle)); |
MultiWordSuggestion muWoSug = new MultiWordSuggestion(possibilites.get(cle), cleAffichee); |
retenus.add(muWoSug); |
} |
|
Response reponse = new Response(retenus); |
callback.onSuggestionsReady(request, reponse); |
} |
}; |
|
suggestions = new SuggestBox(msu, new TextBox(), sgd) { |
public void onBrowserEvent(Event event) { |
switch (event.getTypeInt()) { |
case Event.ONPASTE: { |
if(surCopierColler != null) { |
surCopierColler.onSuccess(suggestions.getValueBox().getValue()); |
} |
} |
break; |
default: |
super.onBrowserEvent(event); |
} |
|
} |
}; |
|
suggestions.setAutoSelectEnabled(false); |
setLayout(new FitLayout()); |
add(label); |
add(suggestions); |
gererEvenements(); |
} |
|
public void gererEvenements() { |
suggestions.addKeyDownHandler(new KeyDownHandler() { |
|
@Override |
public void onKeyDown(KeyDownEvent event) { |
// Lorsque la liste de suggestions est ouverte, une frappe sur entrée selectionne la valeur |
// Si elle est fermée, elle déclenche la fonction abstraite de validation (utile pour les champs |
// du genre station, milieu etc... et la saisie d'obs rapide |
if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { |
if((sgd == null || !sgd.isSuggestionListShowing())) { |
onValidationSaisie(); |
event.stopPropagation(); |
return; |
} else { |
// Dans les autres cas, un appui sur entrée ne doit pas redéclencher l'autcomplétion |
return; |
} |
} |
|
if(event.getNativeKeyCode() == KeyCodes.KEY_DOWN) { |
// Un appui sur flèche bas permet de demander toute la liste |
if(!sgd.isSuggestionListShowing()) { |
requeteToutesSuggestions(); |
} |
} |
|
// Tout autre frappe d'un caractère "normal" déclenche le timer d'autocomplétion |
if(!KeyDownEvent.isArrow(event.getNativeKeyCode())) { |
gererTimer(); |
} |
} |
|
}); |
|
requeteOracle = new SuggestOracle.Request(); |
callBackOracle = new SuggestOracle.Callback() { |
|
public void onSuggestionsReady(SuggestOracle.Request request, SuggestOracle.Response response) { |
suggestions.showSuggestionList(); |
} |
}; |
|
suggestions.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>(){ |
@Override |
public void onSelection(SelectionEvent<Suggestion> event) { |
onSelectionValeur(); |
} |
}); |
|
suggestions.addValueChangeHandler(new ValueChangeHandler<String>() { |
@Override |
public void onValueChange(ValueChangeEvent<String> event) { |
onModificationValeur(); |
} |
}); |
|
surCopierColler = new Callback<String, String>() { |
@Override |
public void onSuccess(String result) { |
gererTimer(); |
} |
|
@Override |
public void onFailure(String reason) { |
// rien à faire ça n'échoue jamais |
} |
}; |
|
addListener(new PanelListenerAdapter() { |
|
@Override |
public void onResize(BoxComponent component, int adjWidth, int adjHeight, |
int rawWidth, int rawHeight) { |
redimensionner(rawWidth); |
} |
}); |
} |
|
public void redimensionner(final int largeur) { |
suggestions.setWidth((largeur - label.getOffsetWidth() - 13)+"px"); |
} |
|
public void gererTimer() { |
if(suggestionTimer == null) { |
suggestionTimer = new Timer() { |
public void run() { |
requeteSuggestions(); |
} |
}; |
suggestionTimer.schedule(tempsAvantRequete); |
} else { |
suggestionTimer.schedule(tempsAvantRequete); |
} |
} |
|
public void setTempsAvantRequete(int temps) { |
tempsAvantRequete = temps; |
} |
|
public int getTempsAvantRequete(int temps) { |
return tempsAvantRequete; |
} |
|
public void requeteToutesSuggestions() { |
// Cette méthode permet de demander l'autocomplétion même si |
// la valeur saisie est vide (cas de l'appui sur flèche bas) |
envoyerRequeteSuggestions("*"); |
} |
|
public void requeteSuggestions() { |
// Suppression des espaces et caractères inutiles |
String valeur = suggestions.getValue().trim().isEmpty() ? null : suggestions.getValue().trim(); |
|
// ceci permet au composant qui utilise l'autocomplétion |
// d'annuler une requete et également d'éviter de faire une requête lors du vidage du champ |
if(valeur == null) { |
return; |
} |
envoyerRequeteSuggestions(valeur); |
} |
|
private void envoyerRequeteSuggestions(final String valeur) { |
final String urlRequeteFmt = preTraiterUrlRequete(urlRequete, valeur); |
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, urlRequeteFmt) ; |
try { |
rb.sendRequest(null, new RequestCallback() { |
public void onError(final Request request, final Throwable exception) { |
// TODO Auto-generated method stub |
} |
|
public void onResponseReceived(final Request request, |
final Response response) { |
surReponseRequete(valeur, response); |
} |
}) ; |
|
} catch (RequestException e) { |
// TODO Auto-generated catch block |
e.printStackTrace(); |
} |
} |
|
public void surReponseRequete(String requete, Response response) { |
possibilites = parserResultatRequete(response); |
msu.clear(); |
Iterator<String> it = possibilites.keySet().iterator(); |
while (it.hasNext()) { |
msu.add(possibilites.get(it.next())); |
} |
|
requeteOracle.setQuery(requete); |
if(requete.equals("*")) { |
// TODO : il y a peut être une méthode plus simple |
// mais ceci permet d'afficher les suggestions en cas d'appui |
// sur bas lorsque la liste est vide |
msu.setDefaultSuggestionsFromText(possibilites.values()); |
SuggestOracle.Request rq = new SuggestOracle.Request(); |
rq.setQuery(null); |
msu.requestDefaultSuggestions(rq, callBackOracle); |
} else { |
msu.requestSuggestions(requeteOracle, callBackOracle); |
} |
} |
|
public String getText() { |
return suggestions.getText(); |
} |
|
public String getRawValue() { |
return suggestions.getText(); |
} |
|
public void setValue(String texte) { |
suggestions.setText(texte); |
} |
|
public void reset() { |
suggestions.setValue(""); |
} |
|
public void setTabIndex(int index) { |
suggestions.setTabIndex(index); |
} |
|
public String getLabelText() { |
return label.getText(); |
} |
|
public int getFieldWidth() { |
return suggestions.getOffsetWidth(); |
} |
|
public int getLabelWidth() { |
return label.getOffsetWidth(); |
} |
|
public void agrandirChamp(int largeur) { |
suggestions.setWidth(largeur+"px"); |
} |
|
protected String preTraiterValeurAvantAffichage(String valeur) { |
return valeur; |
} |
protected String preTraiterUrlRequete(String urlRequete, String valeur) { |
return urlRequete+URL.encodeQueryString(valeur); |
} |
protected abstract Map<String, String> parserResultatRequete(Response response); |
protected abstract void onModificationValeur(); |
protected abstract void onSelectionValeur(); |
protected abstract void onValidationSaisie(); |
} |