Package org.locationtech.udig.project.ui.internal

Source Code of org.locationtech.udig.project.ui.internal.RenderManagerDynamic

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

import static org.locationtech.udig.project.ui.internal.Trace.RENDER;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.internal.ContextModelListenerAdapter;
import org.locationtech.udig.project.internal.Layer;
import org.locationtech.udig.project.internal.Map;
import org.locationtech.udig.project.internal.ProjectPackage;
import org.locationtech.udig.project.internal.ProjectPlugin;
import org.locationtech.udig.project.internal.render.CompositeRenderContext;
import org.locationtech.udig.project.internal.render.ExecutorVisitor;
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.RenderPackage;
import org.locationtech.udig.project.internal.render.SelectionLayer;
import org.locationtech.udig.project.internal.render.impl.CompositeRenderContextImpl;
import org.locationtech.udig.project.internal.render.impl.CompositeRendererImpl;
import org.locationtech.udig.project.internal.render.impl.RenderExecutorComposite;
import org.locationtech.udig.project.internal.render.impl.RenderExecutorMultiLayer;
import org.locationtech.udig.project.internal.render.impl.RenderManagerImpl;
import org.locationtech.udig.project.render.IRenderContext;
import org.locationtech.udig.project.render.IRenderer;
import org.locationtech.udig.project.render.RenderException;
import org.locationtech.udig.project.render.displayAdapter.IMapDisplay;
import org.locationtech.udig.project.ui.render.displayAdapter.ViewportPane;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.geotools.geometry.jts.ReferencedEnvelope;

import com.vividsolutions.jts.geom.Envelope;

/**
* A IRenderManager that is reacts to events such as viewport model changes.
* <p>
* These are the events we have found this beastie pays attention to:
* <ul>
* <li>viewportListner will trigger some kind of refresh when you change view
* size
* <li>renderExecuttorListener does not actually do much; it passes along
* something else that actually does the listeneing. The composite render
* exector
* <li>contextModelAdapter watches the IMap and notices new layers, deleted
* layers, zorder changing and the occasional style change
* </ul>
* The Map owns one of these things; uses it to scribble on the screen to the
* user.
*
* @generated
*/
public class RenderManagerDynamic extends RenderManagerImpl {
  /**
   * Watches the layer add / delete / change of zorder and style changes.
   */
  ContextModelListenerAdapter contextModelAdapter = RenderManagerAdapters
      .createContextModelListener(this);
  /**
   * Watches the viewport model and triggers some kind of refresh. This is the
   * bounds and the crs changing; panning zooming swooshing and other assorted
   * user drive fun.
   */
  Adapter viewportListener = RenderManagerAdapters
      .createViewportListener(this);

  /**
   * listents to the viewport model (using the provided viewportListener)
   * and morphing the events into something for the map to be updated with?
   *
   */
  private Adapter viewportModelChangeListener = RenderManagerAdapters
            .createViewportModelChangeListener(this, viewportListener, contextModelAdapter);

  /**
   * Collection of contexts used to draw the images.
   */
    public volatile Collection<RenderContext> configuration = null;

    /**
     * <!-- begin-user-doc --> <!-- end-user-doc -->
     *
     * @generated NOT
     */
    @SuppressWarnings("unchecked")
  public RenderManagerDynamic() {
    super();
    eAdapters().add(viewportModelChangeListener);
  }

  /**
   * @see org.locationtech.udig.project.render.impl.RenderManagerImpl#refresh(org.locationtech.udig.project.Layer)
   */
  public void refresh(final ILayer layer, Envelope bounds) {
    checkState();
    if (!renderingEnabled) {
      return;
    }

    if (getMapDisplay() == null || getRenderExecutor() == null) {
      return; // we are not set up to renderer yet!
    }
    getRendererCreator().reset();
    validateRendererConfiguration();
    final SelectionLayer selectionLayer = getRendererCreator()
        .findSelectionLayer(layer);

    final ReferencedEnvelope bbox = bounds == null
        || bounds instanceof ReferencedEnvelope ? (ReferencedEnvelope) bounds
        : new ReferencedEnvelope(bounds, getRenderExecutor()
            .getContext().getCRS());

    getRenderExecutor().visit(new ExecutorVisitor() {
      public void visit(RenderExecutor executor) {
        if (executor.getContext().getLayer() == layer
            || selectionLayer == executor.getContext().getLayer()) {
          // tell the renderer the area of the screen to refresh
          executor.getRenderer().setRenderBounds(bbox);
          // register our interest in seeing the screen redrawn
          executor.getRenderer().setState(IRenderer.RENDER_REQUEST);
        }
      }

      public void visit(RenderExecutorMultiLayer executor) {
        if (executor.getContext().getLayers().contains(layer)
            || executor.getContext().getLayers().contains(
                selectionLayer))
          executor.getRenderer().setState(IRenderer.RENDER_REQUEST);
      }

      public void visit(RenderExecutorComposite executor) {
        List<RenderExecutor> executors = new ArrayList<RenderExecutor>(
            executor.getRenderer().getRenderExecutors());
        for (RenderExecutor child : executors) {
          child.visit(this);
        }
      }
    });
  }
 
  @Override
    public void refreshImage() {
      try {
            ((CompositeRendererImpl)getRenderExecutor().getRenderer()).refreshImage();
            getRenderExecutor().setState(IRenderer.DONE);
        } catch (RenderException e) {
            ProjectPlugin.log("", e); //$NON-NLS-1$
        }
    }

  /**
   * @see org.locationtech.udig.project.render.impl.RenderManagerImpl#refreshSelection(com.vividsolutions.jts.geom.Envelope)
   */
  public void refreshSelection(final ILayer layer, final Envelope bounds) {
    checkState();
    if (!renderingEnabled) {
      return;
    }

    if (getMapDisplay() == null || getRenderExecutor() == null)
      return;

    final Layer selectionLayer = getRendererCreator().findSelectionLayer(
        layer);

    if (selectionLayer == null)
      return;

    getRendererCreator().reset();
    validateRendererConfiguration();

    getRenderExecutor().visit(new ExecutorVisitor() {
      public void visit(RenderExecutor executor) {
        IRenderContext context = executor.getContext();
        if (selectionLayer == context.getLayer()) {
          executor.getRenderer().setRenderBounds(bounds);
          if (bounds != null) {
            Rectangle bounds2 = context.toShape(
                new ReferencedEnvelope(bounds,
                    getViewportModelInternal().getCRS()))
                .getBounds();
            context.clearImage(bounds2);
          } else {
            context.clearImage();
          }
          executor.getRenderer().setState(IRenderer.RENDER_REQUEST);
        }
      }

      public void visit(RenderExecutorMultiLayer executor) {
        CompositeRenderContext contexts = executor.getContext();
        for (IRenderContext context : contexts.getContexts()) {
          if (context.getLayer() == selectionLayer) {
            executor.getRenderer().setState(
                IRenderer.RENDER_REQUEST);
            return;
          }
        }
      }

      public void visit(RenderExecutorComposite executor) {
        for (RenderExecutor child : executor.getRenderer()
            .getRenderExecutors())
          child.visit(this);
      }
    });
  }

  /**
   * @see org.locationtech.udig.project.render.IRenderManager#clearSelection(ILayer)
   */
  public void clearSelection(ILayer layer) {
    checkState();
    if (getMapDisplay() == null || getRenderExecutor() == null)
      return;
    final Layer selectionLayer = getRendererCreator().findSelectionLayer(
        layer);

    if (selectionLayer == null)
      return;

    try {
      CompositeRendererImpl compositeRendererImpl = (CompositeRendererImpl) getRenderExecutor()
          .getRenderer();
      compositeRendererImpl.refreshImage();
      compositeRendererImpl.setState(IRenderer.DONE);

    } catch (RenderException e) {
      ProjectUIPlugin.log("", e); //$NON-NLS-1$
    }
  }

  /**
   * <!-- begin-user-doc --> <!-- end-user-doc -->
   *
   * @generated NOT
   */
  @SuppressWarnings("unchecked")
  public void refresh(final Envelope bounds) {
    checkState();
    if (!renderingEnabled) {
      return;
    }
    getViewportModelInternal().setInitialized(true);
    if (getMapDisplay() == null) {
      return;
    }
    if (getMapDisplay().getWidth() < 1 || getMapDisplay().getHeight() < 1)
      return;

    getRendererCreator().reset();
    validateRendererConfiguration();

    if (!getMapInternal().getContextModel().eAdapters().contains(
        contextModelAdapter))
      getMapInternal().getContextModel().eAdapters().add(
          contextModelAdapter);

    try {
      getRenderExecutor().setRenderBounds(bounds);
      getRenderExecutor().render();
    } catch (RenderException e) {
      // Won't happen
    }
  }

  void initRenderCreator(RenderContext context) {
    checkState();
    List<Layer> layers = getMapInternal().getLayersInternal();
    // make sure renderer creator is initialized.
    getRendererCreator().setContext(context);
    ENotificationImpl notification = new ENotificationImpl(this,
        Notification.ADD_MANY, ProjectPackage.CONTEXT_MODEL__LAYERS,
        null, layers);
    getRendererCreator().changed(notification);

  }

  /**
   * <!-- begin-user-doc --> <!-- end-user-doc -->
   *
   * @generated NOT
   */
  @SuppressWarnings("unchecked")
  public void dispose() {
    configuration = null;
    Set<EObject> set = new HashSet<EObject>();
    set.add(getMapInternal());
    Iterator<EObject> iter = getMapInternal().eAllContents();
    while (iter.hasNext()) {
      EObject obj = iter.next();
      removeAdapters(obj);
    }
    removeAdapters(getRenderExecutor());
    ((ViewportPane) mapDisplay).setRenderManager(null);
    super.dispose();
  }

  /**
   * @param obj
   */
  private void removeAdapters(EObject obj) {
    obj.eAdapters().remove(this.viewportListener);
    obj.eAdapters().remove(this.viewportModelChangeListener);
    obj.eAdapters().remove(this.contextModelAdapter);
    obj.eAdapters().remove(this.renderExecutorListener);
    obj.eAdapters().remove(this.selectionListener);
  }

  /**
   * <!-- begin-user-doc --> <!-- end-user-doc -->
   *
   * @generated
   */
  public void setDisplayGen(IMapDisplay newDisplay) {
    IMapDisplay oldDisplay = mapDisplay;
    mapDisplay = newDisplay;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET,
          RenderPackage.RENDER_MANAGER__MAP_DISPLAY, oldDisplay,
          mapDisplay));
  }

  /**
   * TODO summary sentence for setViewport ...
   *
   * @see org.locationtech.udig.project.render.RenderManager#setDisplay(org.locationtech.udig.project.render.displayAdapter.IMapDisplay)
   * @param value
   */
  public void setDisplay(IMapDisplay value) {
    checkState();
    ((ViewportPane) value).setRenderManager(this);
    setDisplayGen(value);
  }

  Adapter renderExecutorListener = RenderManagerAdapters
      .getRenderExecutorListener(this);

  /**
   * @see org.locationtech.udig.project.render.impl.RenderManagerImpl#setRenderExecutor(org.locationtech.udig.project.render.RenderExecutor)
   */
  @SuppressWarnings("unchecked")
  public void setRenderExecutor(RenderExecutor newRenderExecutor) {
    checkState();
    if (renderExecutor != null) {
      renderExecutor.eAdapters().remove(renderExecutorListener);
    }
    if (newRenderExecutor != null
        && !newRenderExecutor.eAdapters().contains(
            renderExecutorListener)) {
      newRenderExecutor.eAdapters().add(renderExecutorListener);
    }
    super.setRenderExecutor(newRenderExecutor);
  }

  Adapter selectionListener = RenderManagerAdapters.createLayerListener(this);

  /**
   * @see org.locationtech.udig.project.render.impl.RenderManagerImpl#basicSetMap(org.locationtech.udig.project.Map,
   *      org.eclipse.emf.common.notify.NotificationChain)
   */
  @SuppressWarnings("unchecked")
  public NotificationChain basicSetMapInternal(Map newMap,
      NotificationChain msgs) {
    if (getMapInternal() != null) {
      getMapInternal().eAdapters().remove(selectionListener);
      getMapInternal().removeDeepAdapter(selectionListener);
    }
    if (newMap != null) {
      newMap.eAdapters().add(selectionListener);
      newMap.addDeepAdapter(selectionListener);
    }
    return super.basicSetMapInternal(newMap, msgs);
  }

  /**
   * Ensures that the current configuration of renderer is a valid choice. For
   * example the each of the layers in the map has a renderer that can render
   * it.
   */
  public void validateRendererConfiguration() {
    checkState();
    Collection<RenderContext> configuration;
    synchronized (this) {
      if (this.configuration == null) {
        configuration = null;
      } else {
        configuration = new ArrayList<RenderContext>(this.configuration);
      }
    }
    Collection<RenderContext> configuration2;
    if (configuration != null) {
      configuration2 = getRendererCreator().getConfiguration();
      List<RenderContext> removeList = new ArrayList<RenderContext>();
      List<RenderContext> addList = new ArrayList<RenderContext>();
      for (IRenderContext context : configuration) {
        if (!configuration2.contains(context))
          removeList.add((RenderContext) context);
      }
      for (RenderContext context : configuration2) {
        if (configuration.contains(context))
          continue;

        addList.add(context);
      }
      CompositeRenderContext compositecontext = (CompositeRenderContext) getRenderExecutor()
          .getContext();
      compositecontext.removeContexts(removeList);
      if (!addList.isEmpty())
        compositecontext.removeContexts(addList);
      compositecontext.addContexts(addList);

    } else {
      initRenderExecutor();
      configuration2 = getRendererCreator().getConfiguration();

      CompositeRenderContext compositecontext = (CompositeRenderContext) getRenderExecutor()
          .getContext();
      // need this because this is taking place in a non-synchronized
      // block so it is possible for
      // this code to be executed twice. I want the second run to be
      // accurate.
      // might need to be thought about more.
      compositecontext.clear();
      compositecontext.addContexts(configuration2);
    }
    synchronized (this) {
      this.configuration = configuration2;
    }
    logRendererTypes();

  }

  /**
     *
     */
  private void initRenderExecutor() {
    checkState();
    MultiLayerRenderer renderExecutor = RenderFactory.eINSTANCE
        .createCompositeRenderer();
    CompositeRenderContext context = new CompositeRenderContextImpl() {
      @Override
      public synchronized BufferedImage getImage(int width, int height) {
        if (image == null || image.getWidth() < width
            || image.getHeight() < height) {
          image = new BufferedImage(width, height,
              BufferedImage.TYPE_3BYTE_BGR);
          Graphics2D g = image.createGraphics();
          g.setBackground(Color.WHITE);
          g.clearRect(0, 0, width, height);
          g.dispose();
        }

        return image;
      }

      @Override
      public synchronized void clearImage(Rectangle paintArea) {
        if (image == null)
          return;
        Graphics2D g = image.createGraphics();
        g.setBackground(Color.WHITE);
        g.clearRect(paintArea.x, paintArea.y, paintArea.width,
            paintArea.height);
        g.dispose();
        // // FIXME Arbonaut Oy , Vitali Diatchkov
        // System.out.println(
        // "synchronized CompositeRenderContext.clearImage()");
      }

    };
    context.setMapInternal(getMapInternal());
    context.setRenderManagerInternal(this);
   
    renderExecutor.setContext(context);

    initRenderCreator(context);

    renderExecutor.setName(Messages.RenderManagerDynamic_allLayers);
    setRenderExecutor(RenderFactory.eINSTANCE
        .createRenderExecutor(renderExecutor));
  }

  private void logRendererTypes() {
    if (ProjectUIPlugin.isDebugging(RENDER)) {

      final StringBuffer log = new StringBuffer("Current Renderers:"); //$NON-NLS-1$
      getRenderExecutor().visit(new ExecutorVisitor() {
        public void visit(RenderExecutor executor) {
          log
              .append("\n\t" + executor.getClass().getSimpleName() + ":" + //$NON-NLS-1$ //$NON-NLS-2$
                  executor.getRenderer().getClass()
                      .getSimpleName() + "-" + //$NON-NLS-1$
                  executor.getContext().getLayer().getName());
        }

        public void visit(RenderExecutorComposite executor) {
          log
              .append("\n\t" + executor.getRenderer().getClass().getSimpleName()); //$NON-NLS-1$
          for (RenderExecutor child : executor.getRenderer()
              .getRenderExecutors())
            child.visit(this);
        }

        public void visit(RenderExecutorMultiLayer executor) {
          log
              .append("\n\t" + executor.getRenderer().getClass().getSimpleName()); //$NON-NLS-1$
        }
      });
      System.out.println(log);
    }
  }

  public RenderExecutor getRenderExecutor() {
    checkState();
    if (renderExecutor == null) {
      initRenderExecutor();
    }

    return renderExecutor;
  }
} // RenderManagerImpl
TOP

Related Classes of org.locationtech.udig.project.ui.internal.RenderManagerDynamic

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.