X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.image.ui%2Fsrc%2Forg%2Fsimantics%2Fimage%2Fui%2Feditor%2FImageEditor.java;h=a9ab8aef6041b8287c468a6656628c5024c46496;hp=d8dbe08846570d1e2f48c0758881ef5c80845577;hb=47269fe0acb894f346810417d950a1ab59cdc0ea;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.image.ui/src/org/simantics/image/ui/editor/ImageEditor.java b/bundles/org.simantics.image.ui/src/org/simantics/image/ui/editor/ImageEditor.java index d8dbe0884..a9ab8aef6 100644 --- a/bundles/org.simantics.image.ui/src/org/simantics/image/ui/editor/ImageEditor.java +++ b/bundles/org.simantics.image.ui/src/org/simantics/image/ui/editor/ImageEditor.java @@ -1,395 +1,395 @@ -/******************************************************************************* - * Copyright (c) 2007- VTT Technical Research Centre of Finland. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.image.ui.editor; - -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.DirectColorModel; -import java.awt.image.IndexColorModel; -import java.awt.image.WritableRaster; -import java.io.ByteArrayInputStream; - -import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.resource.LocalResourceManager; -import org.eclipse.jface.resource.ResourceManager; -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTError; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.PaletteData; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Canvas; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.simantics.Simantics; -import org.simantics.databoard.Bindings; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.common.request.ParametrizedRead; -import org.simantics.db.common.request.ResourceRead; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.request.combinations.Combinators; -import org.simantics.image2.ontology.ImageResource; -import org.simantics.scenegraph.ScenegraphUtils; -import org.simantics.scenegraph.utils.GeometryUtils; -import org.simantics.ui.workbench.IResourceEditorInput; -import org.simantics.ui.workbench.ResourceEditorPart; -import org.simantics.ui.workbench.editor.input.InputValidationCombinators; -import org.simantics.utils.ui.ErrorLogger; -import org.simantics.utils.ui.LayoutUtils; - -import com.kitfox.svg.SVGDiagram; -import com.kitfox.svg.SVGException; -import com.kitfox.svg.SVGUniverse; - -/** - * @author Tuukka Lehtonen - */ -public class ImageEditor extends ResourceEditorPart { - - public static final String EDITOR_ID = "org.simantics.wiki.ui.image.editor"; - - protected boolean disposed = false; - - protected Image image; - protected SVGDiagram svgDiagram; - private ResourceManager resourceManager; - private Canvas canvas; - - private double zoomLevel = 1; - private Point2D previousTranslate = new Point2D.Double(); - private Point2D translate = new Point2D.Double(); - private boolean zoomToFit = false; - private SVGUniverse svgUniverse = new SVGUniverse(); - - static ImageData convertToSWT(BufferedImage bufferedImage) { - if (bufferedImage.getColorModel() instanceof DirectColorModel) { - DirectColorModel colorModel = (DirectColorModel) bufferedImage - .getColorModel(); - PaletteData palette = new PaletteData(colorModel.getRedMask(), - colorModel.getGreenMask(), colorModel.getBlueMask()); - ImageData data = new ImageData(bufferedImage.getWidth(), - bufferedImage.getHeight(), colorModel.getPixelSize(), - palette); - WritableRaster raster = bufferedImage.getRaster(); - int[] pixelArray = new int[4]; - for (int y = 0; y < data.height; y++) { - for (int x = 0; x < data.width; x++) { - raster.getPixel(x, y, pixelArray); - int pixel = palette.getPixel(new RGB(pixelArray[0], - pixelArray[1], pixelArray[2])); - data.setPixel(x, y, pixel); - } - } - return data; - } else if (bufferedImage.getColorModel() instanceof IndexColorModel) { - IndexColorModel colorModel = (IndexColorModel) bufferedImage - .getColorModel(); - int size = colorModel.getMapSize(); - byte[] reds = new byte[size]; - byte[] greens = new byte[size]; - byte[] blues = new byte[size]; - colorModel.getReds(reds); - colorModel.getGreens(greens); - colorModel.getBlues(blues); - RGB[] rgbs = new RGB[size]; - for (int i = 0; i < rgbs.length; i++) { - rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, - blues[i] & 0xFF); - } - PaletteData palette = new PaletteData(rgbs); - ImageData data = new ImageData(bufferedImage.getWidth(), - bufferedImage.getHeight(), colorModel.getPixelSize(), - palette); - data.transparentPixel = colorModel.getTransparentPixel(); - WritableRaster raster = bufferedImage.getRaster(); - int[] pixelArray = new int[1]; - for (int y = 0; y < data.height; y++) { - for (int x = 0; x < data.width; x++) { - raster.getPixel(x, y, pixelArray); - data.setPixel(x, y, pixelArray[0]); - } - } - return data; - } - return null; - } - - ParametrizedRead INPUT_VALIDATOR = - Combinators.compose( - InputValidationCombinators.hasURI(), - InputValidationCombinators.extractInputResource() - ); - - @Override - protected ParametrizedRead getInputValidator() { - return INPUT_VALIDATOR; - } - - @Override - public void createPartControl(final Composite parent) { - this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent); - - parent.setLayout(LayoutUtils.createNoBorderGridLayout(1)); - - canvas = new Canvas(parent, SWT.DOUBLE_BUFFERED); - canvas.setBackground(resourceManager.createColor(new RGB(255, 255, 255))); - GridDataFactory.fillDefaults().grab(true, true).applyTo(canvas); - - canvas.addListener(SWT.Paint, new Listener() { - @Override - public void handleEvent(Event event) { - if (svgDiagram != null) { - Rectangle2D r = svgDiagram.getViewRect(); - if (r.isEmpty()) - return; - - // FIXME: this is unsafe, renders unnecessarily large - // buffered images when only control size is ultimately needed. - - AffineTransform tr = AffineTransform.getScaleInstance(zoomLevel, zoomLevel); - tr.translate(translate.getX(), translate.getY()); - try { - BufferedImage bi = ScenegraphUtils.paintSVG(svgDiagram, tr, 0f); - Image img = new Image(parent.getDisplay(), convertToSWT(bi)); - drawImage(event.gc, img, false); - img.dispose(); - } catch (SVGException e) { - } - } else if (image != null) { - drawImage(event.gc, image, true); - } - } - private void drawImage(GC gc, Image image, boolean fitToCanvas) { - Rectangle r = image.getBounds(); - if (r.isEmpty()) - return; - - Point destSize = canvas.getSize(); - int xSpace = destSize.x - r.width; - int ySpace = destSize.y - r.height; - boolean fitsX = xSpace >= 0; - boolean fitsY = ySpace >= 0; - boolean fitsCanvas = fitsX && fitsY; - - // if the image is larger than the canvas, zoom it to fit - if ((!fitsCanvas && fitToCanvas) || zoomToFit) { - gc.setAntialias(SWT.ON); - - // Zoom to fit propertionally - int leftMargin = 0; - int topMargin = 0; - if (xSpace > ySpace) { - double yr = (double) destSize.y / r.height; - double xo = (int)(r.width * yr); - leftMargin = (int) Math.round(((destSize.x - r.width) + (r.width - xo)) * 0.5); - gc.drawImage(image, 0, 0, r.width, r.height, leftMargin, topMargin, (int) xo, destSize.y); - } else { - double xr = (double) destSize.x / r.width; - double yo = (int)(r.height * xr); - topMargin = (int) Math.round(((destSize.y - r.height) + (r.height - yo)) * 0.5); - gc.drawImage(image, 0, 0, r.width, r.height, leftMargin, topMargin, destSize.x, (int) yo); - } - } else { - if (!fitsCanvas) { - int srcX = fitsX ? 0 : (int) Math.round(-xSpace * 0.5); - int srcY = fitsY ? 0 : (int) Math.round(-ySpace * 0.5); - int srcW = fitsX ? r.width : r.width + xSpace; - int srcH = fitsY ? r.height : r.height + ySpace; - int destX = fitsX ? (int) Math.round(xSpace * 0.5) : 0; - int destY = fitsY ? (int) Math.round(ySpace * 0.5) : 0; - int destW = fitsX ? r.width : destSize.x; - int destH = fitsY ? r.height : destSize.y; - gc.drawImage(image, srcX, srcY, srcW, srcH, destX, destY, destW, destH); - } else { - // Center on the canvas. - int leftMargin = (int) Math.round((destSize.x - r.width) * 0.5); - int topMargin = (int) Math.round((destSize.y - r.height) * 0.5); - gc.drawImage(image, 0, 0, r.width, r.height, leftMargin, topMargin, r.width, r.height); - } - } - } - }); - canvas.addListener(SWT.MouseDoubleClick, new Listener() { - @Override - public void handleEvent(Event event) { - zoomToFit ^= true; - canvas.redraw(); - } - }); - - // Mouse tracking support - Listener listener = new Listener() { - boolean pan = false; - Point panStart = new Point(0, 0); - @Override - public void handleEvent(Event e) { - switch (e.type) { - case SWT.MouseUp: - if (e.button == 3) { - pan = false; - previousTranslate.setLocation(translate); - } - break; - case SWT.MouseDown: - if (e.button == 3) { - panStart.x = e.x; - panStart.y = e.y; - pan = true; - previousTranslate.setLocation(translate); - } - break; - case SWT.MouseMove: - if (pan) { - int dx = e.x - panStart.x; - int dy = e.y - panStart.y; - translate.setLocation( - previousTranslate.getX() + dx / zoomLevel, - previousTranslate.getY() + dy / zoomLevel); - canvas.redraw(); - } - break; - case SWT.MouseVerticalWheel: - double scroll = Math.min(0.9, -e.count / 20.0); - double z = 1 - scroll; - zoomLevel = limitScaleFactor(zoomLevel, z); - canvas.redraw(); - break; - } - } - private double limitScaleFactor(double zoomLevel, double scaleFactor) { - double inLimit = 200.0; - double outLimit = 10; - - AffineTransform view = AffineTransform.getScaleInstance(zoomLevel, zoomLevel); - double currentScale = GeometryUtils.getScale(view) * 100.0; - double newScale = currentScale * scaleFactor; - - if (newScale > currentScale && newScale > inLimit) { - if (currentScale < inLimit) - scaleFactor = inLimit / currentScale; - else - return inLimit / 100.0; - } else if (newScale < currentScale && newScale < outLimit) { - if (currentScale > outLimit) - scaleFactor = outLimit / currentScale; - else - return outLimit / 100.0; - } - return zoomLevel * scaleFactor; - } - }; - canvas.addListener(SWT.MouseUp, listener); - canvas.addListener(SWT.MouseDown, listener); - canvas.addListener(SWT.MouseMove, listener); - canvas.addListener(SWT.MouseWheel, listener); - - // Start tracking editor input validity. - activateValidation(); - - loadAndTrackInput(); - } - - private void loadAndTrackInput() { - final Resource input = getInputResource(); - Simantics.getSession().asyncRequest(new ResourceRead(input) { - @Override - public Object perform(ReadGraph graph) throws DatabaseException { - ImageResource img = ImageResource.getInstance(graph); - if (graph.isInstanceOf(input, img.SvgImage)) { - String text = graph.getPossibleValue(input, Bindings.STRING); - return text; - } else if (graph.isInstanceOf(input, img.Image)) { - byte data[] = graph.getPossibleValue(input, Bindings.BYTE_ARRAY); - return data; - } - return null; - } - }, new org.simantics.db.procedure.Listener() { - @Override - public void execute(Object result) { - if (result instanceof String) { - // svg text - try { - svgDiagram = ScenegraphUtils.loadSVGDiagram(svgUniverse, (String) result); - scheduleRedraw(); - } catch (SVGException e) { - ErrorLogger.defaultLogError(e); - } - } else if (result instanceof byte[]) { - // bitmap image data - Display display = canvas.getDisplay(); - if (!display.isDisposed()) { - try { - image = new Image(canvas.getDisplay(), new ByteArrayInputStream((byte[]) result)); - scheduleRedraw(); - } catch (SWTException e) { - ErrorLogger.defaultLogError(e); - } catch (SWTError e) { - ErrorLogger.defaultLogError(e); - } - } - } - } - private void scheduleRedraw() { - Display d = canvas.getDisplay(); - if (!d.isDisposed()) - d.asyncExec(new Runnable() { - @Override - public void run() { - if (!canvas.isDisposed()) - canvas.redraw(); - } - }); - } - @Override - public void exception(Throwable t) { - ErrorLogger.defaultLogError(t); - } - @Override - public boolean isDisposed() { - return disposed; - } - }); - } - - @Override - public void dispose() { - disposed = true; - if (image != null) { - image.dispose(); - image = null; - } - svgUniverse.clear(); - } - - @Override - public void setFocus() { - if (canvas != null) - canvas.setFocus(); - } - - @SuppressWarnings("rawtypes") - @Override - public Object getAdapter(Class adapter) { - return null; - } - -} +/******************************************************************************* + * Copyright (c) 2007- VTT Technical Research Centre of Finland. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.image.ui.editor; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.DirectColorModel; +import java.awt.image.IndexColorModel; +import java.awt.image.WritableRaster; +import java.io.ByteArrayInputStream; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.resource.ResourceManager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTError; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.PaletteData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.common.request.ParametrizedRead; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.request.combinations.Combinators; +import org.simantics.image2.ontology.ImageResource; +import org.simantics.scenegraph.ScenegraphUtils; +import org.simantics.scenegraph.utils.GeometryUtils; +import org.simantics.ui.workbench.IResourceEditorInput; +import org.simantics.ui.workbench.ResourceEditorPart; +import org.simantics.ui.workbench.editor.input.InputValidationCombinators; +import org.simantics.utils.ui.ErrorLogger; +import org.simantics.utils.ui.LayoutUtils; + +import com.kitfox.svg.SVGDiagram; +import com.kitfox.svg.SVGException; +import com.kitfox.svg.SVGUniverse; + +/** + * @author Tuukka Lehtonen + */ +public class ImageEditor extends ResourceEditorPart { + + public static final String EDITOR_ID = "org.simantics.wiki.ui.image.editor"; //$NON-NLS-1$ + + protected boolean disposed = false; + + protected Image image; + protected SVGDiagram svgDiagram; + private ResourceManager resourceManager; + private Canvas canvas; + + private double zoomLevel = 1; + private Point2D previousTranslate = new Point2D.Double(); + private Point2D translate = new Point2D.Double(); + private boolean zoomToFit = false; + private SVGUniverse svgUniverse = new SVGUniverse(); + + static ImageData convertToSWT(BufferedImage bufferedImage) { + if (bufferedImage.getColorModel() instanceof DirectColorModel) { + DirectColorModel colorModel = (DirectColorModel) bufferedImage + .getColorModel(); + PaletteData palette = new PaletteData(colorModel.getRedMask(), + colorModel.getGreenMask(), colorModel.getBlueMask()); + ImageData data = new ImageData(bufferedImage.getWidth(), + bufferedImage.getHeight(), colorModel.getPixelSize(), + palette); + WritableRaster raster = bufferedImage.getRaster(); + int[] pixelArray = new int[4]; + for (int y = 0; y < data.height; y++) { + for (int x = 0; x < data.width; x++) { + raster.getPixel(x, y, pixelArray); + int pixel = palette.getPixel(new RGB(pixelArray[0], + pixelArray[1], pixelArray[2])); + data.setPixel(x, y, pixel); + } + } + return data; + } else if (bufferedImage.getColorModel() instanceof IndexColorModel) { + IndexColorModel colorModel = (IndexColorModel) bufferedImage + .getColorModel(); + int size = colorModel.getMapSize(); + byte[] reds = new byte[size]; + byte[] greens = new byte[size]; + byte[] blues = new byte[size]; + colorModel.getReds(reds); + colorModel.getGreens(greens); + colorModel.getBlues(blues); + RGB[] rgbs = new RGB[size]; + for (int i = 0; i < rgbs.length; i++) { + rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, + blues[i] & 0xFF); + } + PaletteData palette = new PaletteData(rgbs); + ImageData data = new ImageData(bufferedImage.getWidth(), + bufferedImage.getHeight(), colorModel.getPixelSize(), + palette); + data.transparentPixel = colorModel.getTransparentPixel(); + WritableRaster raster = bufferedImage.getRaster(); + int[] pixelArray = new int[1]; + for (int y = 0; y < data.height; y++) { + for (int x = 0; x < data.width; x++) { + raster.getPixel(x, y, pixelArray); + data.setPixel(x, y, pixelArray[0]); + } + } + return data; + } + return null; + } + + ParametrizedRead INPUT_VALIDATOR = + Combinators.compose( + InputValidationCombinators.hasURI(), + InputValidationCombinators.extractInputResource() + ); + + @Override + protected ParametrizedRead getInputValidator() { + return INPUT_VALIDATOR; + } + + @Override + public void createPartControl(final Composite parent) { + this.resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent); + + parent.setLayout(LayoutUtils.createNoBorderGridLayout(1)); + + canvas = new Canvas(parent, SWT.DOUBLE_BUFFERED); + canvas.setBackground(resourceManager.createColor(new RGB(255, 255, 255))); + GridDataFactory.fillDefaults().grab(true, true).applyTo(canvas); + + canvas.addListener(SWT.Paint, new Listener() { + @Override + public void handleEvent(Event event) { + if (svgDiagram != null) { + Rectangle2D r = svgDiagram.getViewRect(); + if (r.isEmpty()) + return; + + // FIXME: this is unsafe, renders unnecessarily large + // buffered images when only control size is ultimately needed. + + AffineTransform tr = AffineTransform.getScaleInstance(zoomLevel, zoomLevel); + tr.translate(translate.getX(), translate.getY()); + try { + BufferedImage bi = ScenegraphUtils.paintSVG(svgDiagram, tr, 0f); + Image img = new Image(parent.getDisplay(), convertToSWT(bi)); + drawImage(event.gc, img, false); + img.dispose(); + } catch (SVGException e) { + } + } else if (image != null) { + drawImage(event.gc, image, true); + } + } + private void drawImage(GC gc, Image image, boolean fitToCanvas) { + Rectangle r = image.getBounds(); + if (r.isEmpty()) + return; + + Point destSize = canvas.getSize(); + int xSpace = destSize.x - r.width; + int ySpace = destSize.y - r.height; + boolean fitsX = xSpace >= 0; + boolean fitsY = ySpace >= 0; + boolean fitsCanvas = fitsX && fitsY; + + // if the image is larger than the canvas, zoom it to fit + if ((!fitsCanvas && fitToCanvas) || zoomToFit) { + gc.setAntialias(SWT.ON); + + // Zoom to fit propertionally + int leftMargin = 0; + int topMargin = 0; + if (xSpace > ySpace) { + double yr = (double) destSize.y / r.height; + double xo = (int)(r.width * yr); + leftMargin = (int) Math.round(((destSize.x - r.width) + (r.width - xo)) * 0.5); + gc.drawImage(image, 0, 0, r.width, r.height, leftMargin, topMargin, (int) xo, destSize.y); + } else { + double xr = (double) destSize.x / r.width; + double yo = (int)(r.height * xr); + topMargin = (int) Math.round(((destSize.y - r.height) + (r.height - yo)) * 0.5); + gc.drawImage(image, 0, 0, r.width, r.height, leftMargin, topMargin, destSize.x, (int) yo); + } + } else { + if (!fitsCanvas) { + int srcX = fitsX ? 0 : (int) Math.round(-xSpace * 0.5); + int srcY = fitsY ? 0 : (int) Math.round(-ySpace * 0.5); + int srcW = fitsX ? r.width : r.width + xSpace; + int srcH = fitsY ? r.height : r.height + ySpace; + int destX = fitsX ? (int) Math.round(xSpace * 0.5) : 0; + int destY = fitsY ? (int) Math.round(ySpace * 0.5) : 0; + int destW = fitsX ? r.width : destSize.x; + int destH = fitsY ? r.height : destSize.y; + gc.drawImage(image, srcX, srcY, srcW, srcH, destX, destY, destW, destH); + } else { + // Center on the canvas. + int leftMargin = (int) Math.round((destSize.x - r.width) * 0.5); + int topMargin = (int) Math.round((destSize.y - r.height) * 0.5); + gc.drawImage(image, 0, 0, r.width, r.height, leftMargin, topMargin, r.width, r.height); + } + } + } + }); + canvas.addListener(SWT.MouseDoubleClick, new Listener() { + @Override + public void handleEvent(Event event) { + zoomToFit ^= true; + canvas.redraw(); + } + }); + + // Mouse tracking support + Listener listener = new Listener() { + boolean pan = false; + Point panStart = new Point(0, 0); + @Override + public void handleEvent(Event e) { + switch (e.type) { + case SWT.MouseUp: + if (e.button == 3) { + pan = false; + previousTranslate.setLocation(translate); + } + break; + case SWT.MouseDown: + if (e.button == 3) { + panStart.x = e.x; + panStart.y = e.y; + pan = true; + previousTranslate.setLocation(translate); + } + break; + case SWT.MouseMove: + if (pan) { + int dx = e.x - panStart.x; + int dy = e.y - panStart.y; + translate.setLocation( + previousTranslate.getX() + dx / zoomLevel, + previousTranslate.getY() + dy / zoomLevel); + canvas.redraw(); + } + break; + case SWT.MouseVerticalWheel: + double scroll = Math.min(0.9, -e.count / 20.0); + double z = 1 - scroll; + zoomLevel = limitScaleFactor(zoomLevel, z); + canvas.redraw(); + break; + } + } + private double limitScaleFactor(double zoomLevel, double scaleFactor) { + double inLimit = 200.0; + double outLimit = 10; + + AffineTransform view = AffineTransform.getScaleInstance(zoomLevel, zoomLevel); + double currentScale = GeometryUtils.getScale(view) * 100.0; + double newScale = currentScale * scaleFactor; + + if (newScale > currentScale && newScale > inLimit) { + if (currentScale < inLimit) + scaleFactor = inLimit / currentScale; + else + return inLimit / 100.0; + } else if (newScale < currentScale && newScale < outLimit) { + if (currentScale > outLimit) + scaleFactor = outLimit / currentScale; + else + return outLimit / 100.0; + } + return zoomLevel * scaleFactor; + } + }; + canvas.addListener(SWT.MouseUp, listener); + canvas.addListener(SWT.MouseDown, listener); + canvas.addListener(SWT.MouseMove, listener); + canvas.addListener(SWT.MouseWheel, listener); + + // Start tracking editor input validity. + activateValidation(); + + loadAndTrackInput(); + } + + private void loadAndTrackInput() { + final Resource input = getInputResource(); + Simantics.getSession().asyncRequest(new ResourceRead(input) { + @Override + public Object perform(ReadGraph graph) throws DatabaseException { + ImageResource img = ImageResource.getInstance(graph); + if (graph.isInstanceOf(input, img.SvgImage)) { + String text = graph.getPossibleValue(input, Bindings.STRING); + return text; + } else if (graph.isInstanceOf(input, img.Image)) { + byte data[] = graph.getPossibleValue(input, Bindings.BYTE_ARRAY); + return data; + } + return null; + } + }, new org.simantics.db.procedure.Listener() { + @Override + public void execute(Object result) { + if (result instanceof String) { + // svg text + try { + svgDiagram = ScenegraphUtils.loadSVGDiagram(svgUniverse, (String) result); + scheduleRedraw(); + } catch (SVGException e) { + ErrorLogger.defaultLogError(e); + } + } else if (result instanceof byte[]) { + // bitmap image data + Display display = canvas.getDisplay(); + if (!display.isDisposed()) { + try { + image = new Image(canvas.getDisplay(), new ByteArrayInputStream((byte[]) result)); + scheduleRedraw(); + } catch (SWTException e) { + ErrorLogger.defaultLogError(e); + } catch (SWTError e) { + ErrorLogger.defaultLogError(e); + } + } + } + } + private void scheduleRedraw() { + Display d = canvas.getDisplay(); + if (!d.isDisposed()) + d.asyncExec(new Runnable() { + @Override + public void run() { + if (!canvas.isDisposed()) + canvas.redraw(); + } + }); + } + @Override + public void exception(Throwable t) { + ErrorLogger.defaultLogError(t); + } + @Override + public boolean isDisposed() { + return disposed; + } + }); + } + + @Override + public void dispose() { + disposed = true; + if (image != null) { + image.dispose(); + image = null; + } + svgUniverse.clear(); + } + + @Override + public void setFocus() { + if (canvas != null) + canvas.setFocus(); + } + + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Class adapter) { + return null; + } + +}