Package org.locationtech.udig.project.internal.render.impl

Source Code of org.locationtech.udig.project.internal.render.impl.CompositeRendererImpl

/**
* <copyright></copyright> $Id$
*/
package org.locationtech.udig.project.internal.render.impl;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArraySet;

import org.locationtech.udig.project.IMap;
import org.locationtech.udig.project.ProjectBlackboardConstants;
import org.locationtech.udig.project.internal.ProjectPlugin;
import org.locationtech.udig.project.internal.render.CompositeRenderContext;
import org.locationtech.udig.project.internal.render.MultiLayerRenderer;
import org.locationtech.udig.project.internal.render.RenderContext;
import org.locationtech.udig.project.internal.render.RenderExecutor;
import org.locationtech.udig.project.internal.render.RenderFactory;
import org.locationtech.udig.project.internal.render.RenderListenerAdapter;
import org.locationtech.udig.project.internal.render.RenderManager;
import org.locationtech.udig.project.internal.render.Renderer;
import org.locationtech.udig.project.internal.render.RendererCreator;
import org.locationtech.udig.project.internal.render.SelectionLayer;
import org.locationtech.udig.project.preferences.PreferenceConstants;
import org.locationtech.udig.project.render.ILabelPainter;
import org.locationtech.udig.project.render.IRenderContext;
import org.locationtech.udig.project.render.RenderException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.swt.graphics.RGB;

/**
* <ul>
* <li>Combines the output from several renderer into a single image.</li>
* <li>Listens to its context (CompositeContext) and creates new RenderExecutors when required.</li>
*
* @author Jesse
* @since 1.0.0
*/
public class CompositeRendererImpl extends RendererImpl implements MultiLayerRenderer {

    private final static Comparator<? super RenderExecutor> comparator = new Comparator<RenderExecutor>(){
       
        public int compare(RenderExecutor e1,RenderExecutor e2){
           
            return e1.getContext().getLayer().compareTo(
                    e2.getContext().getLayer());
           
        }
    };

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public static final String copyright =
          "uDig - User Friendly Desktop Internet GIS client\n"
        + "http://udig.refractions.net\n"
        + "(C) 2004-2012, Refractions Research Inc.\n"
        + "\n\n"
        + "All rights reserved. This program and the accompanying materials\n"
        + "are made available under the terms of the Eclipse Public License v1.0\n"
        + "(http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD\n"
        + "License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).\n";
   
    static final AffineTransform IDENTITY = new AffineTransform();
    CompositeContextListener contextListener = new CompositeContextListener(){
  
      private void add( List<RenderContext> contexts ) {
            List<RenderExecutor> renderers = new ArrayList<RenderExecutor>();
            for( RenderContext context : contexts ) {
                if (findExecutor(context) == null) {
                    Renderer renderer = getRendererCreator(context).getRenderer(context);
                    renderers.add(createRenderExecutor(renderer));
                }
            }
            if (!renderers.isEmpty()) {
                getRenderExecutors().addAll(renderers);
            }
        }

        public void notifyChanged( CompositeRenderContext context, List<RenderContext> contexts, boolean added ) {
            if( added ){
                add(contexts);
            }else{
                remove(contexts);
            }
        }

        private void remove( List<RenderContext> contexts){
        for( RenderContext context : contexts ) {
          RenderExecutor executor = findExecutor(context);
          if(executor != null){
            getRenderExecutors().remove(executor);
            executor.dispose();
          }
        }
      }
    };

    RendererCreator rendererCreator = null;

    private final Set<RenderExecutor> renderExecutors;

    {
        renderExecutors=new CopyOnWriteArraySet<RenderExecutor>();
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    protected CompositeRendererImpl() {
        super();
    }

    /**
     *
     * Returns a list that is a copy of all the children render.
     *
     * @see org.locationtech.udig.project.internal.render.MultiLayerRenderer#children()
     */
    public List<Renderer> children() {
        List<Renderer> children = new ArrayList<Renderer>();
        for( RenderExecutor victim : getRenderExecutors() ) {
            children.add(victim.getRenderer());
        }
        return children;
    }


    /**
     * @param renderer
     */
    protected RenderExecutor createRenderExecutor( Renderer renderer ) {
         final RenderExecutor executor = RenderFactory.eINSTANCE.createRenderExecutor(renderer);
        executor.eAdapters().add(new RenderListenerAdapter(){

            /**
             * @see org.locationtech.udig.project.internal.render.RenderListenerAdapter#renderDisposed(org.eclipse.emf.common.notify.Notification)
             */
            protected void renderDisposed( Notification msg ) {
                EObject obj = (EObject) getTarget();
                obj.eAdapters().remove(this);
            }

            /**
             * @see org.locationtech.udig.project.internal.render.RenderListenerAdapter#renderDone()
             */
            protected void renderDone() {
               setState(DONE);
            }

            protected void renderRequest() {
                setRenderBounds(executor.getRenderBounds());
                setState(RENDER_REQUEST);
            }

            @Override
            protected void renderStarting() {
//                setState(STARTING);
            }

            /**
             * @see org.locationtech.udig.project.internal.render.RenderListenerAdapter#renderUpdate()
             */
            protected void renderUpdate() {
                synchronized (CompositeRendererImpl.this) {
//                    try {
//                        refreshImage();
                        setState(RENDERING);
//                    } catch (RenderException e) {
//                        // TODO Catch e
//                    }
                }
            }
        });
        return executor;
    }

    /**
     * @see org.locationtech.udig.project.internal.render.impl.RendererImpl#dispose()
     */
    public synchronized void dispose() {
        for (RenderExecutor renderer : getRenderExecutors()) {
            renderer.dispose();
        }
        getRenderExecutors().clear();
    }

    /**
     * Called to remove the corresponding RenderExecutor from the list of RenderExecutors.
     *
     * @param renderer the renderer that has been removed
     */
    protected RenderExecutor findExecutor( IRenderContext context ) {
        for( Iterator<RenderExecutor> eIter = getRenderExecutors().iterator(); eIter.hasNext(); ) {
            RenderExecutor executor = (RenderExecutor) eIter.next();
            if (executor.getRenderer().getContext().equals(context))
                return executor;
        }
        return null;
    }
   
    /**
     * @see org.locationtech.udig.project.internal.render.impl.RendererImpl#getContext()
     */
    public CompositeRenderContext getContext() {
        return (CompositeRenderContext) super.getContext();
    }

  /**
     * @see org.locationtech.udig.project.render.IMultiLayerRenderer#getIChildren()
     */
    @SuppressWarnings("unchecked")
  public List getIChildren() {
        return children();
    }

    /**
     * @see org.locationtech.udig.project.render.IMultiLayerRenderer#getIContext()
     */
    public IRenderContext getIContext() {
        return getContext();
    }

//    /**
//     * <!-- begin-user-doc --> <!-- end-user-doc -->
//     *
//     * @throws RenderException
//     * @generated NOT
//     */
//    public synchronized void render( IProgressMonitor monitor ) throws RenderException {
//        if (getRenderExecutors().size() == 0)
//            setState(DONE);
//        for( Iterator iter = getRenderExecutors().iterator(); iter.hasNext(); ) {
//            RenderExecutor executor = (RenderExecutor) iter.next();
//            executor.render((Envelope) null, monitor);
//        }
//    }

    RendererCreator getRendererCreator( IRenderContext context ) {
        rendererCreator = ((RenderManager) context.getRenderManager()).getRendererCreator();
        rendererCreator.setContext((RenderContext) context);
        return rendererCreator;
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @uml.property name="renderExecutors"
     * @generated NOT
     */
    public Collection<RenderExecutor> getRenderExecutors() {
        return renderExecutors;
    }

    private boolean isFullAlphaUsed(RenderExecutor executor) {
   
        Object object = getContext().getMap().getBlackboard().get("MYLAR"); //$NON-NLS-1$
       
        if( object==null || !((Boolean)object).booleanValue() )
      return true;
   
    if( executor.getContext() instanceof CompositeRenderContext ){
      CompositeRenderContext context=(CompositeRenderContext) executor.getContext();
      if (context.getLayers().contains(getContext().getSelectedLayer()) )
        return true;
     
      return false;
    }
   
    if (executor.getContext().getLayer()==getContext().getSelectedLayer())
      return true;
   
    return false;
  }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @throws RenderException
     * @generated NOT
     */
    public void refreshImage() throws RenderException {
        refreshImage(true);
    }

    /**
     * Vitalus:
     * Refreshes map image from buffered images of renderers with or without
     * labels cache painting.
     *
     * @param paintLabels
     */
   
   
    void refreshImage(boolean paintLabels) throws RenderException{
        if( getContext().getMapDisplay()==null ){
            // we've been disposed lets bail
            return;
        }
        synchronized (getContext()) {
            Graphics2D g = null;
            try {
                BufferedImage current = getContext().getImage();
               
                //create a copy of the image to draw into
           
                BufferedImage copy = new BufferedImage(current.getWidth(), current.getHeight(),current.getType() );
           
                g = (Graphics2D)copy.getGraphics();
               
                g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
                g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
                g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED);
                g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
                g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
                g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
               
                IMap map = getContext().getMap();
                Object object = map.getBlackboard().get(ProjectBlackboardConstants.MAP__BACKGROUND_COLOR);
                if( object==null ){
                    IPreferenceStore store = ProjectPlugin.getPlugin().getPreferenceStore();
                    RGB background = PreferenceConverter.getColor(store, PreferenceConstants.P_BACKGROUND);
                    map.getBlackboard().put(ProjectBlackboardConstants.MAP__BACKGROUND_COLOR, new Color(background.red, background.green, background.blue ));
                    object = map.getBlackboard().get(ProjectBlackboardConstants.MAP__BACKGROUND_COLOR);
                }
                g.setBackground((Color) object);
                g.clearRect(0,0,copy.getWidth(), copy.getHeight());
               
                SortedSet<RenderExecutor> executors;
                synchronized (renderExecutors) {
                    executors = new TreeSet<RenderExecutor>(comparator);
                    executors.addAll(getRenderExecutors());
                }
                ILabelPainter cache = getContext().getLabelPainter();
               
                RENDERERS: for( RenderExecutor executor : executors ) {

                    if (!executor.getContext().isVisible()){
                        if(paintLabels && !(executor.getContext().getLayer() instanceof SelectionLayer)){
                          //disable layer from label cache
                            cache.disableLayer(executor.getContext().getLayer().getID().toString());
                        }
                        continue RENDERERS;
                    }
                       

                    if (executor.getState() == NEVER || executor.getState() == STARTING || executor.getState() == RENDER_REQUEST) {
                        continue RENDERERS;
                    }
                    if( isFullAlphaUsed(executor) ){
                        g.setComposite(AlphaComposite.getInstance(
                                AlphaComposite.SRC_OVER, 1.0f));
                    }else{
                        g.setComposite(AlphaComposite.getInstance(
                                AlphaComposite.SRC_OVER, 0.5f));                       
                    }
                    g.drawRenderedImage(executor.getContext().getImage(), IDENTITY);
                }
                if(paintLabels){
                    RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g.setRenderingHints(hints);
                    Dimension displaySize = getContext().getMapDisplay().getDisplaySize();
                    try {
                        cache.end(g, new Rectangle(displaySize));
                    }
                    catch( Throwable t ){
                        ProjectPlugin.trace( CompositeRenderContextImpl.class,"painting labels failed", t );
                    }
                }

                //update the context with the new image
                ((RenderContextImpl)getContext()).setImage(copy);
               

            } catch (IllegalStateException e) {
                stopRendering();
//                e.printStackTrace();
                return;
            } finally {
                if (g != null)
                    g.dispose();
            }
        }
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @throws RenderException
     * @generated NOT
     */
    public void render( Graphics2D destination, IProgressMonitor monitor ) throws RenderException {
        // notify that they are starting
        for( RenderExecutor executor : renderExecutors ) {
            executor.getRenderer().setState(STARTING);
        }
        for( RenderExecutor executor : renderExecutors ) {
            executor.render();
        }
    }

    /**
     * @see org.locationtech.udig.project.internal.render.Renderer#getInfo(java.awt.Point,
     *      org.locationtech.udig.project.Layer) public InfoList getInfo(Point screenLocation) throws
     *      IOException { InfoList infos = new InfoList(screenLocation); Iterator iter =
     *      getRenderExecutors().iterator(); while (iter.hasNext()) { Renderer renderer =
     *      ((RenderExecutor) iter.next()); List results = renderer.getInfo(screenLocation); if
     *      (results != null) { infos.addAll(results); } } return infos; }
     */

    /**
     * @throws RenderException
     * @see org.locationtech.udig.project.internal.render.Renderer#render(com.vividsolutions.jts.geom.Envelope)
     */
    public void render( IProgressMonitor monitor ) throws RenderException {
        if (getRenderExecutors().size() == 0)
            setState(DONE);
        for (RenderExecutor renderExecutor : getRenderExecutors()) {
            renderExecutor.setRenderBounds(getRenderBounds());
            renderExecutor.render( );
        }
    }

    /**
     * @see org.locationtech.udig.project.internal.render.impl.RendererImpl#setContext(org.locationtech.udig.project.render.RenderContext)
     */
    @SuppressWarnings("unchecked")
    public void setContext( IRenderContext newContext ) {
        if (context != null) {
            ((CompositeRenderContext) context).removeListener(contextListener);
        }
        if (newContext != null) {
            CompositeRenderContext compositeRenderContext = (CompositeRenderContext) newContext;
            compositeRenderContext.addListener(contextListener);
            for( IRenderContext context : compositeRenderContext.getContexts() ) {
                if (findExecutor(context) == null) {
                    Renderer renderer = getRendererCreator(context).getRenderer((RenderContext) context);
                    getRenderExecutors().add(createRenderExecutor(renderer));
                }
            }
            super.setContext(newContext);
        }
    }

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    public void stopRendering() {
        for (RenderExecutor element : getRenderExecutors()) {
            element.stopRendering();
        }
    }

} // CompositeRendererImpl
TOP

Related Classes of org.locationtech.udig.project.internal.render.impl.CompositeRendererImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.