]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.graphviz.ui/src/org/simantics/graphviz/ui/GraphvizComponent.java
6ba556da09d65f1076bb4108e9e2fb35dcca190d
[simantics/platform.git] / bundles / org.simantics.graphviz.ui / src / org / simantics / graphviz / ui / GraphvizComponent.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.graphviz.ui;
13
14 import java.awt.Canvas;
15 import java.awt.Frame;
16 import java.awt.event.WindowAdapter;
17 import java.awt.event.WindowEvent;
18 import java.io.File;
19 import java.io.IOException;
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.util.concurrent.atomic.AtomicBoolean;
23
24 import javax.swing.SwingUtilities;
25
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.awt.SWT_AWT;
28 import org.eclipse.swt.widgets.Composite;
29 import org.eclipse.swt.widgets.Control;
30 import org.eclipse.swt.widgets.Shell;
31 import org.simantics.graphviz.Graph;
32 import org.simantics.graphviz.Graphs;
33 import org.simantics.graphviz.continuation.Computation;
34 import org.simantics.graphviz.continuation.Continuation;
35 import org.simantics.graphviz.drawable.GraphDrawable;
36 import org.simantics.graphviz.drawable.ViewerCanvas;
37 import org.simantics.utils.ui.SWTUtils;
38
39 public class GraphvizComponent extends Composite {
40
41     Canvas canvas;
42     GraphDrawable drawable;
43     Graph graph;
44     AtomicBoolean initialized = new AtomicBoolean(false);
45
46     public GraphvizComponent(Composite parent, int style) {
47         super(parent, style | SWT.EMBEDDED | SWT.NO_BACKGROUND);
48
49         final Frame frame = SWT_AWT.new_Frame(this);
50         workaroundJava7FocusProblem(frame);
51         
52         SwingUtilities.invokeLater(new Runnable() {
53
54             @Override
55             public void run() {
56                 try {
57                     drawable = new GraphDrawable();
58                     canvas = new ViewerCanvas(drawable);
59                     frame.add(canvas);
60                 } finally {
61                     synchronized (initialized) {
62                         initialized.set(true);
63                         initialized.notifyAll();
64                     }
65                 }
66             }
67
68         });
69     }
70     
71     private void workaroundJava7FocusProblem(Frame frame) {
72         String ver = System.getProperty("java.version");
73         if (ver.startsWith("1.7") || ver.startsWith("1.8")) {
74             try {
75                 frame.addWindowListener(new Java7FocusFixListener(this, frame));
76             } catch (SecurityException e) {
77                 e.printStackTrace();
78                 //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
79             } catch (NoSuchMethodException e) {
80                 e.printStackTrace();
81                 //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
82             }
83         }
84     }
85
86     static class Java7FocusFixListener extends WindowAdapter {
87
88         Method shellSetActiveControl;
89         Control control;
90         Frame frame;
91
92         public Java7FocusFixListener(Control control, Frame frame) throws NoSuchMethodException, SecurityException {
93             this.shellSetActiveControl = Shell.class.getDeclaredMethod("setActiveControl", Control.class);
94             this.frame = frame;
95             this.control = control;
96         }
97
98         @Override
99         public void windowActivated(WindowEvent e) {
100             SWTUtils.asyncExec(control, new Runnable() {
101                 @Override
102                 public void run() {
103                     if (control.isDisposed())
104                         return;
105                     if (control.getDisplay().getFocusControl() == control) {
106                         try {
107                             boolean accessible = shellSetActiveControl.isAccessible();
108                             if (!accessible)
109                                 shellSetActiveControl.setAccessible(true);
110                             shellSetActiveControl.invoke(control.getShell(), control);
111                             if (!accessible)
112                                 shellSetActiveControl.setAccessible(false);
113                         } catch (SecurityException e) {
114                             e.printStackTrace();
115                             //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
116                         } catch (IllegalArgumentException e) {
117                             e.printStackTrace();
118                             //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
119                         } catch (IllegalAccessException e) {
120                             e.printStackTrace();
121                             //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
122                         } catch (InvocationTargetException e) {
123                             e.getCause().printStackTrace();
124                             //Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
125                         }
126                     }
127                 }
128             });
129         }
130
131     }
132
133     public void waitUntilInitialized() {
134         try {
135             synchronized (initialized) {
136                 while (!initialized.get())
137                     initialized.wait();
138             }
139         } catch (InterruptedException e) {
140             throw new Error("GraphvizComponent AWT population interrupted for class " + this, e);
141         }
142     }
143
144     /**
145      * Sets a new graph to be drawn. This operation may take a while. It can
146      * be called from any thread. Automatically redraws the component.
147      * @param graph
148      */
149     public void setGraph(Graph graph) {
150         setGraph(graph, "dot");
151     }
152
153     /**
154      * Sets a new graph to be drawn. This operation may take a while. It can
155      * be called from any thread. Automatically redraws the component.
156      * @param graph
157      */
158     public Computation<Graph> setGraph(Graph graph, String algorithm) {
159         waitUntilInitialized();
160         Computation<Graph> computation = drawable.setGraph(graph, algorithm);
161         computation.addContinuation(new Continuation<Graph>() {
162
163             @Override
164             public void succeeded(Graph result) {
165                 if (isDisposed())
166                     return;
167                 
168                 fit();
169             }
170
171             @Override
172             public void failed(Exception exception) {
173             }
174
175         });
176         return computation;
177     }
178
179     /**
180      * Fits the content of the canvas to the component.
181      * Can be called from any thread.
182      */
183     public void fit() {
184         ((ViewerCanvas)canvas).fit();
185         getDisplay().asyncExec(new Runnable() {
186
187             @Override
188             public void run() {
189                 if (!isDisposed())
190                     redraw();
191             }
192
193         });
194         SwingUtilities.invokeLater(new Runnable() {
195
196             @Override
197             public void run() {
198                 canvas.repaint();
199             }
200
201         });
202
203
204     }
205
206     public void requestFocus() {
207         if(canvas != null)
208             canvas.requestFocus();
209     }
210     
211     public void save(File file) throws IOException {
212         if (drawable == null) {
213                         throw new IOException("Nothing to save");
214                 }
215                 Graph graph = drawable.getGraph();
216                 String algo = drawable.getAlgorithm();
217         
218                 String type = getExtension(file);
219                 if (type == null)
220                         return;
221                 Graphs.createImage(graph, algo, type, file);
222     }
223     
224     public String[] getFileExtensions() {
225         return new String[]{"*.svg","*.dot","*.eps", "*.jpg", "*.jpeg","*.pdf","*.png","*.ps"};
226     }
227     
228     public String[] getFileNames() {
229         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"};
230     }
231     
232     public static String getExtension(File file) {
233                 String filename = file.getName();
234                 int index = filename.lastIndexOf(".");
235                 if (index < 0)
236                         return null;
237                 return filename.substring(index+1).toLowerCase();
238         }
239
240 }