-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.graphviz.drawable;\r
-\r
-import java.awt.Canvas;\r
-import java.awt.Color;\r
-import java.awt.Graphics;\r
-import java.awt.Graphics2D;\r
-import java.awt.Image;\r
-import java.awt.Point;\r
-import java.awt.RenderingHints;\r
-import java.awt.event.ActionEvent;\r
-import java.awt.event.ComponentAdapter;\r
-import java.awt.event.ComponentEvent;\r
-import java.awt.event.KeyAdapter;\r
-import java.awt.event.KeyEvent;\r
-import java.awt.event.MouseAdapter;\r
-import java.awt.event.MouseEvent;\r
-import java.awt.event.MouseWheelEvent;\r
-import java.awt.event.MouseWheelListener;\r
-import java.awt.event.WindowAdapter;\r
-import java.awt.event.WindowEvent;\r
-import java.awt.geom.AffineTransform;\r
-import java.awt.geom.Rectangle2D;\r
-import java.io.File;\r
-import java.io.IOException;\r
-\r
-import javax.swing.AbstractAction;\r
-import javax.swing.JFileChooser;\r
-import javax.swing.JFrame;\r
-import javax.swing.JMenu;\r
-import javax.swing.JMenuBar;\r
-import javax.swing.JMenuItem;\r
-import javax.swing.JOptionPane;\r
-import javax.swing.filechooser.FileFilter;\r
-import javax.swing.filechooser.FileView;\r
-\r
-import org.simantics.graphviz.Graph;\r
-import org.simantics.graphviz.Graphs;\r
-\r
-/**\r
- * A stand alone frame that shows and makes it\r
- * possible to navigate a given Drawable.\r
- * \r
- * @author Hannu Niemistö\r
- */\r
-public class JViewer extends JFrame {\r
- private static final long serialVersionUID = 3022682167091092801L;\r
- Drawable drawable;\r
- ViewerCanvas canvas = new ViewerCanvas();\r
- \r
- class ViewerCanvas extends Canvas {\r
- private static final long serialVersionUID = -5330090168115281754L;\r
- AffineTransform transform;\r
- Point prev;\r
- Image im;\r
- \r
- ViewerCanvas() { \r
- setBackground(Color.WHITE); \r
- addKeyListener(new KeyAdapter() {\r
- \r
- @Override\r
- public void keyPressed(KeyEvent e) {\r
- if(e.getKeyChar()=='1') {\r
- //System.out.println("a");\r
- canvas.fit();\r
- canvas.repaint();\r
- }\r
- else if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {\r
- JViewer.this.dispose();\r
- }\r
- }\r
- \r
- });\r
- addMouseListener(new MouseAdapter() {\r
- \r
- @Override\r
- public void mousePressed(MouseEvent e) {\r
- prev = e.getPoint();\r
- } \r
- });\r
- addMouseMotionListener(new MouseAdapter() {\r
- @Override\r
- public void mouseDragged(MouseEvent e) {\r
- Point cur = e.getPoint();\r
- if (prev == null)\r
- prev = cur;\r
- double deltaX = cur.getX()-prev.getX();\r
- double deltaY = cur.getY()-prev.getY();\r
- transform.preConcatenate(AffineTransform.getTranslateInstance(deltaX, deltaY)); \r
- repaint();\r
- prev = cur;\r
- }\r
- });\r
- addMouseWheelListener(new MouseWheelListener() {\r
-\r
- @Override\r
- public void mouseWheelMoved(MouseWheelEvent e) {\r
- if(transform != null) {\r
- double scale = Math.exp(-0.1*e.getUnitsToScroll());\r
- Point p = e.getPoint();\r
- AffineTransform mod = new AffineTransform();\r
- mod.translate(p.getX(), p.getY());\r
- mod.scale(scale, scale);\r
- mod.translate(-p.getX(), -p.getY());\r
- transform.preConcatenate(mod); \r
- repaint();\r
- }\r
- }\r
- \r
- });\r
- addComponentListener(new ComponentAdapter() {\r
- @Override\r
- public void componentResized(ComponentEvent e) {\r
- im = createImage(getWidth(), getHeight());\r
- repaint();\r
- }\r
- });\r
- }\r
- \r
- private void fit() {\r
- Rectangle2D bounds = drawable.getBounds();\r
- \r
- Rectangle2D container = getBounds();\r
- double scale = container == null ? 1 : Math.min(\r
- container.getWidth() / bounds.getWidth(), \r
- container.getHeight() / bounds.getHeight());\r
- \r
- transform = new AffineTransform(\r
- scale, 0.0,\r
- 0.0, scale,\r
- container.getX() + container.getWidth() * 0.5 - bounds.getCenterX() * scale,\r
- container.getY() + container.getHeight() * 0.5 - bounds.getCenterY() * scale\r
- );\r
- }\r
- \r
- @Override\r
- public void paint(Graphics _g) {\r
- if(im == null)\r
- im = createImage(getWidth(), getHeight());\r
- Graphics2D g = (Graphics2D)im.getGraphics();\r
- \r
- g.clearRect(0, 0, im.getWidth(null), im.getHeight(null));\r
- \r
- g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
- g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);\r
- g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);\r
- \r
- if(transform == null)\r
- fit();\r
- g.setTransform(transform);\r
- \r
- drawable.draw(g, null);\r
- \r
- _g.drawImage(im, 0, 0, this);\r
- }\r
- \r
- @Override\r
- public void update(Graphics g) {\r
- paint(g);\r
- }\r
- \r
- }\r
- \r
- public JViewer(Drawable _drawable) {\r
- this.drawable = _drawable;\r
- setTitle("Image viewer");\r
- setSize(1024, 768);\r
- addWindowListener(new WindowAdapter(){\r
- public void windowClosing(WindowEvent we){\r
- dispose();\r
- } \r
- @Override\r
- public void windowActivated(WindowEvent e) {\r
- repaint(0, 0, getWidth(), getHeight()); \r
- }\r
- @Override\r
- public void windowGainedFocus(WindowEvent e) {\r
- requestFocus();\r
- }\r
- });\r
- getContentPane().add(canvas);\r
- \r
- JMenuBar menuBar = new JMenuBar();\r
- \r
- JMenu menu = new JMenu("File");\r
- menuBar.add(menu);\r
- \r
- JMenuItem saveItem = new JMenuItem(new SaveAsAction());\r
- JMenuItem exitItem = new JMenuItem(new ExitAction());\r
- menu.add(saveItem);\r
- menu.addSeparator();\r
- menu.add(exitItem);\r
- setJMenuBar(menuBar);\r
- \r
- setVisible(true);\r
- }\r
- \r
- public class ExitAction extends AbstractAction {\r
-\r
- private static final long serialVersionUID = 5680421985865931443L;\r
-\r
- public ExitAction() {\r
- super("Exit");\r
- }\r
- \r
- @Override\r
- public void actionPerformed(ActionEvent e) {\r
- JViewer.this.setVisible(false);\r
- JViewer.this.dispose();\r
- }\r
- }\r
- \r
- public class SaveAsAction extends AbstractAction {\r
- \r
- private static final long serialVersionUID = 4627419396805081199L;\r
-\r
- public SaveAsAction() {\r
- super("Save as");\r
- }\r
- \r
- @Override\r
- public void actionPerformed(ActionEvent e) {\r
- if (!(drawable instanceof GraphDrawable)) {\r
- JOptionPane.showMessageDialog(JViewer.this, "File saving not supported", "Error",JOptionPane.ERROR_MESSAGE);\r
- return;\r
- }\r
- GraphDrawable gdraw = (GraphDrawable)drawable;\r
- Graph graph = gdraw.getGraph();\r
- String algo = gdraw.getAlgorithm();\r
- JFileChooser chooser = new JFileChooser();\r
- chooser.addChoosableFileFilter(new DotImageFilter());\r
- chooser.setAcceptAllFileFilterUsed(false);\r
- chooser.setFileView(new DotImageFileView());\r
- int returnval = chooser.showSaveDialog(JViewer.this);\r
- if (returnval == JFileChooser.APPROVE_OPTION) {\r
- try {\r
- File file = chooser.getSelectedFile();\r
- \r
- String type = getExtension(file);\r
- if (type == null)\r
- return;\r
- Graphs.createImage(graph, algo, type, file);\r
- } catch (IOException err) {\r
- err.printStackTrace();\r
- JOptionPane.showMessageDialog(JViewer.this, "File saving failed: " + err.getMessage(), "Error",JOptionPane.ERROR_MESSAGE);\r
- }\r
- }\r
- }\r
- }\r
- \r
- public static String getExtension(File file) {\r
- String filename = file.getName();\r
- int index = filename.lastIndexOf(".");\r
- if (index < 0)\r
- return null;\r
- return filename.substring(index+1).toLowerCase();\r
- }\r
- \r
- public class DotImageFilter extends FileFilter {\r
- @Override\r
- public boolean accept(File f) {\r
- if (f.isDirectory())\r
- return true;\r
- String ext = getExtension(f);\r
- if (ext == null)\r
- return false;\r
- if (ext.equals("svg"))\r
- return true;\r
- if (ext.equals("dot"))\r
- return true;\r
- if (ext.equals("eps"))\r
- return true;\r
- if (ext.equals("jpg"))\r
- return true;\r
- if (ext.equals("jpeg"))\r
- return true;\r
- if (ext.equals("pdf"))\r
- return true;\r
- if (ext.equals("png"))\r
- return true;\r
- if (ext.equals("ps"))\r
- return true;\r
- return false;\r
- }\r
- \r
- @Override\r
- public String getDescription() {\r
- return "Image files";\r
- }\r
- }\r
- \r
- public class DotImageFileView extends FileView {\r
- @Override\r
- public String getTypeDescription(File f) {\r
- String ext = getExtension(f);\r
- if (ext == null)\r
- return null;\r
- if (ext.equals("svg"))\r
- return "Scalable Vector Graphics Image";\r
- if (ext.equals("dot"))\r
- return "DOT Image";\r
- if (ext.equals("eps"))\r
- return "Encapsulated PostScript Image";\r
- if (ext.equals("jpg"))\r
- return "JPG Image";\r
- if (ext.equals("jpeg"))\r
- return "JPG Image";\r
- if (ext.equals("pdf"))\r
- return "Portable Document Format Image";\r
- if (ext.equals("png"))\r
- return "Portable Network Graphics Image";\r
- if (ext.equals("ps"))\r
- return "PostScript Image";\r
- return null;\r
- }\r
- }\r
- \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * 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.graphviz.drawable;
+
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.swing.AbstractAction;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+import javax.swing.filechooser.FileFilter;
+import javax.swing.filechooser.FileView;
+
+import org.simantics.graphviz.Graph;
+import org.simantics.graphviz.Graphs;
+
+/**
+ * A stand alone frame that shows and makes it
+ * possible to navigate a given Drawable.
+ *
+ * @author Hannu Niemist�
+ */
+public class JViewer extends JFrame {
+ private static final HashMap<String, JViewer> VIEWER_MAP = new HashMap<String, JViewer>();
+
+ private static final long serialVersionUID = 3022682167091092801L;
+ Drawable drawable;
+ ViewerCanvas canvas = new ViewerCanvas();
+
+ private String windowName;
+
+ class ViewerCanvas extends Canvas {
+ private static final long serialVersionUID = -5330090168115281754L;
+ AffineTransform transform;
+ Point prev;
+ Image im;
+
+ ViewerCanvas() {
+ setBackground(Color.WHITE);
+ addKeyListener(new KeyAdapter() {
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if(e.getKeyChar()=='1') {
+ //System.out.println("a");
+ canvas.fit();
+ canvas.repaint();
+ }
+ else if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ JViewer.this.dispose();
+ }
+ }
+
+ });
+ addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ prev = e.getPoint();
+ }
+ });
+ addMouseMotionListener(new MouseAdapter() {
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ if(transform == null)
+ return;
+ Point cur = e.getPoint();
+ if (prev == null)
+ prev = cur;
+ double deltaX = cur.getX()-prev.getX();
+ double deltaY = cur.getY()-prev.getY();
+ transform.preConcatenate(AffineTransform.getTranslateInstance(deltaX, deltaY));
+ repaint();
+ prev = cur;
+ }
+ });
+ addMouseWheelListener(new MouseWheelListener() {
+
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent e) {
+ if(transform == null)
+ return;
+ double scale = Math.exp(-0.1*e.getUnitsToScroll());
+ Point p = e.getPoint();
+ AffineTransform mod = new AffineTransform();
+ mod.translate(p.getX(), p.getY());
+ mod.scale(scale, scale);
+ mod.translate(-p.getX(), -p.getY());
+ transform.preConcatenate(mod);
+ repaint();
+ }
+
+ });
+ addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ im = createImage(getWidth(), getHeight());
+ repaint();
+ }
+ });
+ }
+
+ private void fit() {
+ Rectangle2D bounds = drawable.getBounds();
+ Rectangle2D container = getBounds();
+
+ if(bounds == null || container == null)
+ return;
+
+ double scale = container == null ? 1 : Math.min(
+ container.getWidth() / bounds.getWidth(),
+ container.getHeight() / bounds.getHeight());
+
+ transform = new AffineTransform(
+ scale, 0.0,
+ 0.0, scale,
+ container.getX() + container.getWidth() * 0.5 - bounds.getCenterX() * scale,
+ container.getY() + container.getHeight() * 0.5 - bounds.getCenterY() * scale
+ );
+ }
+
+ @Override
+ public void paint(Graphics _g) {
+ if(im == null)
+ im = createImage(getWidth(), getHeight());
+ Graphics2D g = (Graphics2D)im.getGraphics();
+
+ g.clearRect(0, 0, im.getWidth(null), im.getHeight(null));
+
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+
+ if(transform == null) {
+ fit();
+ if(transform == null) {
+ g.setTransform(new AffineTransform());
+ g.setColor(Color.BLACK);
+ g.drawString("No data available yet", 20f, 20f);
+ return;
+ }
+ }
+ g.setTransform(transform);
+
+ drawable.draw(g, null);
+
+ _g.drawImage(im, 0, 0, this);
+ }
+
+ @Override
+ public void update(Graphics g) {
+ paint(g);
+ }
+
+ }
+
+ public JViewer(Drawable _drawable) {
+ this.drawable = _drawable;
+ setTitle("Image viewer");
+ setSize(1024, 768);
+ addWindowListener(new WindowAdapter(){
+ public void windowClosing(WindowEvent we){
+ dispose();
+ }
+ @Override
+ public void windowActivated(WindowEvent e) {
+ repaint(0, 0, getWidth(), getHeight());
+ }
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ requestFocus();
+ }
+ });
+ getContentPane().add(canvas);
+
+ JMenuBar menuBar = new JMenuBar();
+
+ JMenu menu = new JMenu("File");
+ menuBar.add(menu);
+
+ JMenuItem saveItem = new JMenuItem(new SaveAsAction());
+ JMenuItem exitItem = new JMenuItem(new ExitAction());
+ menu.add(saveItem);
+ menu.addSeparator();
+ menu.add(exitItem);
+ setJMenuBar(menuBar);
+
+ setVisible(true);
+ }
+
+ public void updateDrawable(Drawable drawable) {
+ this.drawable = drawable;
+ canvas.fit();
+ canvas.repaint();
+ }
+
+ public class ExitAction extends AbstractAction {
+
+ private static final long serialVersionUID = 5680421985865931443L;
+
+ public ExitAction() {
+ super("Exit");
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JViewer.this.setVisible(false);
+ JViewer.this.dispose();
+ }
+ }
+
+ public class SaveAsAction extends AbstractAction {
+
+ private static final long serialVersionUID = 4627419396805081199L;
+
+ public SaveAsAction() {
+ super("Save as");
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (!(drawable instanceof GraphDrawable)) {
+ JOptionPane.showMessageDialog(JViewer.this, "File saving not supported", "Error",JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ GraphDrawable gdraw = (GraphDrawable)drawable;
+ Graph graph = gdraw.getGraph();
+ String algo = gdraw.getAlgorithm();
+ JFileChooser chooser = new JFileChooser();
+ chooser.addChoosableFileFilter(new DotImageFilter());
+ chooser.setAcceptAllFileFilterUsed(false);
+ chooser.setFileView(new DotImageFileView());
+ int returnval = chooser.showSaveDialog(JViewer.this);
+ if (returnval == JFileChooser.APPROVE_OPTION) {
+ try {
+ File file = chooser.getSelectedFile();
+
+ String type = getExtension(file);
+ if (type == null)
+ return;
+ Graphs.createImage(graph, algo, type, file);
+ } catch (IOException err) {
+ err.printStackTrace();
+ JOptionPane.showMessageDialog(JViewer.this, "File saving failed: " + err.getMessage(), "Error",JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ }
+
+ public static String getExtension(File file) {
+ String filename = file.getName();
+ int index = filename.lastIndexOf(".");
+ if (index < 0)
+ return null;
+ return filename.substring(index+1).toLowerCase();
+ }
+
+ public class DotImageFilter extends FileFilter {
+ @Override
+ public boolean accept(File f) {
+ if (f.isDirectory())
+ return true;
+ String ext = getExtension(f);
+ if (ext == null)
+ return false;
+ if (ext.equals("svg"))
+ return true;
+ if (ext.equals("dot"))
+ return true;
+ if (ext.equals("eps"))
+ return true;
+ if (ext.equals("jpg"))
+ return true;
+ if (ext.equals("jpeg"))
+ return true;
+ if (ext.equals("pdf"))
+ return true;
+ if (ext.equals("png"))
+ return true;
+ if (ext.equals("ps"))
+ return true;
+ return false;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Image files";
+ }
+ }
+
+ public class DotImageFileView extends FileView {
+ @Override
+ public String getTypeDescription(File f) {
+ String ext = getExtension(f);
+ if (ext == null)
+ return null;
+ if (ext.equals("svg"))
+ return "Scalable Vector Graphics Image";
+ if (ext.equals("dot"))
+ return "DOT Image";
+ if (ext.equals("eps"))
+ return "Encapsulated PostScript Image";
+ if (ext.equals("jpg"))
+ return "JPG Image";
+ if (ext.equals("jpeg"))
+ return "JPG Image";
+ if (ext.equals("pdf"))
+ return "Portable Document Format Image";
+ if (ext.equals("png"))
+ return "Portable Network Graphics Image";
+ if (ext.equals("ps"))
+ return "PostScript Image";
+ return null;
+ }
+ }
+
+ public static void getOrCreateViewer(String windowName, GraphDrawable graphDrawable) {
+ JViewer viewer = VIEWER_MAP.get(windowName);
+ if(viewer == null) {
+ viewer = new JViewer(graphDrawable);
+ viewer.setTitle(windowName);
+ viewer.windowName = windowName;
+ VIEWER_MAP.put(windowName, viewer);
+ viewer.toFront();
+ }
+ else {
+ viewer.updateDrawable(graphDrawable);
+ viewer.toFront();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ if(windowName != null)
+ VIEWER_MAP.remove(windowName);
+ super.dispose();
+ }
+}