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

Source Code of org.locationtech.udig.project.ui.internal.render.displayAdapter.impl.ViewportPainter$CommandList

/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2004-2012, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.project.ui.internal.render.displayAdapter.impl;

import java.awt.Color;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.RenderedImage;
import java.util.Map;
import java.util.Set;

import org.locationtech.udig.project.internal.render.ViewportModel;
import org.locationtech.udig.project.render.Tile;
import org.locationtech.udig.project.ui.commands.IDrawCommand;
import org.locationtech.udig.project.ui.commands.IMapTransformCommand;
import org.locationtech.udig.project.ui.commands.IPreMapDrawCommand;
import org.locationtech.udig.project.ui.internal.ProjectUIPlugin;
import org.locationtech.udig.project.ui.internal.commands.draw.DrawEditFeatureCommand;
import org.locationtech.udig.project.ui.render.displayAdapter.ViewportPane;
import org.locationtech.udig.project.ui.render.glass.GlassPane;
import org.locationtech.udig.ui.graphics.ViewportGraphics;

import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.swt.graphics.GC;
import org.geotools.geometry.jts.ReferencedEnvelope;

import com.vividsolutions.jts.geom.Coordinate;

/**
* Draws to the Viewport. Handles command processing.
*
* @author jeichar
* @since 0.3
*/
public class ViewportPainter {

    private CommandList commands = new CommandList();
    private ViewportPane pane;
    private int renderState = 0;
    private static final int RENDERING = 1;
    private static final int STARTING = 1 << 1;
    private static final int DONE = 1 << 2;
    private static final AffineTransform IDENTITY = new AffineTransform();
   
    private static final boolean TESTING = ProjectUIPlugin.getDefault().isDebugging();
   
    private DrawEditFeatureCommand editfeatureCommand;

    /**
     * Whether to draw custom <code>IDrawCommand</code>s during painting.
     */
    private boolean enable = true;
   
    /**
     * Construct <code>ViewportPainter</code>.
     *
     * @param pane owner pane
     */
    public ViewportPainter( ViewportPane pane ) {
        this.pane = pane;
    }

    /**
     * Paints the image and all the currently valid commands on the viewport.
     *
     * @param g The graphics to draw on.
     * @param image The image to draw.
     * @param minHeight
     * @param minWidth
     */
    public void paint( ViewportGraphics g, Image image, int minWidth, int minHeight ) {
        processCommands(g, true);
        clearPane(g, minWidth, minHeight);
        g.drawImage(image, 0, 0, minWidth, minHeight, 0, 0, minWidth, minHeight);
       
        //draw glass pane
        drawGlassPane(g);
       
        processCommands(g, false);
        runEditFeatureCommand(g);
    }
   
    /**
     * Switches on/off graphics being rendered by custom <code>IDrawCommand</code>s.
     * <br><code>IMapTransformCommand</code>s are processed always regardless
     * enablement.
     *
     * @param enable
     */
    public void switchOnOff(boolean enable){
      this.enable = enable;
    }

    /**
     * @param g
     * @param minWidth
     * @param minHeight
     */
    private void clearPane( ViewportGraphics g, int minWidth, int minHeight ) {
        if (!g.getTransform().isIdentity()) {
            AffineTransform t = g.getTransform();
            g.setTransform(IDENTITY);
            g.clearRect(0, 0, pane.getWidth(), pane.getHeight());
            g.setTransform(t);
        } else {
            if (minWidth < pane.getWidth())
                g.clearRect(minWidth, 0, pane.getWidth() - minWidth, pane.getHeight());
            if (minHeight < pane.getHeight())
                g.clearRect(0, minHeight, pane.getWidth(), pane.getHeight() - minHeight);
        }
    }

    /**
     * Paints the image and all the currently valid commands on the viewport.
     *
     * @param g The graphics to draw on.
     * @param image The image to draw.
     * @param minHeight
     * @param minWidth
     */
    public void paint( ViewportGraphics g, org.eclipse.swt.graphics.Image image, int minWidth,
            int minHeight ) {
        processCommands(g, true);
        clearPane(g, minWidth, minHeight);
        if( image!=null ) {
            g.drawImage(image, 0, 0, minWidth, minHeight, 0, 0, minWidth, minHeight);
        }
        //draw glass pane
        drawGlassPane(g);
       
        processCommands(g, false);
        runEditFeatureCommand(g);
    }
   
    /**
     * Paints the image of all the given tiles, and all the currently valid commands on
     * the viewport.
     *
     * @param g The graphics to draw on.
     * @param tiles the tiles to draw.
     * @param minHeight of total area to be painted
     * @param minWidth of total area to be painted
     */
    public void paint( ViewportGraphics g, Map<ReferencedEnvelope, Tile> tiles, int minWidth, int minHeight ) {
        processCommands(g, true);
        clearPane(g, minWidth, minHeight);

        if (tiles != null) {
          // determine if we are drawing AWT or SWT
          GC gc = g.getGraphics(GC.class);
          if (gc != null ) {
            // SWT, draw all the tiles
            Set<ReferencedEnvelope> keySet = tiles.keySet();
              for (ReferencedEnvelope env : keySet) {
                Tile tile = tiles.get(env);
                //System.out.println("SWTImage: "+tile.getSWTImage());
                ViewportModel viewportModelInternal = tile.getRenderExecutor().getRenderer().getContext().getViewportModelInternal();
                java.awt.Point a = viewportModelInternal.worldToPixel(new Coordinate(env.getMinX(), env.getMinY()));
              java.awt.Point b = viewportModelInternal.worldToPixel(new Coordinate(env.getMaxX(), env.getMaxY()));
                    int width = b.x - a.x;
                    int height = a.y - b.y;
              synchronized (tile) {
                      //an exception can be thrown here if the image has been disposed of
                      //since it was retrieved or something else bad happens while drawing
                      //this is OK in our case because another paint event should be coming soon
                      //which will fix the issue; so for now we just catch the errors
                      //and don't worry about them.
                      try{
                          org.eclipse.swt.graphics.Image im = tile.getSWTImage();
                          gc.drawImage(im, 0, 0, im.getBounds().width, im.getBounds().height, a.x, b.y, width, height);
                      }catch (Exception ex){
                      }   
                    }
              if( TESTING ){
                    g.setColor(Color.BLUE);
                      g.drawLine(a.x, a.y, a.x, b.y);
                      g.drawLine(a.x, b.y, b.x, b.y);
                      g.drawLine(b.x, b.y, b.x, a.y);
                      g.drawLine(b.x, a.y, a.x, a.y);               
              }
              }  
            }
          else {
            // AWT, draw all the tiles
            Set<ReferencedEnvelope> keySet = tiles.keySet();
              for (ReferencedEnvelope env : keySet) {
                Tile tile = tiles.get(env);
                //System.out.println("BufferedImage: "+tile.getBufferedImage());
                ViewportModel viewportModelInternal = tile.getRenderExecutor().getRenderer().getContext().getViewportModelInternal();
                java.awt.Point a = viewportModelInternal.worldToPixel(new Coordinate(env.getMinX(), env.getMinY()));
                java.awt.Point b = viewportModelInternal.worldToPixel(new Coordinate(env.getMaxX(), env.getMaxY()));
                g.drawImage((RenderedImage)tile.getBufferedImage(), a.x, b.y);
                g.setColor(Color.BLUE);
                  g.drawLine(a.x, a.y, a.x, b.y);
                  g.drawLine(a.x, b.y, b.x, b.y);
                  g.drawLine(b.x, b.y, b.x, a.y);
                  g.drawLine(b.x, a.y, a.x, a.y);                 
              }
          }
         
        }
        //draw glass pane
        drawGlassPane(g);
        processCommands(g, false);
        runEditFeatureCommand(g);
    }

    private void runEditFeatureCommand( ViewportGraphics g ) {
        if (editfeatureCommand == null
                && pane.getMapEditor().getMap().getViewportModelInternal() != null) {
            editfeatureCommand = new DrawEditFeatureCommand(pane.getMapEditor().getMap()
                    .getViewportModelInternal());
        }
        if (editfeatureCommand != null) {
            editfeatureCommand.setGraphics(g, pane);
//            editfeatureCommand.run(null);
        }
    }

    private void processCommands( ViewportGraphics g, boolean pre ) {
        //System.out.println("process commands");
//      if(enable){
          try {
              Object[] varray = null;
              if (pre)
                  varray = commands.getPreCommands();
              else
                  varray = commands.getPostCommands();
              for( int i = 0; i < varray.length; i++ ) {
                  IDrawCommand command = (IDrawCommand) varray[i];
                 
//                  //TODO probably add other command types as  exceptions.
//                  if(!enable && !(command instanceof IMapTransformCommand))
//                    continue;
                 
                  if (command.isValid()) {
                      command.setGraphics(g, pane);
                      try {
                          command.setMap(this.pane.getMapEditor().getMap());
                          command.run(new NullProgressMonitor());
                      } catch (Exception e) {
                          ProjectUIPlugin.log("", e); //$NON-NLS-1$
                            if(pre){
                                commands.removePre(command);
                            }else{
                                commands.removePost(command);
                            }
                      }
                  } else {
                      if (pre)
                          commands.removePre(command);
                      else
                          commands.removePost(command);
                  }
              }
          } catch (Exception e) {
                ProjectUIPlugin.log("", e); //$NON-NLS-1$
              commands.clearCommands();
          }
//      }
    }

    /**
     * Dispose of resources
     */
    public void dispose() {
        // do nothing
    }

    /**
     * Adds a draw command to the set of commands that are executed during a paint.
     *
     * @param command The new command.
     */
    public synchronized void addDrawCommand( IDrawCommand command ) {
        if( command==null )
            throw new NullPointerException();
        commands.add(command);
    }

    private static class CommandList {
        /**
         * Commands that transform the entire display area and are only removed when a rerender
         * occurs Pre commands occur before drawing. Post commands occur after drawing preTI is the
         * count of pre Transform commands postTI is the count of post Transform commands
         */
        IDrawCommand[] preTransform = new IMapTransformCommand[5];
        IDrawCommand[] postTransform = new IMapTransformCommand[5];
        int preTI = 0, postTI = 0;
        /**
         * Commands that decorate display area and are only checked for valid every redraw if
         * invalid they are removed Pre commands occur before drawing. Post commands occur after
         * drawing preNI is the count of pre Normal/Decorator commands postNI is the count of post
         * Normal/Decorator commands
         */
        IDrawCommand[] preNorm = new IDrawCommand[5];
        IDrawCommand[] postNorm = new IDrawCommand[5];
        int preNI = 0, postNI = 0;

        synchronized IDrawCommand[] getPreCommands() {
            if (preNI + preTI == 0)
                return new IDrawCommand[0];
            IDrawCommand[] carray = new IDrawCommand[preNI + preTI];
            if (preTI > 0)
                System.arraycopy(preTransform, 0, carray, 0, preTI);
            if (preNI > 0)
                System.arraycopy(preNorm, 0, carray, preTI, preNI);
            return carray;
        }

        /**
         *
         */
        public void clearCommands() {
            for (IDrawCommand command : preTransform) {
                command.setValid(false);
                command.dispose();
            }
            for (IDrawCommand command : postTransform) {
                command.setValid(false);
                command.dispose();
            }
            preTransform = new IMapTransformCommand[5];
            postTransform = new IMapTransformCommand[5];
            preTI = 0;
            postTI = 0;

            for (IDrawCommand command : preNorm) {
                command.setValid(false);
                command.dispose();
            }
            for (IDrawCommand command : postNorm) {
                command.setValid(false);
                command.dispose();
            }
            preNorm = new IDrawCommand[5];
            postNorm = new IDrawCommand[5];
            preNI = 0;
            postNI = 0;
        }

        synchronized void removePost( IDrawCommand command ) {
            command.setValid(false);
            for( int i = 0; i < postNI; i++ ) {
                if (command == postNorm[i]) {
                    if(i < postNI - 1){
                        System.arraycopy(postNorm, i + 1, postNorm, i, postNI - i - 1);
                    }
                    setPostNI(postNI - 1);
                    return;
                }
            }
            for( int i = 0; i < postTI; i++ ) {
                if (command == postTransform[i]) {
                    if(i < postTI - 1){
                        System.arraycopy(postTransform, i + 1, postTransform, i, postTI - i - 1);
                    }
                    setPostTI(postTI - 1);
                    return;
                }
            }
            command.dispose();
        }

        synchronized void removePre( IDrawCommand command ) {
            command.setValid(false);
            for( int i = 0; i < preNI; i++ ) {
                if (command == preNorm[i]) {
                    if(i < preNI - 1){
                        System.arraycopy(preNorm, i + 1, preNorm, i, preNI - i - 1);
                    }
                    setPreNI(preNI - 1);
                    return;
                }
            }
            for( int i = 0; i < preTI; i++ ) {
                if (command == preTransform[i]) {
                    // TODO this is a bug sometimes
                    if(i < preTI - 1){
                        System.arraycopy(preTransform, i + 1, preTransform, i, preTI - i - 1);
                    }
                    setPreTI(preTI - 1);
                    return;
                }
            }
            command.dispose();
        }
        synchronized IDrawCommand[] getPostCommands() {
            if (postNI + postTI == 0)
                return new IDrawCommand[0];
            IDrawCommand[] carray = new IDrawCommand[postNI + postTI];
            if (postTI > 0)
                System.arraycopy(postTransform, 0, carray, 0, postTI);
            if (postNI > 0)
                System.arraycopy(postNorm, 0, carray, postTI, postNI);
            return carray;
        }
        synchronized void add( IDrawCommand command ) {
            if (command instanceof IPreMapDrawCommand) {
                if (command instanceof IMapTransformCommand) {
                    preTransform = add(command, preTransform, preTI);
                    setPreTI(preTI + 1);
                } else {
                    preNorm = add(command, preNorm, preNI);
                    setPreNI(preNI + 1);
                }
            } else {
                if (command instanceof IMapTransformCommand) {
                    postTransform = add(command, postTransform, postTI);
                    setPostTI(postTI + 1);
                } else {
                    postNorm = add(command, postNorm, postNI);
                    setPostNI(postNI + 1);
                }
            }
        }

        void renderstart() {
            if (preNI > 0) {
                for( IDrawCommand command : preNorm ) {
                    if (command != null)
                        command.setValid(false);
                }
                preNorm = new IDrawCommand[preNI];
                setPreNI(0);
            }
            // if( postNI>0 ){
            // postNorm=new IDrawCommand[postNI];
            // setPostNI(0);
            // }
        }

        void renderupdate() {
            if (preTI > 0) {
                for( IDrawCommand command : preTransform ) {
                    if (command != null)
                        command.setValid(false);
                }
                preTransform = new IDrawCommand[preTI];
                setPreTI(0);
            }
            // if( postTI>0 ){
            // postTransform=new IDrawCommand[postTI];
            // setPostTI(0);
            // }
        }

        private IDrawCommand[] add( IDrawCommand command, IDrawCommand[] array, int index ) {
            if (index == array.length) {
                IDrawCommand[] tmp = array;
                array = new IDrawCommand[index * 2];
                System.arraycopy(tmp, 0, array, 0, index);
            }
            array[index] = command;
            return array;
        }

        private synchronized void setPostNI( int postNI ) {
            if (postNI > -1)
                this.postNI = postNI;
        }
        private synchronized void setPostTI( int postTI ) {
            if (postTI > -1)
                this.postTI = postTI;
        }
        private synchronized void setPreNI( int preNI ) {
            if (preNI > -1)
                this.preNI = preNI;
        }
        private synchronized void setPreTI( int preTI ) {
            if (preTI > -1)
                this.preTI = preTI;
        }
    }

    void renderStart() {
        commands.renderstart();
        renderState = STARTING | RENDERING;
    }

    void renderUpdate() {
        if ((renderState & STARTING) == STARTING) {
            commands.renderupdate();
            renderState = RENDERING;
        }
    }

    void renderDone() {
        renderState = DONE;
    }
   
    /**
     * Returns the viewport pane associated with this painter.
     *
     * @return
     */
    public ViewportPane getPane(){
        return this.pane;
    }
   
    /**
     * Draws the glass pane if the ViewportGraphics is
     * a SWTGraphics or NonAdvancedSWTGraphics.
     *
     * Will not draw the glasspane if it is null or the
     * Viewport Graphics is a AWT Graphics.
     *
     * @param g
     */
    private void drawGlassPane(ViewportGraphics g){
        GC gc = g.getGraphics(GC.class);
        if (gc != null ){
            GlassPane glass = this.pane.getGlass();
            if (glass != null){
                glass.draw(gc);
            }   
        }   
    }
}
TOP

Related Classes of org.locationtech.udig.project.ui.internal.render.displayAdapter.impl.ViewportPainter$CommandList

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.