Subversion Repositories eFlore/Archives.cel-v1

Rev

Rev 25 | Rev 27 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
Auto-Completion Textbox for GWT
Copyright (C) 2006 Oliver Albers http://gwt.components.googlepages.com/

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

*/
package org.tela_botanica.client;


// TODO : traiter latence (augmenter en fonction rapidité saisie + texte vide)
// TODO : traitement espace apres l'espece (%20)

import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.HTTPRequest;
import com.google.gwt.user.client.ResponseTextHandler;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event; 

import java.util.Vector;
import java.util.HashMap;



public class AutoCompleteAsyncTextBox extends TextBox
    implements KeyboardListener, SourcesAutoCompleteAsyncTextBoxEvents {
   
  private String searchUrl = null; 
  private AutoCompleteAsyncTextBoxListenerCollection autoCompleteAsyncTextBoxListeners=null;  
    
  private HashMap cache = new HashMap();
  private boolean searching = false;
  private ResponseTextHandler responseTextHandler=null;
                  
  protected PopupPanel choicesPopup = new PopupPanel(true);
  protected ListBox choices = new ListBox() {
          public void onBrowserEvent(Event event) {
                  if (Event.ONCLICK == DOM.eventGetType(event)) {
                          complete();
                  }
          } 
  };
  protected Vector items = new Vector(); 
  protected boolean popupAdded = false;
  protected boolean visible = false;
  
  /**
   * Value linked to current text
   */
  protected String currentValue = null;
  
   
   
  /**
   * Default Constructor
   *
   */
  public AutoCompleteAsyncTextBox(ResponseTextHandler rsp)
  {
    super();
    responseTextHandler=rsp;
    this.addKeyboardListener(this);
    choices.sinkEvents(Event.ONCLICK); 
    this.setStyleName("AutoCompleteAsyncTextBox");
       
    choicesPopup.add(choices);
    choicesPopup.addStyleName("AutoCompleteChoices");
       
    choices.setStyleName("list");
    
  }

 
  
  public void addAutoCompleteAsyncTextBoxListener(AutoCompleteAsyncTextBoxListener listener) {
            if (autoCompleteAsyncTextBoxListeners == null) {
              autoCompleteAsyncTextBoxListeners = new AutoCompleteAsyncTextBoxListenerCollection();
            }
            autoCompleteAsyncTextBoxListeners.addElement(listener);
  }


 
  public void setSearchUrl(String url) {
          
          this.searchUrl=url;
  }
  
  private void doFetchURL(String match) {
          /*
           * Here we fetch the URL and call the handler
           */     
        

          String rematch=match.replaceAll(" ","/");
          rematch=rematch.replaceAll("%","");
          
          if (this.searchUrl!=null && searching==false) {
                  searching=true;
         //     HTTPRequest.asyncGet(URL.encodeComponent(this.searchUrl) + rematch, responseTextHandler );
              HTTPRequest.asyncGet(this.searchUrl + rematch, responseTextHandler );

          }
  }

  
  public void onKeyDown(Widget arg0, char arg1, int arg2) {
          
          
          if(arg1 == KEY_ENTER)
            {
              enterKey(arg0, arg1, arg2);
            }
            else if(arg1 == KEY_DOWN)
            {
              downKey(arg0, arg1, arg2);
            }
            else if(arg1 == KEY_UP)
            {
              upKey(arg0, arg1, arg2);
            }
            else if(arg1 == KEY_ESCAPE)
            {
              escapeKey(arg0, arg1, arg2);
            }
                
          
  }      
  /**
   * Not used at all (probleme avec ie, qui ne comprend pas les touches meta)
   */
  public void onKeyPress(Widget arg0, char arg1, int arg2) {
        

  }
  
  // The down key was pressed.
  protected void downKey(Widget arg0, char arg1, int arg2) {
          
            int selectedIndex = choices.getSelectedIndex();
            selectedIndex++;
            if (selectedIndex >= choices.getItemCount())
            {
              selectedIndex = 0;
            }
            choices.setSelectedIndex(selectedIndex);
 }

  // The up key was pressed.
  protected void upKey(Widget arg0, char arg1, int arg2) {
    int selectedIndex = choices.getSelectedIndex();
    selectedIndex--;
    if(selectedIndex < 0)
    {
      selectedIndex = choices.getItemCount() - 1;
    }
    choices.setSelectedIndex(selectedIndex);
  } 

  // The enter key was pressed.
  protected void enterKey(Widget arg0, char arg1, int arg2) {
      if(visible)
      {
        complete();
      }
      else {
         // Validation de l'entree : appel asynchrone  
          if (autoCompleteAsyncTextBoxListeners!= null) {
              autoCompleteAsyncTextBoxListeners.fireTextBoxEnter(this,this.getText(),currentValue);
          }
          currentValue=null;
          this.setText("");
      }

  }

//The escape key was pressed.
  protected void escapeKey(Widget arg0, char arg1, int arg2) {
    choices.clear();
    items.clear();
    choicesPopup.hide();
    visible = false;

  } 


  // Any other non-special key was pressed.
  protected void otherKey(Widget arg0, char arg1, int arg2) {
   
        
    // Lancement appel 
    String text = this.getText();
    
        
            if(text.length() > 0)
            {
            
                      items.clear();
                      
                      if (getFromCache(text)!=null) {
                          items=getFromCache(text);
                          displayList();
                      }
                      else {
                     
                          this.doFetchURL(text);
                      }
                 }
   
        
            
    
  } 
  
  public void onKeyUp(Widget arg0, char arg1, int arg2) {
          
          switch(arg1) {
      case KEY_ALT:
      case KEY_CTRL:
      case KEY_DOWN:
      case KEY_END:
      case KEY_ENTER:
      case KEY_ESCAPE:
      case KEY_HOME:
      case KEY_LEFT:
      case KEY_PAGEDOWN:
      case KEY_PAGEUP:
      case KEY_RIGHT:
      case KEY_SHIFT:
      case KEY_TAB:
      case KEY_UP:
        break;
      default:
        otherKey(arg0, arg1, arg2);
        break;
    }

  }
    
  
  // Display assistant
  
    public void displayList() { 
        
        searching=false;
            if(this.items.size() > 0)
            {
                
              addToCache(this.getText(),(Vector) items.clone());
              
              choices.clear();
                   
              for(int i = 0; i < items.size(); i++)
              {
                choices.addItem(((String [])items.get(i))[0],((String [])items.get(i))[1]);
              }
              
                   
              // if there is only one match and it is what is in the
              // text field anyways there is no need to show autocompletion
            //  if(items.size() == 1 && (((String []) items.get(0))[0]).compareTo(this.getText()) == 0)
             // {
               // choicesPopup.hide();
             // } else {
                choices.setSelectedIndex(0);
                choices.setVisibleItemCount(items.size());
                       
                if(!popupAdded)
                {
                  RootPanel.get().add(choicesPopup);
                  popupAdded = true;
                }
                choicesPopup.show();
                visible = true;
                choicesPopup.setPopupPosition(this.getAbsoluteLeft(),
                this.getAbsoluteTop() + this.getOffsetHeight());
                choicesPopup.setWidth(this.getOffsetWidth() + "px");
                choices.setWidth(this.getOffsetWidth() + "px");
            //  }
        
            } else {
              visible = false;
              choicesPopup.hide();
            }
          }

  /**
   * A mouseclick in the list of items
   */
  public void onChange(Widget arg0) {
    complete();
  }
  
 
  public void onClick(Widget arg0) {
    complete();
  }
   
  // add selected item to textbox
  protected void complete()
  {
          
    
    if(choices.getItemCount() > 0)
    {
      this.setText(choices.getItemText(choices.getSelectedIndex()));
      currentValue=choices.getValue(choices.getSelectedIndex());
      if (autoCompleteAsyncTextBoxListeners!= null) {
          autoCompleteAsyncTextBoxListeners.fireTextBoxComplete(responseTextHandler,this.getText(),currentValue);
      }
    }

    visible=false;
    items.clear();
    choices.clear();
    choicesPopup.hide();
  }
  
  
  public void addItem(String item, String value) {
          items.add(new String [] {item, value});
  }
  
  private void addToCache (String query, Vector result)
  {
        cache.put(query.toLowerCase(),result);
  }

  private Vector getFromCache (String query)
  {
        return (Vector) cache.get(query.toLowerCase());
  }



public String getValue() {
        return currentValue;
}
  

public  void setValue(String value) {
         this.currentValue=value;
}
  
  
}