diff --git a/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF index 350d78994f..8e38aa2417 100644 --- a/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.uf.viz.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Core Plug-in Bundle-SymbolicName: com.raytheon.uf.viz.core;singleton:=true -Bundle-Version: 1.13.0.qualifier +Bundle-Version: 1.14.0.qualifier Bundle-Activator: com.raytheon.uf.viz.core.Activator Bundle-Vendor: Raytheon Require-Bundle: org.eclipse.ui, @@ -17,7 +17,6 @@ Require-Bundle: org.eclipse.ui, com.raytheon.uf.common.status;visibility:=reexport, org.apache.commons.lang, javax.vecmath;bundle-version="1.3.1", - org.geotools;bundle-version="2.5.2", javax.measure;bundle-version="1.0.0", org.jep;bundle-version="1.0.0", com.raytheon.uf.common.datastorage;bundle-version="1.11.11", @@ -38,7 +37,6 @@ Require-Bundle: org.eclipse.ui, com.raytheon.uf.common.comm;bundle-version="1.12.1174", com.raytheon.uf.common.message;bundle-version="1.12.1174", com.raytheon.uf.common.alertmonitor;bundle-version="1.12.1174", - com.raytheon.uf.common.python;bundle-version="1.12.1174", com.raytheon.uf.common.velocity;bundle-version="1.0.0", ch.qos.logback;bundle-version="1.0.13", com.raytheon.uf.common.style;bundle-version="1.0.0", diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/GeneralCanvasRenderingExtension.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/GeneralCanvasRenderingExtension.java index 3cbb52dbd6..bb8778b1cf 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/GeneralCanvasRenderingExtension.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/GeneralCanvasRenderingExtension.java @@ -23,13 +23,16 @@ import java.util.ArrayList; import java.util.List; import com.raytheon.uf.viz.core.DrawableColorMap; +import com.raytheon.uf.viz.core.DrawableImage; import com.raytheon.uf.viz.core.DrawableLine; import com.raytheon.uf.viz.core.DrawableString; -import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.IView; +import com.raytheon.uf.viz.core.PixelCoverage; import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.drawables.PaintProperties; import com.raytheon.uf.viz.core.exception.VizException; +import com.vividsolutions.jts.geom.Coordinate; /** * A general implementation of the canvas rendering extension which converts @@ -39,12 +42,14 @@ import com.raytheon.uf.viz.core.exception.VizException; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jun 26, 2012 bsteffen Initial creation - * Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap - * parameters, disable colormap interpolation - * by default. + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Jun 26, 2012 bsteffen Initial creation + * Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap + * parameters, disable colormap interpolation + * by default. + * Jan 14, 2014 2313 bsteffen Add method to draw images. + * * * * @@ -58,10 +63,7 @@ public class GeneralCanvasRenderingExtension extends @Override public void drawStrings(PaintProperties paintProps, DrawableString... parameters) throws VizException { - IExtent extent = paintProps.getView().getExtent(); - double xRatio = extent.getWidth() / paintProps.getCanvasBounds().width; - double yRatio = extent.getHeight() - / paintProps.getCanvasBounds().height; + IView view = paintProps.getView(); List mapStrings = new ArrayList( parameters.length); @@ -79,10 +81,10 @@ public class GeneralCanvasRenderingExtension extends mapString.basics.alpha = screenString.basics.alpha; mapString.basics.xOrColors = screenString.basics.xOrColors; mapString.basics.color = screenString.basics.color; - mapString.basics.x = extent.getMinX() + screenString.basics.x - * xRatio; - mapString.basics.y = extent.getMinY() + screenString.basics.y - * yRatio; + double[] grid = view.screenToGrid(screenString.basics.x, + screenString.basics.y, 1.0, target); + mapString.basics.x = grid[0]; + mapString.basics.y = grid[1]; mapString.basics.z = screenString.basics.z; mapStrings.add(mapString); } @@ -94,10 +96,7 @@ public class GeneralCanvasRenderingExtension extends @Override public void drawLines(PaintProperties paintProps, DrawableLine... parameters) throws VizException { - IExtent extent = paintProps.getView().getExtent(); - double xRatio = extent.getWidth() / paintProps.getCanvasBounds().width; - double yRatio = extent.getHeight() - / paintProps.getCanvasBounds().height; + IView view = paintProps.getView(); List mapLines = new ArrayList( parameters.length); for (DrawableLine screenLine : parameters) { @@ -108,9 +107,9 @@ public class GeneralCanvasRenderingExtension extends mapLine.basics.color = screenLine.basics.color; mapLine.basics.xOrColors = screenLine.basics.xOrColors; for (double[] point : screenLine.points) { - double x = extent.getMinX() + point[0] * xRatio; - double y = extent.getMinY() + point[1] * yRatio; - mapLine.addPoint(x, y); + double[] grid = view.screenToGrid(point[0], point[1], 1.0, + target); + mapLine.addPoint(grid[0], grid[1]); } mapLines.add(mapLine); } @@ -122,10 +121,7 @@ public class GeneralCanvasRenderingExtension extends @Override public void drawColorRamp(PaintProperties paintProps, DrawableColorMap colorMap) throws VizException { - IExtent extent = paintProps.getView().getExtent(); - double xRatio = extent.getWidth() / paintProps.getCanvasBounds().width; - double yRatio = extent.getHeight() - / paintProps.getCanvasBounds().height; + IView view = paintProps.getView(); DrawableColorMap newColorMap = new DrawableColorMap( colorMap.getColorMapParams()); newColorMap.alpha = colorMap.alpha; @@ -135,17 +131,49 @@ public class GeneralCanvasRenderingExtension extends double y1 = colorMap.extent.getMinY(); double x2 = colorMap.extent.getMaxX(); double y2 = colorMap.extent.getMaxY(); + double[] grid = view.screenToGrid(x1, y1, 1.0, target); + x1 = grid[0]; + y1 = grid[1]; + grid = view.screenToGrid(x2, y2, 1.0, target); + x2 = grid[0]; + y2 = grid[1]; - x1 = extent.getMinX() + x1 * xRatio; - y1 = extent.getMinY() + y1 * yRatio; - x2 = extent.getMinX() + x2 * xRatio; - y2 = extent.getMinY() + y2 * yRatio; newColorMap.extent = new PixelExtent(x1, x2, y1, y2); target.clearClippingPlane(); target.drawColorRamp(newColorMap); target.setupClippingPlane(paintProps.getClippingPane()); } + @Override + public void drawImages(PaintProperties paintProps, DrawableImage... images) + throws VizException { + IView view = paintProps.getView(); + List mapImages = new ArrayList( + images.length); + for (DrawableImage screenImage : images) { + PixelCoverage screenCoverage = screenImage.getCoverage(); + if (screenCoverage.getMesh() != null) { + throw new VizException( + this.getClass().getSimpleName() + + " does not support canvas rendering of images with meshes."); + } + Coordinate ul = screenCoverage.getUl(); + double[] grid = view.screenToGrid(ul.x, ul.y, 1.0, target); + ul = new Coordinate(grid[0], grid[1]); + Coordinate lr = screenCoverage.getLr(); + grid = view.screenToGrid(lr.x, lr.y, 1.0, target); + lr = new Coordinate(grid[0], grid[1]); + Coordinate ur = new Coordinate(lr.x, ul.y); + Coordinate ll = new Coordinate(ul.x, lr.y); + PixelCoverage mapCoverage = new PixelCoverage(ul, ur, lr, ll); + mapImages.add(new DrawableImage(screenImage.getImage(), + mapCoverage, screenImage.getMode())); + } + target.clearClippingPlane(); + target.drawRasters(paintProps, mapImages.toArray(new DrawableImage[0])); + target.setupClippingPlane(paintProps.getClippingPane()); + } + @Override public int getCompatibilityValue(IGraphicsTarget target) { return Compatibilty.GENERIC; diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/ICanvasRenderingExtension.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/ICanvasRenderingExtension.java index ff2697a347..cfd7ea5b1d 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/ICanvasRenderingExtension.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ext/ICanvasRenderingExtension.java @@ -20,6 +20,7 @@ package com.raytheon.uf.viz.core.drawables.ext; import com.raytheon.uf.viz.core.DrawableColorMap; +import com.raytheon.uf.viz.core.DrawableImage; import com.raytheon.uf.viz.core.DrawableLine; import com.raytheon.uf.viz.core.DrawableString; import com.raytheon.uf.viz.core.drawables.PaintProperties; @@ -35,9 +36,11 @@ import com.raytheon.uf.viz.core.exception.VizException; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jun 26, 2012 bsteffen Initial creation + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Jun 26, 2012 bsteffen Initial creation + * Jan 14, 2014 2313 bsteffen Add method to draw images. + * * * * @@ -48,33 +51,59 @@ import com.raytheon.uf.viz.core.exception.VizException; public interface ICanvasRenderingExtension extends IGraphicsExtensionInterface { /** - * Draw the DrawableString object to the screen, the location of the + * Draw the DrawableString objects to the screen, the location of the * draqwable strings should be in canvas pixels which start at 0,0 in the * upper left. * - * @param parameters + * @param paintProps + * the current frame paint properties + * @param strings + * the strings to draw. * @throws VizException */ public abstract void drawStrings(PaintProperties paintProps, - DrawableString... parameters) throws VizException; + DrawableString... strings) throws VizException; /** - * Draw the DrawableLine object to the screen. The points in the line should - * be in canvas pixels which start at 0,0 in the upper left. + * Draw the DrawableLine objects to the screen. The points in the line + * should be in canvas pixels which start at 0,0 in the upper left. + * + * @param paintProps + * the current frame paint properties + * + * @param lines + * the lines to draw. * - * @param parameters * @throws VizException */ public abstract void drawLines(PaintProperties paintProps, - DrawableLine... parameters) throws VizException; + DrawableLine... lines) throws VizException; /** * Draw the drawable colormap to the screen, the extent of the colormap * should be in canvas pixels. * + * @param paintProps + * the current frame paint properties * @param colorMap * the colorMap to draw + * @throws VizException */ public abstract void drawColorRamp(PaintProperties paintProps, DrawableColorMap colorMap) throws VizException; + + /** + * Draw the drawable images to the screen. the coordinates in the pixel + * coverage should be specified in canvas pixels. + * + * @param paintProps + * the current frame paint properties + * @param images + * the images to draw + * @throws VizException + * + * @since 1.14.0 + */ + public abstract void drawImages(PaintProperties paintProps, + DrawableImage... images) throws VizException; } diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/interp/InterpolationContainer.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/interp/InterpolationContainer.java deleted file mode 100644 index 4a602dcbf4..0000000000 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/interp/InterpolationContainer.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.uf.viz.core.interp; - -import jep.INumpyable; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Dec 8, 2009            mschenke     Initial creation
- * 
- * 
- * - * @author mschenke - * @version 1.0 - */ - -public class InterpolationContainer implements INumpyable { - - private float[] xValues; - - private float[] yValues; - - private float[] zValues; - - private float[] xSpace; - - private float[] ySpace; - - private float[] interpValues; - - public InterpolationContainer(float[] xValues, float[] yValues, - float[] zValues) { - this.xValues = xValues; - this.yValues = yValues; - this.zValues = zValues; - } - - /* - * (non-Javadoc) - * - * @see jep.INumpyable#getNumpy() - */ - @Override - public Object[] getNumpy() { - // todo - return new Object[] { xValues, yValues, zValues }; - } - - /* - * (non-Javadoc) - * - * @see jep.INumpyable#getNumpyX() - */ - @Override - public int getNumpyX() { - return xValues.length; - } - - /* - * (non-Javadoc) - * - * @see jep.INumpyable#getNumpyY() - */ - @Override - public int getNumpyY() { - return 1; - } - - public void setResults(float[] XI, float[] YI, float[] ZI) { - this.xSpace = XI; - this.ySpace = YI; - this.interpValues = ZI; - } - - public float[] getXSpace() { - return xSpace; - } - - public float[] getYSpace() { - return ySpace; - } - - public float[] getInterpValues() { - return interpValues; - } - - public float[] getXValues() { - return xValues; - } - - public float[] getYValues() { - return yValues; - } - - public float[] getZValues() { - return zValues; - } - - public void setXValues(float[] values) { - xValues = values; - } - - public void setYValues(float[] values) { - yValues = values; - } - - public void setZValues(float[] values) { - zValues = values; - } -} diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/interp/PythonInterpolation.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/interp/PythonInterpolation.java deleted file mode 100644 index 2baadacf49..0000000000 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/interp/PythonInterpolation.java +++ /dev/null @@ -1,140 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.uf.viz.core.interp; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; - -import jep.JepException; - -import org.geotools.coverage.grid.GeneralGridEnvelope; -import org.geotools.coverage.grid.GridGeometry2D; -import org.geotools.geometry.GeneralEnvelope; - -import com.raytheon.uf.common.localization.PathManagerFactory; -import com.raytheon.uf.common.python.PythonScript; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; -import com.raytheon.uf.common.status.UFStatus.Priority; -import com.raytheon.uf.viz.core.Activator; -import com.raytheon.uf.viz.core.status.StatusConstants; -import com.raytheon.viz.core.slice.request.HeightScale.ScaleType; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Dec 8, 2009            mschenke     Initial creation
- * 
- * 
- * - * @author mschenke - * @version 1.0 - */ - -public class PythonInterpolation implements IInterpolation { - private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(PythonInterpolation.class); - - /** the python function to call */ - protected String function; - - protected String localizationScript = "scripts/interpolation.py"; - - protected static PythonScript ps = null; - - protected File interpolationFile = null; - - public PythonInterpolation(ScaleType scale) { - switch (scale) { - case LIN: { - function = "linInterpolate"; - break; - } - default: { - function = "logInterpolate"; - } - } - } - - /* - * (non-Javadoc) - * - * @seecom.raytheon.uf.viz.core.interp.IInterpolation#interpolate( - * com.raytheon.uf.viz.core.interp.InterpolationRequest, - * org.geotools.coverage.grid.GridGeometry2D) - */ - @Override - public InterpolationResult interpolate(InterpolationRequest request) { - long t0 = System.currentTimeMillis(); - - InterpolationContainer container = new InterpolationContainer(request - .getXData(), request.getYData(), request.getZData()); - try { - if (interpolationFile == null) { - interpolationFile = PathManagerFactory.getPathManager() - .getStaticLocalizationFile(localizationScript) - .getFile(); - } - if (ps == null) { - String file = interpolationFile.getAbsolutePath(); - - ps = new PythonScript(file, "", PythonInterpolation.class - .getClassLoader()); - } - Map args = new HashMap(); - args.put("data", container); - args.put("gridX", request.getGridX()); - args.put("gridY", request.getGridY()); - args.put("xMin", request.getMinX()); - args.put("xMax", request.getMaxX()); - args.put("yMin", request.getMinY()); - args.put("yMax", request.getMaxY()); - ps.execute(function, args); - System.out.println("Time to execute interpolation: " - + (System.currentTimeMillis() - t0)); - InterpolationResult result = new InterpolationResult(); - - result.setValues(container.getInterpValues()); - - float[] xspace = container.getXSpace(); - float[] yspace = container.getYSpace(); - double minX = Math.min(xspace[0], xspace[xspace.length - 1]); - double maxX = Math.max(xspace[0], xspace[xspace.length - 1]); - double minY = Math.min(yspace[0], yspace[yspace.length - 1]); - double maxY = Math.max(yspace[0], yspace[yspace.length - 1]); - GeneralEnvelope env = new GeneralEnvelope( - new double[] { minX, minY }, new double[] { maxX, maxY }); - GeneralGridEnvelope range = new GeneralGridEnvelope(new int[] { 0, - 0 }, new int[] { xspace.length, yspace.length }, false); - result.setGeometry(new GridGeometry2D(range, env)); - return result; - } catch (JepException e) { - statusHandler.handle(Priority.CRITICAL, - "Error running interpolation", e); - } - return null; - } - -} diff --git a/cave/com.raytheon.uf.viz.drawing/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.drawing/META-INF/MANIFEST.MF index 06b6faf4ff..8a57bb8d59 100644 --- a/cave/com.raytheon.uf.viz.drawing/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.uf.viz.drawing/META-INF/MANIFEST.MF @@ -2,20 +2,17 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Drawing Bundle-SymbolicName: com.raytheon.uf.viz.drawing;singleton:=true -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 1.14.0.qualifier Bundle-Activator: com.raytheon.uf.viz.drawing.Activator -Eclipse-RegisterBuddy: com.raytheon.uf.viz.core Bundle-Vendor: RAYTHEON -Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime, - com.raytheon.uf.viz.core;bundle-version="1.12.1174", - com.raytheon.uf.viz.core.rsc;bundle-version="1.0.0", - com.raytheon.uf.common.geospatial;bundle-version="1.12.1174", - com.raytheon.viz.ui;bundle-version="1.12.1174", - org.geotools, - com.raytheon.viz.core;bundle-version="1.12.1174" -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy -Import-Package: com.raytheon.uf.common.time, - com.vividsolutions.jts.geom +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Require-Bundle: com.raytheon.uf.viz.core;bundle-version="1.14.0", + org.eclipse.ui;bundle-version="3.8.0", + org.eclipse.core.runtime;bundle-version="3.8.0", + com.raytheon.uf.common.geospatial, + com.raytheon.viz.ui, + com.raytheon.uf.common.time +Import-Package: com.raytheon.viz.core Export-Package: com.raytheon.uf.viz.drawing + diff --git a/cave/com.raytheon.uf.viz.drawing/plugin.xml b/cave/com.raytheon.uf.viz.drawing/plugin.xml index 5eb191a1bb..18d224ea3a 100644 --- a/cave/com.raytheon.uf.viz.drawing/plugin.xml +++ b/cave/com.raytheon.uf.viz.drawing/plugin.xml @@ -20,4 +20,39 @@ --> + + + + + + + + + + + + + + + + + + diff --git a/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/EditRectangleInputHandler.java b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/EditRectangleInputHandler.java new file mode 100644 index 0000000000..5dbd847ccb --- /dev/null +++ b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/EditRectangleInputHandler.java @@ -0,0 +1,307 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.drawing.image; + +import java.util.EnumSet; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; + +import com.raytheon.uf.viz.core.IDisplayPaneContainer; +import com.raytheon.viz.ui.input.InputAdapter; + +/** + * Input handler for editing a rectangle. Provides the ability to move and + * resize, moving edges individually or from a corner. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 15, 2014  2313     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class EditRectangleInputHandler extends InputAdapter { + + private static final int CLICK_WIDTH = 15; + + private static final int MOUSE_BUTTON = 1; + + private final EditRectangleTarget target; + + private EnumSet activeModes = EnumSet + .noneOf(ResizeDirection.class); + + private Point movePoint = null; + + public EditRectangleInputHandler(EditRectangleTarget target) { + this.target = target; + } + + @Override + public boolean handleMouseMove(int x, int y) { + Rectangle rect = target.getRectangle(); + if (rect == null) { + return false; + } + + if (ResizeDirection.NORTH.intersects(rect, x, y)) { + if (ResizeDirection.EAST.intersects(rect, x, y)) { + setCursor(SWT.CURSOR_SIZENE); + } else if (ResizeDirection.WEST.intersects(rect, x, y)) { + setCursor(SWT.CURSOR_SIZENW); + } else { + setCursor(SWT.CURSOR_SIZEN); + } + } else if (ResizeDirection.SOUTH.intersects(rect, x, y)) { + if (ResizeDirection.EAST.intersects(rect, x, y)) { + setCursor(SWT.CURSOR_SIZESE); + } else if (ResizeDirection.WEST.intersects(rect, x, y)) { + setCursor(SWT.CURSOR_SIZESW); + } else { + setCursor(SWT.CURSOR_SIZES); + } + } else if (ResizeDirection.EAST.intersects(rect, x, y)) { + setCursor(SWT.CURSOR_SIZEE); + } else if (ResizeDirection.WEST.intersects(rect, x, y)) { + setCursor(SWT.CURSOR_SIZEW); + } else if (rect.contains(x, y)) { + setCursor(SWT.CURSOR_HAND); + } else { + unsetCursor(); + } + return true; + } + + @Override + public boolean handleMouseDown(int x, int y, int mouseButton) { + if (mouseButton != MOUSE_BUTTON) { + return false; + } + Rectangle rect = target.getRectangle(); + if (rect == null) { + return false; + } + for (ResizeDirection mode : ResizeDirection.values()) { + if (mode.intersects(rect, x, y)) { + activeModes.add(mode); + } + } + if (activeModes.isEmpty()) { + if (rect.contains(x, y)) { + movePoint = new Point(x, y); + return true; + } + return false; + } else { + return true; + } + } + + @Override + public boolean handleMouseDownMove(int x, int y, int mouseButton) { + if (mouseButton != MOUSE_BUTTON) { + return false; + } + Rectangle rect = target.getRectangle(); + if (rect == null) { + return false; + } + if (movePoint != null) { + int xDist = x - movePoint.x; + int yDist = y - movePoint.y; + target.resize(new Rectangle(rect.x + xDist, rect.y + yDist, + rect.width, rect.height)); + movePoint = new Point(x, y); + setCursor(SWT.CURSOR_SIZEALL); + return true; + } else if (!activeModes.isEmpty()) { + for (ResizeDirection mode : activeModes) { + rect = mode.resize(rect, x, y); + } + target.resize(rect); + return true; + } + return false; + } + + @Override + public boolean handleMouseUp(int x, int y, int mouseButton) { + if (handleMouseDownMove(x, y, mouseButton)) { + activeModes.clear(); + movePoint = null; + handleMouseMove(x, y); + return true; + } else { + return false; + } + } + + @Override + public boolean handleMouseExit(Event event) { + unsetCursor(); + return false; + } + + @Override + public boolean handleMouseEnter(Event event) { + return handleMouseMove(event.x, event.y); + } + + public void enable(IDisplayPaneContainer container) { + if (container == null) { + return; + } + container.registerMouseHandler(this); + } + + public void disable(IDisplayPaneContainer container) { + if (container == null) { + return; + } + container.unregisterMouseHandler(this); + Display.getDefault().asyncExec(new Runnable() { + + @Override + public void run() { + unsetCursor(); + } + }); + } + + protected void unsetCursor() { + getShell().setCursor(null); + } + + protected void setCursor(int cursor) { + Shell shell = getShell(); + Display display = shell.getDisplay(); + shell.setCursor(display.getSystemCursor(cursor)); + } + + protected Shell getShell() { + IWorkbenchWindow window = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow(); + return window.getShell(); + } + + public static interface EditRectangleTarget { + + public Rectangle getRectangle(); + + public void resize(Rectangle rect); + + } + + private static enum ResizeDirection { + NORTH { + public boolean intersects(Rectangle rect, int cx, int cy) { + int x = rect.x - CLICK_WIDTH; + int y = rect.y - CLICK_WIDTH; + int width = rect.width + CLICK_WIDTH * 2; + int height = CLICK_WIDTH * 2; + Rectangle area = new Rectangle(x, y, width, height); + return area.contains(cx, cy); + } + + public Rectangle resize(Rectangle rect, int cx, int cy) { + int x = rect.x; + int y = cy; + int width = rect.width; + int height = rect.height - y + rect.y; + return new Rectangle(x, y, width, height); + } + }, + SOUTH { + public boolean intersects(Rectangle rect, int cx, int cy) { + int x = rect.x - CLICK_WIDTH; + int y = rect.y + rect.height - CLICK_WIDTH; + int width = rect.width + CLICK_WIDTH * 2; + int height = CLICK_WIDTH * 2; + Rectangle area = new Rectangle(x, y, width, height); + return area.contains(cx, cy); + } + + public Rectangle resize(Rectangle rect, int cx, int cy) { + int x = rect.x; + int y = rect.y; + int width = rect.width; + int height = rect.height + cy - rect.y - rect.height; + return new Rectangle(x, y, width, height); + } + }, + WEST { + public boolean intersects(Rectangle rect, int cx, int cy) { + int x = rect.x - CLICK_WIDTH; + int y = rect.y - CLICK_WIDTH; + int width = CLICK_WIDTH * 2; + int height = rect.height + CLICK_WIDTH * 2; + Rectangle area = new Rectangle(x, y, width, height); + return area.contains(cx, cy); + } + + public Rectangle resize(Rectangle rect, int cx, int cy) { + int x = cx; + int y = rect.y; + int width = rect.width - cx + rect.x; + int height = rect.height; + return new Rectangle(x, y, width, height); + } + + }, + EAST { + public boolean intersects(Rectangle rect, int cx, int cy) { + int x = rect.x + rect.width - CLICK_WIDTH; + int y = rect.y - CLICK_WIDTH; + int width = CLICK_WIDTH * 2; + int height = rect.height + CLICK_WIDTH * 2; + Rectangle area = new Rectangle(x, y, width, height); + return area.contains(cx, cy); + } + + public Rectangle resize(Rectangle rect, int cx, int cy) { + int x = rect.x; + int y = rect.y; + int width = rect.width + cx - rect.x - rect.width; + int height = rect.height; + return new Rectangle(x, y, width, height); + } + + }; + + public abstract boolean intersects(Rectangle rect, int cx, int cy); + + public abstract Rectangle resize(Rectangle rect, int cx, int cy); + + }; + +} diff --git a/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/ImageFileResource.java b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/ImageFileResource.java new file mode 100644 index 0000000000..55eb1f92c0 --- /dev/null +++ b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/ImageFileResource.java @@ -0,0 +1,187 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.drawing.image; + +import org.eclipse.swt.graphics.Rectangle; + +import com.raytheon.uf.viz.core.DrawableImage; +import com.raytheon.uf.viz.core.DrawableLine; +import com.raytheon.uf.viz.core.IGraphicsTarget; +import com.raytheon.uf.viz.core.PixelCoverage; +import com.raytheon.uf.viz.core.drawables.IDescriptor; +import com.raytheon.uf.viz.core.drawables.IImage; +import com.raytheon.uf.viz.core.drawables.PaintProperties; +import com.raytheon.uf.viz.core.drawables.ext.ICanvasRenderingExtension; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.AbstractVizResource; +import com.raytheon.uf.viz.core.rsc.IResourceDataChanged.ChangeType; +import com.raytheon.uf.viz.core.rsc.LoadProperties; +import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability; +import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability; +import com.raytheon.uf.viz.core.rsc.capabilities.ImagingCapability; +import com.raytheon.uf.viz.drawing.image.EditRectangleInputHandler.EditRectangleTarget; +import com.vividsolutions.jts.geom.Coordinate; + +/** + * Resource for displaying a non geolocated image. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 15, 2014  2313     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ + +public class ImageFileResource extends + AbstractVizResource implements + EditRectangleTarget { + + private IImage image; + + private EditRectangleInputHandler inputHandler; + + private Rectangle canvasBounds; + + protected ImageFileResource(ImageFileResourceData resourceData, + LoadProperties loadProperties) { + super(resourceData, loadProperties); + inputHandler = new EditRectangleInputHandler(this); + } + + @Override + protected void initInternal(IGraphicsTarget target) throws VizException { + image = target.initializeRaster(new RenderedImageFileCallback( + resourceData.getFile())); + checkEditable(); + checkImagingProperties(); + } + + @Override + protected void paintInternal(IGraphicsTarget target, + PaintProperties paintProps) throws VizException { + canvasBounds = paintProps.getCanvasBounds(); + Rectangle rect = getRectangle(); + Coordinate ul = new Coordinate(rect.x, rect.y); + Coordinate ur = new Coordinate(rect.x + rect.width, rect.y); + Coordinate lr = new Coordinate(rect.x + rect.width, rect.y + + rect.height); + Coordinate ll = new Coordinate(rect.x, rect.y + rect.height); + PixelCoverage pc = new PixelCoverage(ul, ur, lr, ll); + + ICanvasRenderingExtension renderer = target + .getExtension(ICanvasRenderingExtension.class); + renderer.drawImages(paintProps, new DrawableImage(image, pc)); + + EditableCapability eCap = getCapability(EditableCapability.class); + if (eCap.isEditable()) { + DrawableLine box = new DrawableLine(); + ColorableCapability cCap = getCapability(ColorableCapability.class); + box.basics.color = cCap.getColor(); + box.width = 3.0f; + box.addPoint(ul.x, ul.y); + box.addPoint(ur.x, ur.y); + box.addPoint(lr.x, lr.y); + box.addPoint(ll.x, ll.y); + box.addPoint(ul.x, ul.y); + renderer.drawLines(paintProps, box); + } + } + + @Override + protected void disposeInternal() { + if (image != null) { + image.dispose(); + image = null; + } + inputHandler.disable(getResourceContainer()); + } + + @Override + protected void resourceDataChanged(ChangeType type, Object updateObject) { + super.resourceDataChanged(type, updateObject); + if (type == ChangeType.CAPABILITY) { + if (updateObject instanceof EditableCapability) { + checkEditable(); + } else if (updateObject instanceof ImagingCapability) { + checkImagingProperties(); + } + } + } + + @Override + public String getName() { + return resourceData.getFile().getName(); + } + + @Override + public Rectangle getRectangle() { + if (canvasBounds == null) { + return null; + } + int north = (int) (canvasBounds.y + resourceData.getNorth() + * canvasBounds.height / 100.0); + int east = (int) (canvasBounds.x + resourceData.getEast() + * canvasBounds.width / 100.0); + int south = (int) (canvasBounds.y + resourceData.getSouth() + * canvasBounds.height / 100.0); + int west = (int) (canvasBounds.x + resourceData.getWest() + * canvasBounds.width / 100.0); + return new Rectangle(west, north, east - west, south - north); + } + + @Override + public void resize(Rectangle rect) { + resourceData.setNorth((rect.y - canvasBounds.y) * 100.0 + / canvasBounds.height); + resourceData.setEast((rect.x + rect.width - canvasBounds.x) * 100.0 + / canvasBounds.width); + resourceData.setSouth((rect.y + rect.height - canvasBounds.y) * 100.0 + / canvasBounds.height); + resourceData.setWest((rect.x - canvasBounds.x) * 100.0 + / canvasBounds.width); + issueRefresh(); + } + + protected void checkEditable() { + EditableCapability eCap = getCapability(EditableCapability.class); + if (eCap.isEditable()) { + inputHandler.enable(getResourceContainer()); + } else { + inputHandler.disable(getResourceContainer()); + } + issueRefresh(); + } + + protected void checkImagingProperties() { + if (image != null) { + ImagingCapability iCap = getCapability(ImagingCapability.class); + image.setBrightness(iCap.getBrightness()); + image.setContrast(iCap.getContrast()); + } + } + +} diff --git a/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/ImageFileResourceData.java b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/ImageFileResourceData.java new file mode 100644 index 0000000000..88770a3aab --- /dev/null +++ b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/ImageFileResourceData.java @@ -0,0 +1,184 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.drawing.image; + +import java.io.File; + +import javax.annotation.Generated; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; + +import com.raytheon.uf.viz.core.drawables.IDescriptor; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.AbstractResourceData; +import com.raytheon.uf.viz.core.rsc.LoadProperties; + +/** + * Resource data for displaying a non geolocated image, contains an image file + * name and position. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 15, 2014  2313     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +@XmlAccessorType(XmlAccessType.NONE) +public class ImageFileResourceData extends AbstractResourceData { + + @XmlAttribute + private String fileName; + + @XmlAttribute + private double north = 0; + + @XmlAttribute + private double east = 100; + + @XmlAttribute + private double south = 100; + + @XmlAttribute + private double west = 0; + + + public ImageFileResourceData() { + super(); + } + + public ImageFileResourceData(String fileName) { + this(); + this.fileName = fileName; + } + + @Override + public ImageFileResource construct(LoadProperties loadProperties, + IDescriptor descriptor) throws VizException { + return new ImageFileResource(this, loadProperties); + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public double getNorth() { + return north; + } + + public void setNorth(double north) { + this.north = north; + } + + public double getEast() { + return east; + } + + public void setEast(double east) { + this.east = east; + } + + public double getSouth() { + return south; + } + + public void setSouth(double south) { + this.south = south; + } + + public double getWest() { + return west; + } + + public void setWest(double west) { + this.west = west; + } + + public File getFile() { + return new File(fileName); + } + + @Override + public void update(Object updateData) { + // Nothing updates this resource + } + + @Override + @Generated(value = "org.eclipse.jdt.ui.actions.GenerateHashCodeEqualsAction", comments = "3.8.2.v20130107-165834") + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(east); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + + ((fileName == null) ? 0 : fileName.hashCode()); + temp = Double.doubleToLongBits(north); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(south); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(west); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + @Generated(value = "org.eclipse.jdt.ui.actions.GenerateHashCodeEqualsAction", comments = "3.8.2.v20130107-165834") + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ImageFileResourceData other = (ImageFileResourceData) obj; + if (Double.doubleToLongBits(east) != Double + .doubleToLongBits(other.east)) + return false; + if (fileName == null) { + if (other.fileName != null) + return false; + } else if (!fileName.equals(other.fileName)) + return false; + if (Double.doubleToLongBits(north) != Double + .doubleToLongBits(other.north)) + return false; + if (Double.doubleToLongBits(south) != Double + .doubleToLongBits(other.south)) + return false; + if (Double.doubleToLongBits(west) != Double + .doubleToLongBits(other.west)) + return false; + return true; + } + + +} diff --git a/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/OpenImageFileAction.java b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/OpenImageFileAction.java new file mode 100644 index 0000000000..410ac5cce7 --- /dev/null +++ b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/OpenImageFileAction.java @@ -0,0 +1,178 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ + +package com.raytheon.uf.viz.drawing.image; + +import java.io.File; +import java.io.IOException; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.viz.core.IDisplayPaneContainer; +import com.raytheon.uf.viz.core.drawables.IDescriptor; +import com.raytheon.uf.viz.core.drawables.IRenderableDisplay; +import com.raytheon.uf.viz.core.exception.VizException; +import com.raytheon.uf.viz.core.rsc.LoadProperties; +import com.raytheon.uf.viz.core.rsc.RenderingOrderFactory.ResourceOrder; +import com.raytheon.uf.viz.core.rsc.ResourceProperties; +import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability; +import com.raytheon.viz.core.ColorUtil; +import com.raytheon.viz.ui.EditorUtil; + +/** + * + * Action for loading an image onto the screen. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 15, 2014  2313     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class OpenImageFileAction extends AbstractHandler { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(OpenImageFileAction.class); + + private static final String BACKGROUND = "Background"; + + @Override + public Object execute(ExecutionEvent event) { + IDisplayPaneContainer container = EditorUtil.getActiveVizContainer(); + if (container == null) { + return null; + } + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getShell(); + + FileDialog fd = new FileDialog(shell, SWT.OPEN); + fd.setText("Import Image"); + String[] suffixes = ImageIO.getReaderFileSuffixes(); + StringBuilder filter = new StringBuilder(suffixes.length * 7); + for (String suffix : suffixes) { + if (!suffix.isEmpty()) { + if (filter.length() != 0) { + filter.append(';'); + } + filter.append("*.").append(suffix); + } + } + fd.setFilterExtensions(new String[] { filter.toString() }); + fd.setFilterNames(new String[] { "All Images" }); + + if (fd.open() == null) { + return null; + } + + String fileName = fd.getFilterPath() + File.separator + + fd.getFileName(); + + IRenderableDisplay display = container.getActiveDisplayPane() + .getRenderableDisplay(); + IDescriptor desc = display.getDescriptor(); + ImageFileResourceData data = new ImageFileResourceData(fileName); + LoadProperties lProps = new LoadProperties(); + /* Get a new resource color */ + ColorableCapability cCap = lProps.getCapabilities().getCapability(data, + ColorableCapability.class); + RGB color = ColorUtil.getNewColor(desc); + cCap.setColor(color); + ResourceProperties rProps = new ResourceProperties(); + String importMode = event.getParameter("imageImportMode"); + if (BACKGROUND.equalsIgnoreCase(importMode)) { + /* Render as background */ + rProps.setRenderingOrder(ResourceOrder.LOWEST.value); + /* Fill the screen */ + data.setNorth(0); + data.setWest(0); + data.setSouth(100); + data.setEast(100); + } else { + /* Render as foreground */ + rProps.setRenderingOrder(ResourceOrder.HIGHEST.value); + /* Size the same as the image */ + Rectangle canvasBounds = display.getBounds(); + Rectangle imageBounds; + try { + imageBounds = getImageBounds(fileName); + } catch (IOException e) { + statusHandler.handle(Priority.PROBLEM, "Error Loading Image.", + e); + return null; + } + data.setNorth(0); + data.setWest(0); + data.setEast(imageBounds.width * 100.0 / canvasBounds.width); + data.setSouth(imageBounds.height * 100.0 / canvasBounds.height); + } + try { + ImageFileResource rsc = data.construct(lProps, desc); + desc.getResourceList().add(rsc, rProps); + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, "Error Loading Image.", e); + } + return null; + } + + protected static Rectangle getImageBounds(String fileName) + throws IOException { + Rectangle imageBounds = null; + ImageInputStream in = ImageIO + .createImageInputStream(new File(fileName)); + ImageReader reader = null; + try { + Iterator readers = ImageIO.getImageReaders(in); + if (readers.hasNext()) { + reader = readers.next(); + reader.setInput(in); + imageBounds = new Rectangle(0, 0, reader.getWidth(0), + reader.getHeight(0)); + } + } finally { + in.close(); + if (reader != null) { + reader.dispose(); + } + } + return imageBounds; + } +} diff --git a/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/RenderedImageFileCallback.java b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/RenderedImageFileCallback.java new file mode 100644 index 0000000000..f3fc3ff2cf --- /dev/null +++ b/cave/com.raytheon.uf.viz.drawing/src/com/raytheon/uf/viz/drawing/image/RenderedImageFileCallback.java @@ -0,0 +1,66 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.viz.drawing.image; + +import java.awt.image.RenderedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import com.raytheon.uf.viz.core.data.IRenderedImageCallback; +import com.raytheon.uf.viz.core.exception.VizException; + +/** + * + * Callback which loads an image from a file when it is needed for rendering. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 15, 2014  2313     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class RenderedImageFileCallback implements + IRenderedImageCallback { + + private final File file; + + public RenderedImageFileCallback(File file) { + super(); + this.file = file; + } + + @Override + public RenderedImage getImage() throws VizException { + try { + return ImageIO.read(file); + } catch (IOException e) { + throw new VizException(e); + } + } +} \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/KmlCanvasRenderingExtension.java b/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/KmlCanvasRenderingExtension.java index 3f9bdee22d..53829d10bc 100644 --- a/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/KmlCanvasRenderingExtension.java +++ b/cave/com.raytheon.uf.viz.kml.export/src/com/raytheon/uf/viz/kml/export/graphics/ext/KmlCanvasRenderingExtension.java @@ -21,6 +21,7 @@ package com.raytheon.uf.viz.kml.export.graphics.ext; import java.awt.Color; import java.awt.Graphics; +import java.awt.Image; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; @@ -34,12 +35,17 @@ import java.util.Map; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.core.DrawableColorMap; +import com.raytheon.uf.viz.core.DrawableImage; import com.raytheon.uf.viz.core.DrawableLine; import com.raytheon.uf.viz.core.DrawableString; import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment; import com.raytheon.uf.viz.core.IGraphicsTarget.TextStyle; import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment; +import com.raytheon.uf.viz.core.PixelCoverage; import com.raytheon.uf.viz.core.drawables.PaintProperties; import com.raytheon.uf.viz.core.drawables.ext.GraphicsExtension; import com.raytheon.uf.viz.core.drawables.ext.ICanvasRenderingExtension; @@ -48,6 +54,7 @@ import com.raytheon.uf.viz.kml.export.KmlFeatureGenerator; import com.raytheon.uf.viz.kml.export.graphics.KmlFont; import com.raytheon.uf.viz.kml.export.graphics.KmlGraphicsTarget; import com.raytheon.uf.viz.kml.export.io.KmlOutputManager; +import com.vividsolutions.jts.geom.Coordinate; import de.micromata.opengis.kml.v_2_2_0.ScreenOverlay; import de.micromata.opengis.kml.v_2_2_0.Units; @@ -60,9 +67,10 @@ import de.micromata.opengis.kml.v_2_2_0.Vec2; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jun 26, 2012 bsteffen Initial creation + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Jun 26, 2012 bsteffen Initial creation + * Jan 14, 2013 2313 bsteffen Add image rendering * * * @@ -74,6 +82,9 @@ public class KmlCanvasRenderingExtension extends GraphicsExtension implements ICanvasRenderingExtension { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(KmlCanvasRenderingExtension.class); + @Override public void drawStrings(PaintProperties paintProps, DrawableString... parameters) throws VizException { @@ -92,6 +103,13 @@ public class KmlCanvasRenderingExtension extends getGenerator(paintProps).addColorMaps(colorMap); } + @Override + public void drawImages(PaintProperties paintProps, DrawableImage... images) + throws VizException { + getGenerator(paintProps).addImages(images); + + } + protected Generator getGenerator(PaintProperties paintProps) { for (KmlFeatureGenerator generator : target.getGenerators()) { if (generator instanceof Generator) { @@ -152,6 +170,10 @@ public class KmlCanvasRenderingExtension extends this.objects.addAll(Arrays.asList(colorMaps)); } + public void addImages(DrawableImage... colorMaps) { + this.objects.addAll(Arrays.asList(colorMaps)); + } + @Override public void addFeature(KmlOutputManager outputManager) { Map boundsMap = new IdentityHashMap(); @@ -181,16 +203,18 @@ public class KmlCanvasRenderingExtension extends Vec2 screenxy = overlay.createAndSetScreenXY(); screenxy.withXunits(Units.FRACTION).withYunits(Units.FRACTION); - // This is fairly complex placement code but it produces rather - // nice results on any size of display. Basically if something - // is flush against either the left or right of the screen it - // ends up anchored on that side, if some is smack in the center - // than the anchor point is in the middle of both the overlay - // and the display. Now if an object is offcenter to the left or - // right than the anchor point moves in the correct direction in - // proportion to how far off center it is, its hard to explain - // without a picture but at the end of the day it produces a - // nice result. + /* + * This is fairly complex placement code but it produces rather + * nice results on any size of display. Basically if something + * is flush against either the left or right of the screen it + * ends up anchored on that side, if some is smack in the center + * than the anchor point is in the middle of both the overlay + * and the display. Now if an object is offcenter to the left or + * right than the anchor point moves in the correct direction in + * proportion to how far off center it is, its hard to explain + * without a picture but at the end of the day it produces a + * nice result. + */ double leftFrac = bounds.getMinX() / canvasBounds.width; double rightFrac = 1.0 - bounds.getMaxX() / canvasBounds.width; if (leftFrac < rightFrac) { @@ -210,8 +234,10 @@ public class KmlCanvasRenderingExtension extends } else { overlayxy.setY(botFrac / topFrac / 2); } - // all this 1.0 - stuff is because the math is mostly assuming 0 - // is up and 1.0 is down but kml expects the opposite. + /* + * all this 1.0 - stuff is because the math is mostly assuming 0 + * is up and 1.0 is down but kml expects the opposite. + */ double y = 1.0 - (bounds.getY() + bounds.getHeight() * (1.0 - overlayxy.getY())) @@ -230,8 +256,10 @@ public class KmlCanvasRenderingExtension extends Rectangle2D b = it.next(); if (b.intersects(bounds)) { if (!b.contains(bounds)) { - // need to recheck the larger rectangle of b for any new - // intersections. + /* + * need to recheck the larger rectangle of b for any new + * intersections. + */ it.remove(); b.add(bounds); addBounds(allBounds, b); @@ -250,6 +278,8 @@ public class KmlCanvasRenderingExtension extends drawLines(graphics, imageBounds, (DrawableLine) object); } else if (object instanceof DrawableColorMap) { drawColorMap(graphics, imageBounds, (DrawableColorMap) object); + } else if (object instanceof DrawableImage) { + drawImage(graphics, imageBounds, (DrawableImage) object); } } @@ -330,6 +360,25 @@ public class KmlCanvasRenderingExtension extends } } + protected void drawImage(Graphics graphics, Rectangle2D imageBounds, + DrawableImage image) { + KmlRasterImage kmlImage = (KmlRasterImage) image.getImage(); + PixelCoverage coverage = image.getCoverage(); + Coordinate ul = coverage.getUl(); + Coordinate lr = coverage.getLr(); + try { + Image toDraw = (Image) kmlImage.getImage(); + int x = (int) (ul.x - imageBounds.getX()); + int y = (int) (ul.y - imageBounds.getY()); + int w = (int) (lr.x - ul.x); + int h = (int) (lr.y - ul.y); + graphics.drawImage(toDraw, x, y, w, h, null); + } catch (VizException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + } + } + protected void setColor(Graphics graphics, RGB color) { graphics.setColor(new Color(color.red, color.green, color.blue)); } @@ -341,6 +390,8 @@ public class KmlCanvasRenderingExtension extends return getLineBounds((DrawableLine) object); } else if (object instanceof DrawableColorMap) { return getColorMapBounds((DrawableColorMap) object); + } else if (object instanceof DrawableImage) { + return getImageBounds((DrawableImage) object); } return null; } @@ -354,8 +405,10 @@ public class KmlCanvasRenderingExtension extends bounds.add(point[0], point[1]); } } - // add a buffer region to ensure we have room for wide lines on - // the edge. + /* + * add a buffer region to ensure we have room for wide lines on the + * edge. + */ bounds.add(bounds.getMinX() - line.width, bounds.getMinY() - line.width); bounds.add(bounds.getMaxX() + line.width, bounds.getMaxY() @@ -407,6 +460,13 @@ public class KmlCanvasRenderingExtension extends colorMap.extent.getMinY(), colorMap.extent.getWidth(), colorMap.extent.getHeight()); } + + protected Rectangle2D getImageBounds(DrawableImage image) { + PixelCoverage coverage = image.getCoverage(); + Coordinate ul = coverage.getUl(); + Coordinate lr = coverage.getLr(); + return new Rectangle2D.Double(ul.x, ul.y, lr.x - ul.x, lr.y - ul.y); + } } } diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java index a817741abb..92b99a3029 100644 --- a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java @@ -64,7 +64,6 @@ import com.raytheon.viz.core.imagery.ImageCombiner.IImageCombinerListener; import com.raytheon.viz.ui.VizWorkbenchManager; import com.raytheon.viz.ui.dialogs.ColormapComp.IColormapCompChangeListener; import com.raytheon.viz.ui.dialogs.colordialog.ColorEditDialog; -import com.raytheon.viz.ui.editor.AbstractEditor; import com.raytheon.viz.ui.editor.IMultiPaneEditor; /** @@ -72,18 +71,23 @@ import com.raytheon.viz.ui.editor.IMultiPaneEditor; * *
  * SOFTWARE HISTORY
- * Date         Ticket#     Engineer    Description
- * ------------ ----------  ----------- --------------------------
- * Nov 26, 2006             chammack    Initial Creation.
- * Jul 10, 2008 #980        lvenable    Changed to a SWT dialog to correct a problem
- *                                      caused by a JFace/shell issue.  I also rearranged
- *                                      the controls a bit, used labels instead of text
- *                                      controls since the text is not being edited, changed
- *                                      sliders to scales, added tooltiptext to buttons to
- *                                      show full colormap names, and added comments & Javadoc.
- * Aug 20, 2008				dglazesk	Updated for the new ColorMap interface
- * Feb 10, 2011 #7842       bkowal      set caveStyle for dialog to INDEPENDENT SHELL
- * Oct 17, 2012 #1229       rferrel     Make dialog non-blocking.
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- -----------------------------------------
+ * Nov 26, 2006           chammack    Initial Creation.
+ * Jul 10, 2008  980      lvenable    Changed to a SWT dialog to correct a
+ *                                    problem caused by a JFace/shell issue.  I
+ *                                    also rearranged the controls a bit, used
+ *                                    labels instead of text controls since the
+ *                                    text is not being edited, changed sliders
+ *                                    to scales, added tooltiptext to buttons to
+ *                                    show full colormap names, and added
+ *                                    comments & Javadoc.
+ * Aug 20, 2008	          dglazesk    Updated for the new ColorMap interface
+ * Feb 10, 2011  7842     bkowal      set caveStyle for dialog to INDEPENDENT
+ *                                    SHELL
+ * Oct 17, 2012  1229     rferrel     Make dialog non-blocking.
+ * Jan 15, 2015  2313     bsteffen    Disable color map selection when
+ *                                    ColorMapCapability is not present.
  * 
  * 
* @@ -707,26 +711,6 @@ public class ImagingDialog extends CaveSWTDialog implements contrastScale.setEnabled(true); interpolationChk.setEnabled(true); - final ColorMapCapability cmcap = topResource - .getCapability(ColorMapCapability.class); - String currentCMap = "Not Selected"; - if (cmcap.getColorMapParameters() != null - && cmcap.getColorMapParameters().getColorMap() != null) { - currentCMap = cmcap.getColorMapParameters().getColorMap() - .getName(); - if (currentCMap == null) { - currentCMap = ""; - } - } - topColormapComp.setCap(cmcap); - topColormapComp.setParams(cmcap.getColorMapParameters()); - if (currentCMap != null) { - if (currentCMap.isEmpty()) { - currentCMap = UNSAVED_CMAP_DISPLAY_NAME; - } - topColormapComp.getCMapButton().setText(currentCMap); - } - String topResourceName = topResource.getName(); if (editables.size() > 1) { if (blended) { @@ -742,8 +726,35 @@ public class ImagingDialog extends CaveSWTDialog implements } else { topColorMapButton.setToolTipText(null); } - topColorMapButton.setText("Edit " + topResourceName); + if (topResource.hasCapability(ColorMapCapability.class)) { + final ColorMapCapability cmcap = topResource + .getCapability(ColorMapCapability.class); + String currentCMap = "Not Selected"; + if (cmcap.getColorMapParameters() != null + && cmcap.getColorMapParameters().getColorMap() != null) { + currentCMap = cmcap.getColorMapParameters().getColorMap() + .getName(); + if (currentCMap == null) { + currentCMap = ""; + } + } + topColormapComp.setCap(cmcap); + topColormapComp.setParams(cmcap.getColorMapParameters()); + if (currentCMap.isEmpty()) { + currentCMap = UNSAVED_CMAP_DISPLAY_NAME; + } + topColormapComp.getCMapButton().setText(currentCMap); + topColorMapButton.setText("Edit " + topResourceName); + } else { + topColorMapButton.setText(topResourceName + + " is not color mapped."); + topColormapComp.getCMapButton().setText("Not Selected"); + topColorMapButton.setEnabled(false); + topColormapComp.getCMapButton().setEnabled(false); + interpolationChk.setEnabled(false); + interpolationChk.setSelection(false); + } ImagingCapability imgCap = topResource .getCapability(ImagingCapability.class); brightnessScale @@ -804,12 +815,10 @@ public class ImagingDialog extends CaveSWTDialog implements bottomColormapComp.setCap(bottomCap); bottomColormapComp.setParams(bottomCap.getColorMapParameters()); - if (currentCMap != null) { - if (currentCMap.isEmpty()) { - currentCMap = UNSAVED_CMAP_DISPLAY_NAME; - } - bottomColormapComp.getCMapButton().setText(currentCMap); + if (currentCMap.isEmpty()) { + currentCMap = UNSAVED_CMAP_DISPLAY_NAME; } + bottomColormapComp.getCMapButton().setText(currentCMap); String bottomResourceName = bottomResource.getName(); if (editables.size() > 1) { @@ -925,7 +934,7 @@ public class ImagingDialog extends CaveSWTDialog implements @Override public void editorChanged(IDisplayPaneContainer container) { IDisplayPaneContainer oldEditor = currentEditor; - currentEditor = (AbstractEditor) container; + currentEditor = container; refreshComponents(); setupListeners(oldEditor, currentEditor); }