2014-10-02 13:01:18 +02:00
package org.gcube.portlets.widgets.pickitem.client.dialog ;
import java.util.ArrayList ;
import org.gcube.portlets.widgets.pickitem.client.bundle.CssAndImages ;
2014-10-02 13:06:40 +02:00
import org.gcube.portlets.widgets.pickitem.client.events.PickedItemEvent ;
2014-10-02 15:07:19 +02:00
import org.gcube.portlets.widgets.pickitem.client.uibinder.NoPhotoTemplate ;
2014-10-02 13:01:18 +02:00
import org.gcube.portlets.widgets.pickitem.client.uibinder.SelectableItem ;
import org.gcube.portlets.widgets.pickitem.client.uibinder.WithPhotoTemplate ;
import org.gcube.portlets.widgets.pickitem.shared.ItemBean ;
import com.google.gwt.core.client.GWT ;
import com.google.gwt.event.dom.client.KeyCodes ;
import com.google.gwt.event.dom.client.MouseDownEvent ;
import com.google.gwt.event.dom.client.MouseDownHandler ;
import com.google.gwt.event.dom.client.MouseOutEvent ;
import com.google.gwt.event.dom.client.MouseOutHandler ;
import com.google.gwt.event.dom.client.MouseOverEvent ;
import com.google.gwt.event.dom.client.MouseOverHandler ;
import com.google.gwt.event.shared.HandlerManager ;
import com.google.gwt.user.client.ui.FocusPanel ;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle ;
import com.google.gwt.user.client.ui.PopupPanel ;
import com.google.gwt.user.client.ui.SuggestOracle.Callback ;
import com.google.gwt.user.client.ui.SuggestOracle.Request ;
import com.google.gwt.user.client.ui.SuggestOracle.Response ;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion ;
import com.google.gwt.user.client.ui.VerticalPanel ;
import com.google.gwt.user.client.ui.Widget ;
/ * *
*
* @author Massimiliano Assante , ISTI - CNR
* Use this widget to display a a dropdown user list you can attach to a textbox to make select portal users typing @
*
2014-10-02 13:06:40 +02:00
* To get to know which user was selected listen for the { @link PickedItemEvent } on the { @link HandlerManager } instance you pass to this widget .
2014-10-02 13:01:18 +02:00
*
* /
public class PickItemsDialog extends PopupPanel {
2014-10-02 19:44:49 +02:00
2014-10-02 13:01:18 +02:00
public final static int ARROW_UP = 38 ;
public final static int ARROW_DOWN = 40 ;
public final static int DELETE = KeyCodes . KEY_DELETE ;
public final static int ENTER = KeyCodes . KEY_ENTER ;
public final static int ESCAPE = KeyCodes . KEY_ESCAPE ;
public final static int TAB = KeyCodes . KEY_TAB ;
private HandlerManager eventBus ;
private int limit = 10 ;
private final MultiWordSuggestOracle oracle = new MultiWordSuggestOracle ( ) ;
private int displayIndexSelected ;
private FocusPanel focusPanel = new FocusPanel ( ) ;
private VerticalPanel mainPanel = new VerticalPanel ( ) ;
private String triggerChar ;
private ArrayList < ItemBean > users ;
//needed because is selected when it popups
private Widget first ;
2014-10-02 15:07:19 +02:00
private boolean hasPhoto ;
2014-10-02 13:01:18 +02:00
static {
CssAndImages . INSTANCE . css ( ) . ensureInjected ( ) ;
}
/ * *
* @param triggerChar the ' single char ' used to trigger the items list show , e . g . '@' , '#' . . . .
* @param the list of user to pick
* @param eventBus the event bus on where the widget will fire the selected user event
* @param widthInPixel the desired width ( grater than 199 pixel )
2014-10-02 15:07:19 +02:00
* @param hasPhoto tell of you have want to show photo for the item or not
2014-10-02 13:01:18 +02:00
* /
2014-10-02 15:07:19 +02:00
public PickItemsDialog ( char triggerChar , ArrayList < ItemBean > users , final HandlerManager eventBus , int widthInPixel , boolean hasPhoto ) {
2014-10-02 13:01:18 +02:00
super ( true , false ) ;
if ( widthInPixel < 200 ) {
throw new IllegalArgumentException ( " width must be greater than 199 " ) ;
}
this . eventBus = eventBus ;
this . triggerChar = " " + triggerChar ;
2014-10-02 15:07:19 +02:00
this . hasPhoto = hasPhoto ;
2014-10-02 13:01:18 +02:00
this . users = users ;
focusPanel . setWidth ( widthInPixel + " px " ) ;
mainPanel . setWidth ( widthInPixel + " px " ) ;
setWidth ( widthInPixel + " px " ) ;
focusPanel . add ( mainPanel ) ;
setWidget ( focusPanel ) ;
setStyleName ( " pickDialog " ) ;
//add the user fill names to the oracle
for ( ItemBean user : users ) {
oracle . add ( user . getAlternativeName ( ) ) ;
}
//remove the first selected when hovering
focusPanel . addMouseOverHandler ( new MouseOverHandler ( ) {
@Override
public void onMouseOver ( MouseOverEvent event ) {
if ( first ! = null )
first . removeStyleName ( " pickperson-selected " ) ;
}
} ) ;
focusPanel . addMouseOutHandler ( new MouseOutHandler ( ) {
@Override
public void onMouseOut ( MouseOutEvent event ) {
select ( displayIndexSelected ) ;
}
} ) ;
2014-10-02 19:44:49 +02:00
2014-10-02 18:19:43 +02:00
focusPanel . addMouseDownHandler ( new MouseDownHandler ( ) {
2014-10-02 13:01:18 +02:00
@Override
public void onMouseDown ( MouseDownEvent event ) {
2014-10-02 19:44:49 +02:00
handleMouseDown ( ) ;
2014-10-02 13:01:18 +02:00
}
} ) ;
}
2014-10-02 19:44:49 +02:00
2014-10-02 18:19:43 +02:00
private void handleMouseDown ( ) {
SelectableItem ut = ( SelectableItem ) mainPanel . getWidget ( displayIndexSelected ) ;
eventBus . fireEvent ( new PickedItemEvent ( new ItemBean ( " id " , " username " , ut . getItemName ( ) , " thumb " ) , this . triggerChar ) ) ;
hide ( ) ;
select ( 0 ) ; //RESET
}
2014-10-02 13:01:18 +02:00
/ * *
* called for each keyUp event from the user
* @param keyCode the event keycode
* @param x
* @param y
* @param currText
* /
public void onKeyUp ( int keyCode , int x , int y , String currText ) {
2014-10-02 19:44:49 +02:00
if ( currText . endsWith ( triggerChar ) ) { //the only way i found to intercept the triggerChar
2014-10-02 13:01:18 +02:00
setPopupPosition ( x , y ) ;
hide ( ) ;
2014-10-02 19:44:49 +02:00
}
else {
2014-10-02 23:06:26 +02:00
String last7 = ( currText . length ( ) > 7 ) ? currText . substring ( currText . length ( ) - 7 ) : currText ;
if ( last7 . contains ( triggerChar ) ) {
2014-10-02 19:44:49 +02:00
if ( pickingUser ( currText ) ) {
handleNonCharKeys ( keyCode ) ;
}
2014-10-02 23:06:26 +02:00
} else if ( ! last7 . contains ( triggerChar ) )
2014-10-02 19:44:49 +02:00
hide ( ) ;
}
2014-10-02 13:01:18 +02:00
}
/ * *
* split the text and keeps listening for user keyboard events
* @param currText the text being typed
* /
private boolean pickingUser ( String currText ) {
2014-10-02 19:44:49 +02:00
int tPos = currText . lastIndexOf ( triggerChar ) ;
String toSplit = currText . substring ( tPos ) ;
String [ ] splitted = toSplit . split ( triggerChar ) ; //get the interesting part
if ( splitted [ 1 ] . trim ( ) . length ( ) > 0 ) {
showSuggestions ( splitted [ 1 ] ) ;
2014-10-02 13:01:18 +02:00
return true ;
}
hide ( ) ;
return false ;
}
/ * *
* handles the nonchar events ( arrows , esc , enter etc )
* @param event
* /
private void handleNonCharKeys ( int keyCode ) {
switch ( keyCode ) {
case ARROW_UP :
if ( displayIndexSelected > 0 )
select ( - - displayIndexSelected ) ;
break ;
case ARROW_DOWN :
case TAB :
if ( displayIndexSelected + 1 < mainPanel . getWidgetCount ( ) )
select ( displayIndexSelected + 1 ) ;
break ;
case ESCAPE :
case DELETE :
hide ( ) ;
case ENTER : //selectd with keyboard
SelectableItem ut = null ;
if ( mainPanel . getWidgetCount ( ) > 0 ) {
if ( displayIndexSelected < 0 | | displayIndexSelected > = mainPanel . getWidgetCount ( ) ) //when there's only one left sometimes here i get -sth, no time to see why :)
ut = ( SelectableItem ) mainPanel . getWidget ( 0 ) ;
else
ut = ( SelectableItem ) mainPanel . getWidget ( displayIndexSelected ) ;
2014-10-02 18:19:43 +02:00
eventBus . fireEvent ( new PickedItemEvent ( new ItemBean ( " id " , " username " , ut . getItemName ( ) , " thumb " ) , this . triggerChar ) ) ;
2014-10-02 13:01:18 +02:00
hide ( ) ;
select ( 0 ) ; //RESET
}
break ;
default :
break ;
}
}
public void showSuggestions ( String query ) {
if ( query . length ( ) > 0 ) {
oracle . requestSuggestions ( new Request ( query , limit ) , new Callback ( ) {
public void onSuggestionsReady ( Request request , Response response ) {
mainPanel . clear ( ) ;
int i = 0 ;
for ( Suggestion s : response . getSuggestions ( ) ) {
if ( i = = 0 ) {
2014-10-02 15:07:19 +02:00
first = getUserTemplate ( getUserModelBySuggestion ( s ) , i , hasPhoto ) ;
2014-10-02 13:01:18 +02:00
first . addStyleName ( " pickperson-selected " ) ;
mainPanel . add ( first ) ;
}
else
2014-10-02 15:07:19 +02:00
mainPanel . add ( getUserTemplate ( getUserModelBySuggestion ( s ) , i , hasPhoto ) ) ;
2014-10-02 13:01:18 +02:00
i + + ;
}
if ( i > 0 ) {
show ( ) ;
}
}
} ) ;
}
}
2014-10-02 19:44:49 +02:00
2014-10-02 13:01:18 +02:00
private ItemBean getUserModelBySuggestion ( Suggestion suggestion ) {
for ( ItemBean user : users ) {
if ( suggestion . getReplacementString ( ) . compareTo ( user . getAlternativeName ( ) ) = = 0 )
return user ;
}
return new ItemBean ( " no-match " , " no-match " , " no-match " , " no-match " ) ;
}
2014-10-02 15:07:19 +02:00
private Widget getUserTemplate ( ItemBean user , int displayIndex , boolean hasPhoto ) {
if ( hasPhoto )
2014-10-02 19:44:49 +02:00
return new WithPhotoTemplate ( this , user , displayIndex ) ;
2014-10-02 15:07:19 +02:00
return new NoPhotoTemplate ( this , user , displayIndex ) ;
2014-10-02 13:01:18 +02:00
}
/ * *
* select the user in the model and in the view
* @param displayIndex
* /
public void select ( int displayIndex ) {
for ( int i = 0 ; i < mainPanel . getWidgetCount ( ) ; i + + ) {
Widget ut = ( Widget ) mainPanel . getWidget ( i ) ;
if ( i = = displayIndex ) {
ut . addStyleName ( " pickperson-selected " ) ;
displayIndexSelected = i ;
}
else
ut . removeStyleName ( " pickperson-selected " ) ;
}
}
}