/******************************************************************************* * 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.ui; import java.awt.Canvas; import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.SwingUtilities; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.simantics.graphviz.Graph; import org.simantics.graphviz.Graphs; import org.simantics.graphviz.continuation.Computation; import org.simantics.graphviz.continuation.Continuation; import org.simantics.graphviz.drawable.GraphDrawable; import org.simantics.graphviz.drawable.ViewerCanvas; import org.simantics.utils.ui.SWTUtils; public class GraphvizComponent extends Composite { Canvas canvas; GraphDrawable drawable; Graph graph; AtomicBoolean initialized = new AtomicBoolean(false); public GraphvizComponent(Composite parent, int style) { super(parent, style | SWT.EMBEDDED | SWT.NO_BACKGROUND); final Frame frame = SWT_AWT.new_Frame(this); workaroundJava7FocusProblem(frame); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { drawable = new GraphDrawable(); canvas = new ViewerCanvas(drawable); frame.add(canvas); } finally { synchronized (initialized) { initialized.set(true); initialized.notifyAll(); } } } }); } private void workaroundJava7FocusProblem(Frame frame) { String ver = System.getProperty("java.version"); if (ver.startsWith("1.7") || ver.startsWith("1.8")) { try { frame.addWindowListener(new Java7FocusFixListener(this, frame)); } catch (SecurityException e) { e.printStackTrace(); //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } catch (NoSuchMethodException e) { e.printStackTrace(); //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } } } static class Java7FocusFixListener extends WindowAdapter { Method shellSetActiveControl; Control control; Frame frame; public Java7FocusFixListener(Control control, Frame frame) throws NoSuchMethodException, SecurityException { this.shellSetActiveControl = Shell.class.getDeclaredMethod("setActiveControl", Control.class); this.frame = frame; this.control = control; } @Override public void windowActivated(WindowEvent e) { SWTUtils.asyncExec(control, new Runnable() { @Override public void run() { if (control.isDisposed()) return; if (control.getDisplay().getFocusControl() == control) { try { boolean accessible = shellSetActiveControl.isAccessible(); if (!accessible) shellSetActiveControl.setAccessible(true); shellSetActiveControl.invoke(control.getShell(), control); if (!accessible) shellSetActiveControl.setAccessible(false); } catch (SecurityException e) { e.printStackTrace(); //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } catch (IllegalArgumentException e) { e.printStackTrace(); //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } catch (IllegalAccessException e) { e.printStackTrace(); //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } catch (InvocationTargetException e) { e.getCause().printStackTrace(); //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } } } }); } } public void waitUntilInitialized() { try { synchronized (initialized) { while (!initialized.get()) initialized.wait(); } } catch (InterruptedException e) { throw new Error("GraphvizComponent AWT population interrupted for class " + this, e); } } /** * Sets a new graph to be drawn. This operation may take a while. It can * be called from any thread. Automatically redraws the component. * @param graph */ public void setGraph(Graph graph) { setGraph(graph, "dot"); } /** * Sets a new graph to be drawn. This operation may take a while. It can * be called from any thread. Automatically redraws the component. * @param graph */ public Computation setGraph(Graph graph, String algorithm) { waitUntilInitialized(); Computation computation = drawable.setGraph(graph, algorithm); computation.addContinuation(new Continuation() { @Override public void succeeded(Graph result) { if (isDisposed()) return; fit(); } @Override public void failed(Exception exception) { } }); return computation; } /** * Fits the content of the canvas to the component. * Can be called from any thread. */ public void fit() { ((ViewerCanvas)canvas).fit(); getDisplay().asyncExec(new Runnable() { @Override public void run() { if (!isDisposed()) redraw(); } }); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { canvas.repaint(); } }); } public void requestFocus() { if(canvas != null) canvas.requestFocus(); } public void save(File file) throws IOException { if (drawable == null) { throw new IOException("Nothing to save"); } Graph graph = drawable.getGraph(); String algo = drawable.getAlgorithm(); String type = getExtension(file); if (type == null) return; Graphs.createImage(graph, algo, type, file); } public String[] getFileExtensions() { return new String[]{"*.svg","*.dot","*.eps", "*.jpg", "*.jpeg","*.pdf","*.png","*.ps"}; } public String[] getFileNames() { return new String[]{"Scalable Vector Graphics Image", "DOT Image", "Encapsulated PostScript Image","JPG Image","JPG Image","Portable Document Format Image","Portable Network Graphics Image","PostScript Image"}; } 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(); } }