/*******************************************************************************
* 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 com.eclipsesource.tabris.internal.ui;
import static com.eclipsesource.tabris.internal.Constants.PROPERTY_CONTROL;
import static com.eclipsesource.tabris.internal.Constants.PROPERTY_IMAGE;
import static com.eclipsesource.tabris.internal.Constants.PROPERTY_PARENT;
import static com.eclipsesource.tabris.internal.Constants.PROPERTY_STYLE;
import static com.eclipsesource.tabris.internal.Constants.PROPERTY_TITLE;
import static com.eclipsesource.tabris.internal.Constants.PROPERTY_TOP_LEVEL;
import static com.eclipsesource.tabris.internal.JsonUtil.createJsonArray;
import java.io.ByteArrayInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.rap.json.JsonArray;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.lifecycle.WidgetUtil;
import org.eclipse.rap.rwt.remote.RemoteObject;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.graphics.ImageFactory;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import com.eclipsesource.tabris.internal.ui.rendering.ActionRenderer;
import com.eclipsesource.tabris.internal.ui.rendering.PageRenderer;
import com.eclipsesource.tabris.internal.ui.rendering.RendererFactory;
import com.eclipsesource.tabris.ui.Page;
import com.eclipsesource.tabris.ui.PageData;
import com.eclipsesource.tabris.ui.PageStyle;
import com.eclipsesource.tabris.ui.UI;
@SuppressWarnings("restriction")
public class RemotePage implements Serializable, PageRenderer {
private final RemoteObject remoteObject;
private final List<ActionRenderer> remoteActions;
private final UI ui;
private final RemoteUI uiRenderer;
private final PageData data;
private final Page page;
private PageDescriptor descriptor;
private Control control;
public RemotePage( UI ui, RemoteUI uiRenderer, PageDescriptor descriptor, PageData data ) {
this.ui = ui;
this.uiRenderer = uiRenderer;
this.data = data;
this.remoteObject = RWT.getUISession().getConnection().createRemoteObject( "tabris.Page" );
this.descriptor = descriptor;
this.page = InstanceCreator.createInstance( descriptor.getPageType() );
this.remoteActions = new ArrayList<ActionRenderer>();
setTitle( descriptor.getTitle() );
setAttributes();
}
String getId() {
return remoteObject.getId();
}
private void setAttributes() {
remoteObject.set( PROPERTY_PARENT, uiRenderer.getRemoteUIId() );
remoteObject.set( PROPERTY_TOP_LEVEL, descriptor.isTopLevel() );
if( descriptor.getPageStyle() != null && descriptor.getPageStyle().length > 0 ) {
remoteObject.set( PROPERTY_STYLE, createPageStyleParameter( descriptor.getPageStyle() ) );
}
setImage();
}
private JsonArray createPageStyleParameter( PageStyle[] pageStyle ) {
List<String> parameters = new ArrayList<String>();
for( PageStyle style : pageStyle ) {
parameters.add( style.toString() );
}
String[] result = new String[ parameters.size() ];
parameters.toArray( result );
return createJsonArray( result );
}
private void setImage() {
Image image = createImage( descriptor.getImage() );
if( image != null ) {
Rectangle bounds = image.getBounds();
JsonArray imageData = new JsonArray();
imageData.add( ImageFactory.getImagePath( image ) );
imageData.add( bounds.width );
imageData.add( bounds.height );
remoteObject.set( PROPERTY_IMAGE, imageData );
}
}
private Image createImage( byte[] bytes ) {
if( bytes != null ) {
return new Image( ui.getDisplay(), new ByteArrayInputStream( bytes ) );
}
return null;
}
@Override
public void update( PageDescriptor descriptor, RendererFactory rendererFactory, Composite uiParent ) {
this.descriptor = descriptor;
createActions( rendererFactory, uiParent );
removeOldActions();
}
private void removeOldActions() {
for( ActionRenderer renderer : new ArrayList<ActionRenderer>( remoteActions ) ) {
if( !existInPage( renderer ) ) {
renderer.destroy();
remoteActions.remove( renderer );
}
}
}
private boolean existInPage( ActionRenderer renderer ) {
List<ActionDescriptor> actions = descriptor.getActions();
for( ActionDescriptor actionDescriptor : actions ) {
if( actionDescriptor.getId().equals( renderer.getDescriptor().getId() ) ) {
return true;
}
}
return false;
}
@Override
public void createActions( RendererFactory rendererFactory, Composite uiParent ) {
List<ActionDescriptor> actions = descriptor.getActions();
for( ActionDescriptor actionDescriptor : actions ) {
if( !actionExist( actionDescriptor ) ) {
createAction( rendererFactory, uiParent, actionDescriptor );
}
}
}
private boolean actionExist( ActionDescriptor newAction ) {
for( ActionRenderer renderer : remoteActions ) {
if( renderer.getDescriptor().getId().equals( newAction.getId() ) ) {
return true;
}
}
return false;
}
private void createAction( RendererFactory rendererFactory, Composite uiParent, ActionDescriptor actionDescriptor ) {
ActionRenderer renderer = rendererFactory.createActionRenderer( ui, uiRenderer, actionDescriptor );
remoteActions.add( renderer );
renderer.createUi( uiParent );
}
@Override
public void setTitle( String title ) {
remoteObject.set( PROPERTY_TITLE, title );
}
@Override
public List<ActionRenderer> getActionRenderers() {
return remoteActions;
}
@Override
public PageDescriptor getDescriptor() {
return descriptor;
}
@Override
public Page getPage() {
return page;
}
@Override
public void createControl( Composite parent ) {
if( control == null ) {
Composite container = new Composite( parent, SWT.NONE );
container.setLayout( new FillLayout() );
page.createContent( container, ui );
control = container;
remoteObject.set( PROPERTY_CONTROL, WidgetUtil.getId( control ) );
}
}
@Override
public Control getControl() {
return control;
}
@Override
public PageData getData() {
return data;
}
@Override
public void destroy() {
page.destroy();
control.dispose();
remoteObject.destroy();
}
@Override
public void destroyActions() {
for( ActionRenderer action : remoteActions ) {
action.destroy();
}
remoteActions.clear();
}
}