blob: 60c2f20230c1bc98a68135ddb1e42143b325e2c5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package org.eclipse.rap.addons.autosuggest;
import static org.eclipse.rap.rwt.lifecycle.WidgetUtil.getId;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.rap.addons.autosuggest.internal.ClientModelListener;
import org.eclipse.rap.addons.autosuggest.internal.Model;
import org.eclipse.rap.addons.autosuggest.internal.ModelListener;
import org.eclipse.rap.addons.autosuggest.internal.resources.AutoSuggestScript;
import org.eclipse.rap.addons.autosuggest.internal.resources.EventDelegatorScript;
import org.eclipse.rap.addons.dropdown.DropDown;
import org.eclipse.rap.clientscripting.ClientListener;
import org.eclipse.rap.clientscripting.Script;
import org.eclipse.rap.clientscripting.WidgetDataWhiteList;
import org.eclipse.rap.json.JsonObject;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
public class AutoSuggest {
private static final String EVENT_TYPE_SELECTION = "suggestionSelected";
private static final String MODEL_ID_KEY
= "org.eclipse.rap.addons.autosuggest#Model";
private final Text text;
private final DropDown dropDown;
private final Model model;
private final List<SuggestionSelectedListener> selectionListeners;
private final ModelListener modelListener;
private ClientListener textClientListener;
private int[] textClientListenerTypes;
private boolean isDisposed;
public AutoSuggest( Text text ) {
if( text == null ) {
throw new NullPointerException( "Text must not be null" );
}
if( text.isDisposed() ) {
throw new IllegalArgumentException( "Text must not be disposed" );
}
this.text = text;
dropDown = new DropDown( text );
model = new Model();
selectionListeners = new ArrayList<SuggestionSelectedListener>( 1 );
modelListener = new ModelListener() {
public void handleEvent( JsonObject argument ) {
notifySelectionListeners();
}
};
connectClientObjects();
attachClientListeners();
text.addListener( SWT.Dispose, new Listener() {
public void handleEvent( Event event ) {
dispose();
}
} );
}
public void setDataSource( DataSource dataSource ) {
checkDisposed();
model.set( "dataSourceId", dataSource != null ? dataSource.getId() : null );
if( dataSource != null ) {
ColumnTemplate template = dataSource.getTemplate();
if( template != null ) {
dropDown.setData( "columns", template.getColumnWidths() );
}
}
}
public void setVisibleItemCount( int itemCount ) {
checkDisposed();
dropDown.setVisibleItemCount( itemCount );
}
public int getVisibleItemCount() {
checkDisposed();
return dropDown.getVisibleItemCount();
}
public void setAutoComplete( boolean value ) {
checkDisposed();
model.set( "autoComplete", value );
}
public void addSelectionListener( SuggestionSelectedListener listener ) {
checkDisposed();
if( listener == null ) {
throw new NullPointerException( "Parameter was null: listener" );
}
if( !selectionListeners.contains( listener ) ) {
selectionListeners.add( listener );
}
if( selectionListeners.size() == 1 ) {
model.addListener( EVENT_TYPE_SELECTION, modelListener );
}
}
public void removeSelectionListener( SuggestionSelectedListener listener ) {
checkDisposed();
if( listener == null ) {
throw new NullPointerException( "Parameter was null: listener" );
}
selectionListeners.remove( listener );
if( selectionListeners.isEmpty() ) {
model.removeListener( EVENT_TYPE_SELECTION, modelListener );
}
}
public void dispose() {
isDisposed = true;
dropDown.dispose();
model.dispose();
removeTextClientListeners();
}
public boolean isDisposed() {
return isDisposed;
}
DropDown getDropDown() {
return dropDown;
}
void notifySelectionListeners() {
for( SuggestionSelectedListener listener : selectionListeners ) {
listener.suggestionSelected();
}
}
private void checkDisposed() {
if( isDisposed ) {
throw new IllegalStateException( "AutoSuggest is disposed" );
}
}
protected void attachClientListeners() {
int[] dropDownEventTypes = new int[] { SWT.Show, SWT.Hide, SWT.Selection, SWT.DefaultSelection };
attachClientListenerToDropDown( EventDelegatorScript.getInstance(), dropDownEventTypes );
attachClientListenerToText( EventDelegatorScript.getInstance(), SWT.Modify, SWT.Verify );
attachClientListenerToModel( AutoSuggestScript.getInstance(), "change", "accept" );
}
protected void attachClientListenerToText( Script script, int... types ) {
if( textClientListener != null ) {
throw new IllegalStateException( "AutoSuggest: Can not add listener to Text twice." );
}
textClientListenerTypes = types;
textClientListener = new ClientListener( script );
for( int type : types ) {
text.addListener( type, textClientListener );
}
}
protected void attachClientListenerToDropDown( Script script, int... types ) {
ClientListener clientListener = new ClientListener( script );
for( int type : types ) {
dropDown.addListener( type, clientListener );
}
}
protected void attachClientListenerToModel( Script script, String... types ) {
ClientModelListener clientModelListener = new ClientModelListener( script );
for( String type : types ) {
model.addListener( type, clientModelListener );
}
model.set( "autoSuggestListenerId", clientModelListener.getId() );
}
private void connectClientObjects() {
WidgetDataWhiteList.addKey( MODEL_ID_KEY );
model.set( "textWidgetId", getId( text ) );
model.set( "dropDownWidgetId", getId( dropDown ) );
dropDown.setData( MODEL_ID_KEY, model.getId() );
text.setData( MODEL_ID_KEY, model.getId() );
}
private void removeTextClientListeners() {
for( int type : textClientListenerTypes ) {
text.removeListener( type, textClientListener );
}
}
}