/******************************************************************************* * Copyright (c) 2014, 2016 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 com.eclipsesource.tabris.widgets; import static com.eclipsesource.tabris.internal.Clauses.whenNull; import static com.eclipsesource.tabris.internal.Constants.PROPERTY_PARENT; import static com.eclipsesource.tabris.internal.Constants.TYPE_REFRESH_COMPOSITE; import static com.eclipsesource.tabris.internal.DataWhitelist.WhiteListEntry.REFRESH_COMPOSITE; import static org.eclipse.rap.rwt.widgets.WidgetUtil.getId; import java.util.ArrayList; import java.util.List; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.remote.Connection; import org.eclipse.rap.rwt.remote.RemoteObject; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Tree; import com.eclipsesource.tabris.internal.RefreshCompositeOperationHandler; import com.eclipsesource.tabris.internal.RefreshCompositeRemoteAdapter; import com.eclipsesource.tabris.widgets.enhancement.RefreshHandler; /** * <p> * A {@link RefreshComposite} works like an ordinary {@link Composite} with the exception that it adds native refresh * behavior. This means the client uses native facilities to allow the user to refresh some visible area e.g. by * pulling down the area. * </p> * <p> * Refreshing is an asynchronous operation and is mostly done in the background. For this reason it's your * responsibility to call a refresh done by calling the method {@link RefreshComposite#done()}. This will instruct the * client to hide the refresh UI. * </p> * <p> * <b>Please Note:</b> Because {@link Tree}s are a special component on mobile devices it's recommended to use a * {@link RefreshHandler} on a {@link Tree} instead of embedding it into a {@link RefreshComposite}. * </p> * * @see RefreshHandler * * @since 1.4 */ public class RefreshComposite extends Composite { private final List<RefreshListener> listeners; private String message; private final RemoteObject remoteObject; private final RefreshCompositeRemoteAdapter remoteAdapter; public RefreshComposite( Composite parent, int style ) { super( parent, style ); this.listeners = new ArrayList<RefreshListener>(); Connection connection = RWT.getUISession().getConnection(); remoteObject = connection.createRemoteObject( TYPE_REFRESH_COMPOSITE ); remoteObject.setHandler( new RefreshCompositeOperationHandler( this ) ); remoteObject.set( PROPERTY_PARENT, getId( this ) ); remoteAdapter = new RefreshCompositeRemoteAdapter( this, remoteObject ); setData( REFRESH_COMPOSITE.getKey(), Boolean.TRUE ); } /** * <p> * Sets the message the client should show during a refresh. * </p> * * @param message the message to show. Must not be <code>null</code>. */ public void setMessage( String message ) { whenNull( message ).throwIllegalArgument( "Message must not be null" ); if( !message.equals( this.message ) ) { remoteAdapter.preserveMessage( this.message ); this.message = message; } } public String getMessage() { return message; } /** * <p> * Adds a {@link RefreshListener} that will be notified when the user has triggered a refresh. After the refresh * is done you need to call {@link RefreshComposite#done()} to hide the refresh UI on the client. * </p> * * @param listener the listener to add. Must not be <code>null</code>. */ public void addRefreshListener( RefreshListener listener ) { whenNull( listener ).throwIllegalArgument( "RefreshListener must not be null" ); remoteAdapter.preserveRefreshListener( hasRefreshListener() ); listeners.add( listener ); } /** * <p> * Removes a {@link RefreshListener}. * </p> * * @param listener the listener to remove. Must not be <code>null</code>. */ public void removeRefreshListener( RefreshListener listener ) { whenNull( listener ).throwIllegalArgument( "RefreshListener must not be null" ); remoteAdapter.preserveRefreshListener( hasRefreshListener() ); listeners.remove( listener ); } /** * <p> * Returns the added {@link RefreshListener}s * </p> */ public List<RefreshListener> getRefreshListeners() { return new ArrayList<RefreshListener>( listeners ); } /** * <p> * Instructs a client to hide it's refresh UI. Usually this method will be called within a * {@link RefreshListener#refresh()} method after the refreshing is done. * </p> */ public void done() { remoteAdapter.setDone( true ); } private boolean hasRefreshListener() { return !listeners.isEmpty(); } @Override public void dispose() { if( !isDisposed() ) { remoteObject.destroy(); } super.dispose(); } }