]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorSupport.java
Remove usage of deprecated SimanticsUI-methods
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / workbench / ResourceEditorSupport.java
index f649bb53874d8586c44fc64a899bb22cd3b2b1a9..3597804d8f83164637e8f0b5e60e44c9879d25c2 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2013 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
- *     Semantum Oy - issue #4384\r
- *******************************************************************************/\r
-package org.simantics.ui.workbench;\r
-\r
-import org.eclipse.core.runtime.IAdaptable;\r
-import org.eclipse.ui.IEditorInput;\r
-import org.eclipse.ui.IEditorPart;\r
-import org.eclipse.ui.PartInitException;\r
-import org.eclipse.ui.PlatformUI;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.common.procedure.adapter.ListenerAdapter;\r
-import org.simantics.db.common.request.ParametrizedRead;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.event.ChangeEvent;\r
-import org.simantics.db.event.ChangeListener;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.management.ISessionContext;\r
-import org.simantics.db.management.ISessionContextProvider;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.db.service.GraphChangeListenerSupport;\r
-import org.simantics.ui.SimanticsUI;\r
-import org.simantics.utils.datastructures.map.Tuple;\r
-import org.simantics.utils.ui.ExceptionUtils;\r
-import org.simantics.utils.ui.SWTUtils;\r
-import org.simantics.utils.ui.workbench.WorkbenchUtils;\r
-\r
-/**\r
- * A helper class for easing the attachment of a Simantics database session to\r
- * an editor part.\r
- * \r
- * It handles the life-cycle of {@link IResourceEditorInput} inputs. It will\r
- * listen to graph database changes through {@link ChangeListener} and calls\r
- * {@link IResourceEditorInput#update(org.simantics.db.ReadGraph)}.\r
- * \r
- * Works with any IEditorPart but is only really useful with ones that have\r
- * resource inputs.\r
- * \r
- * @author Tuukka Lehtonen\r
- */\r
-public class ResourceEditorSupport implements IAdaptable, ChangeListener {\r
-\r
-    private IEditorPart                             editorPart;\r
-\r
-    private ChangeListener                          editorPartChangeListener;\r
-\r
-    private ISessionContext                         sessionContext;\r
-\r
-    // Just a cache to make sure that getSession doesn't NPE.\r
-    private Session                                 session;\r
-\r
-    ParametrizedRead<IResourceEditorInput, Boolean> inputValidator;\r
-\r
-    private InputListener                           inputListener;\r
-\r
-    public ResourceEditorSupport(IEditorPart editorPart) throws PartInitException {\r
-        this(editorPart, null);\r
-    }\r
-\r
-    public ResourceEditorSupport(IEditorPart editorPart, ParametrizedRead<IResourceEditorInput, Boolean> inputValidator) throws PartInitException {\r
-        this.editorPart = editorPart;\r
-        this.editorPartChangeListener = getChangeListener(editorPart);\r
-        this.inputValidator = inputValidator;\r
-\r
-        initSession();\r
-\r
-        IResourceEditorInput input = getResourceInput(editorPart);\r
-        if (input == null)\r
-            throw new PartInitException("Editor input must be an IResourceEditorInput, got " + editorPart.getEditorInput());\r
-\r
-        try {\r
-            input.init(this);\r
-        } catch (DatabaseException e) {\r
-            throw new PartInitException("Failed to initialize " + input, e);\r
-        }\r
-    }\r
-\r
-    private ISessionContext initSession() throws PartInitException {\r
-        if (sessionContext == null) {\r
-            ISessionContextProvider provider = SimanticsUI.getSessionContextProvider();\r
-            ISessionContext sc = provider.getSessionContext();\r
-            if (sc == null)\r
-                throw new PartInitException("active database session context is null");\r
-\r
-            sessionContext = sc;\r
-            session = sc.getSession();\r
-\r
-            if (editorPartChangeListener != null) {\r
-                GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class);\r
-                support.addListener(this);\r
-            }\r
-        }\r
-        return sessionContext;\r
-    }\r
-\r
-    private ChangeListener getChangeListener(IEditorPart part) {\r
-        if (part instanceof ChangeListener)\r
-            return (ChangeListener) part;\r
-        ChangeListener cl = (ChangeListener) part.getAdapter(ChangeListener.class);\r
-        return cl;\r
-    }\r
-\r
-    private static IResourceEditorInput getResourceInput(IEditorPart part) {\r
-        IEditorInput input = part.getEditorInput();\r
-        if (input instanceof IResourceEditorInput)\r
-            return (IResourceEditorInput) input;\r
-        return null;\r
-    }\r
-\r
-    public void dispose() {\r
-        deactivateValidation();\r
-\r
-        // This is special for IResourceInput, has to be done in order not to\r
-        // leak random access id's for resources.\r
-        if (!PlatformUI.getWorkbench().isClosing()) {\r
-            IResourceEditorInput input = getResourceInput(editorPart);\r
-            if (input != null)\r
-                input.dispose();\r
-        }\r
-        editorPart = null;\r
-\r
-        sessionContext = null;\r
-        if (session != null) {\r
-            if (editorPartChangeListener != null) {\r
-                GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class);\r
-                support.removeListener(this);\r
-            }\r
-            session = null;\r
-        }\r
-\r
-        editorPartChangeListener = null;\r
-    }\r
-\r
-    protected boolean isDisposed() {\r
-        return editorPart == null;\r
-    }\r
-\r
-    public synchronized void activateValidation() {\r
-        if (isDisposed())\r
-            throw new IllegalStateException(this + " is disposed");\r
-        if (inputListener != null)\r
-            return;\r
-\r
-        inputListener = new InputListener();\r
-        getSession().asyncRequest(validationRequest(editorPart), inputListener);\r
-    }\r
-\r
-    public synchronized void deactivateValidation() {\r
-        if (isDisposed())\r
-            throw new IllegalStateException(this + " is disposed");\r
-        if (inputListener == null)\r
-            return;\r
-        inputListener.dispose();\r
-    }\r
-\r
-    public ISessionContext getSessionContext() {\r
-        if (sessionContext == null)\r
-            throw new IllegalStateException("ResourceEditorSupport is disposed");\r
-        return sessionContext;\r
-    }\r
-\r
-    public Session getSession() {\r
-        if (session == null)\r
-            throw new IllegalStateException("ResourceEditorSupport is disposed");\r
-        return session;\r
-    }\r
-\r
-    @SuppressWarnings("rawtypes")\r
-    @Override\r
-    public Object getAdapter(Class adapter) {\r
-        if (adapter == ISessionContext.class)\r
-            return getSessionContext();\r
-        if (adapter == Session.class)\r
-            return getSession();\r
-        return null;\r
-    }\r
-\r
-    @Override\r
-    public void graphChanged(ChangeEvent e) throws DatabaseException {\r
-        //System.out.println(this + ": graph change: " + e);\r
-        // Only forward the update to the editor if the input is still valid and\r
-        // the editor implements ChangeListener\r
-        if (editorPart instanceof ChangeListener)\r
-            ((ChangeListener) editorPart).graphChanged(e);\r
-    }\r
-\r
-    static enum InputState {\r
-        VALID,\r
-        INVALID,\r
-        NON_EXISTENT;\r
-\r
-        public static InputState parse(boolean exists, boolean valid) {\r
-            if (!exists)\r
-                return NON_EXISTENT;\r
-            return valid ? VALID : INVALID;\r
-        }\r
-    }\r
-\r
-    static class Evaluation extends Tuple {\r
-        public Evaluation(IEditorPart editorPart, IEditorInput input, InputState state, String name, String tooltip) {\r
-            super(editorPart, input, state, name, tooltip);\r
-        }\r
-\r
-        public IEditorPart getEditorPart() {\r
-            return (IEditorPart) getField(0);\r
-        }\r
-\r
-        public IEditorInput getEditorInput() {\r
-            return (IEditorInput) getField(1);\r
-        }\r
-\r
-        public InputState getInputState() {\r
-            return (InputState) getField(2);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * @param input\r
-     * @return a read request that returns <code>true</code> for valid inputs\r
-     *         and <code>false</code> for non-existent or invalid inputs.\r
-     */\r
-    private Read<Evaluation> validationRequest(IEditorPart editorPart) {\r
-        return new UnaryRead<IEditorPart, Evaluation>(editorPart) {\r
-            @Override\r
-            public Evaluation perform(ReadGraph graph) throws DatabaseException {\r
-                IEditorInput input = parameter.getEditorInput();\r
-                IResourceEditorInput resourceInput = getResourceInput(parameter);\r
-\r
-                //System.out.println(ResourceEditorSupport.this + ": checking input " + input);\r
-\r
-                boolean exists = true;\r
-                boolean valid = true;\r
-                if (resourceInput != null) {\r
-                    exists = resourceInput.exists(graph);\r
-                    if (exists && inputValidator != null) {\r
-                        valid = graph.syncRequest(inputValidator.get(resourceInput));\r
-                    }\r
-                } else {\r
-                    exists = input.exists();\r
-                }\r
-\r
-                InputState state = InputState.parse(exists, valid);\r
-                if (state == InputState.VALID) {\r
-                    // Make sure any cached data in the editor input is up-to-date.\r
-                    resourceInput.update(graph);\r
-                }\r
-\r
-                Evaluation eval = new Evaluation(parameter, input, state, input.getName(), input.getToolTipText());\r
-                //System.out.println(ResourceEditorSupport.this + ": validation evaluation: " + eval);\r
-                return eval;\r
-            }\r
-        };\r
-    }\r
-\r
-    private class InputListener extends ListenerAdapter<Evaluation> {\r
-\r
-        private boolean disposed = false;\r
-\r
-        public void dispose() {\r
-            disposed = true;\r
-        }\r
-\r
-        @Override\r
-        public void execute(Evaluation evaluation) {\r
-            //System.out.println("InputListener: " + evaluation);\r
-            switch (evaluation.getInputState()) {\r
-                case VALID:\r
-                    break;\r
-\r
-                case INVALID:\r
-                case NON_EXISTENT:\r
-                    scheduleEditorClose(evaluation.getEditorPart());\r
-                    break;\r
-            }\r
-        }\r
-\r
-        @Override\r
-        public void exception(Throwable t) {\r
-            ExceptionUtils.logError("ResourceEditorSupport.InputListener received an unexpected exception.", t);\r
-        }\r
-\r
-        @Override\r
-        public boolean isDisposed() {\r
-            return disposed || ResourceEditorSupport.this.isDisposed();\r
-        }\r
-    }\r
-\r
-    private void scheduleEditorClose(final IEditorPart editorPart) {\r
-        SWTUtils.asyncExec(editorPart.getSite().getShell(), new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                // Don't have to check isDisposed since closeEditor\r
-                // will ignore already closed editor parts.\r
-                WorkbenchUtils.closeEditor(editorPart, false);\r
-            }\r
-        });\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2013 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
+ *     Semantum Oy - issue #4384
+ *******************************************************************************/
+package org.simantics.ui.workbench;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Session;
+import org.simantics.db.common.procedure.adapter.ListenerAdapter;
+import org.simantics.db.common.request.ParametrizedRead;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.event.ChangeEvent;
+import org.simantics.db.event.ChangeListener;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.db.management.ISessionContextProvider;
+import org.simantics.db.service.GraphChangeListenerSupport;
+import org.simantics.utils.datastructures.map.Tuple;
+import org.simantics.utils.ui.ExceptionUtils;
+import org.simantics.utils.ui.SWTUtils;
+import org.simantics.utils.ui.workbench.WorkbenchUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper class for easing the attachment of a Simantics database session to
+ * an editor part.
+ * 
+ * It handles the life-cycle of {@link IResourceEditorInput} inputs. It will
+ * listen to graph database changes through {@link ChangeListener} and calls
+ * {@link IResourceEditorInput#update(org.simantics.db.ReadGraph)}.
+ * 
+ * Works with any IEditorPart but is only really useful with ones that have
+ * resource inputs.
+ * 
+ * @author Tuukka Lehtonen
+ */
+public class ResourceEditorSupport implements IAdaptable, ChangeListener {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ResourceEditorSupport.class);
+    private static final boolean DEBUG = false;
+
+    private IEditorPart                             editorPart;
+
+    private ChangeListener                          editorPartChangeListener;
+
+    private ISessionContext                         sessionContext;
+
+    // Just a cache to make sure that getSession doesn't NPE.
+    private Session                                 session;
+
+    ParametrizedRead<IResourceEditorInput, Boolean> inputValidator;
+
+    private InputListener                           inputListener;
+
+    public ResourceEditorSupport(IEditorPart editorPart) throws PartInitException {
+        this(editorPart, null);
+    }
+
+    public ResourceEditorSupport(IEditorPart editorPart, ParametrizedRead<IResourceEditorInput, Boolean> inputValidator) throws PartInitException {
+        this.editorPart = editorPart;
+        this.editorPartChangeListener = getChangeListener(editorPart);
+        this.inputValidator = inputValidator;
+
+        initSession();
+
+        IResourceEditorInput input = getResourceInput(editorPart);
+        if (input == null)
+            throw new PartInitException("Editor input must be an IResourceEditorInput, got " + editorPart.getEditorInput());
+
+        try {
+            input.init(this);
+        } catch (DatabaseException e) {
+            throw new PartInitException("Failed to initialize " + input, e);
+        }
+    }
+
+    private ISessionContext initSession() throws PartInitException {
+        if (sessionContext == null) {
+            ISessionContextProvider provider = Simantics.getSessionContextProvider();
+            ISessionContext sc = provider.getSessionContext();
+            if (sc == null)
+                throw new PartInitException("active database session context is null");
+
+            sessionContext = sc;
+            session = sc.getSession();
+
+            if (editorPartChangeListener != null) {
+                GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class);
+                support.addListener(this);
+            }
+        }
+        return sessionContext;
+    }
+
+    private ChangeListener getChangeListener(IEditorPart part) {
+        if (part instanceof ChangeListener)
+            return (ChangeListener) part;
+        ChangeListener cl = (ChangeListener) part.getAdapter(ChangeListener.class);
+        return cl;
+    }
+
+    private static IResourceEditorInput getResourceInput(IEditorPart part) {
+        IEditorInput input = part.getEditorInput();
+        if (input instanceof IResourceEditorInput)
+            return (IResourceEditorInput) input;
+        return null;
+    }
+
+    public void dispose() {
+        deactivateValidation();
+
+        // This is special for IResourceInput, has to be done in order not to
+        // leak random access id's for resources.
+        if (!PlatformUI.getWorkbench().isClosing()) {
+            IResourceEditorInput input = getResourceInput(editorPart);
+            if (input != null)
+                input.dispose();
+        }
+        editorPart = null;
+
+        sessionContext = null;
+        if (session != null) {
+            if (editorPartChangeListener != null) {
+                GraphChangeListenerSupport support = session.getService(GraphChangeListenerSupport.class);
+                support.removeListener(this);
+            }
+            session = null;
+        }
+
+        editorPartChangeListener = null;
+    }
+
+    protected boolean isDisposed() {
+        return editorPart == null;
+    }
+
+    public synchronized void activateValidation() {
+        if (isDisposed())
+            throw new IllegalStateException(this + " is disposed");
+        if (inputListener != null)
+            return;
+
+        inputListener = new InputListener();
+        getSession().asyncRequest(new ValidationRequest(), inputListener);
+    }
+
+    public synchronized void deactivateValidation() {
+        if (isDisposed())
+            throw new IllegalStateException(this + " is disposed");
+        if (inputListener == null)
+            return;
+        inputListener.dispose();
+        inputListener = null;
+    }
+
+    public ISessionContext getSessionContext() {
+        if (sessionContext == null)
+            throw new IllegalStateException("ResourceEditorSupport is disposed");
+        return sessionContext;
+    }
+
+    public Session getSession() {
+        if (session == null)
+            throw new IllegalStateException("ResourceEditorSupport is disposed");
+        return session;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getAdapter(Class<T> adapter) {
+        if (adapter == ISessionContext.class)
+            return (T) getSessionContext();
+        if (adapter == Session.class)
+            return (T) getSession();
+        return null;
+    }
+
+    @Override
+    public void graphChanged(ChangeEvent e) throws DatabaseException {
+        // Only forward the update to the editor if the input is still valid and
+        // the editor implements ChangeListener
+        if (editorPart instanceof ChangeListener)
+            ((ChangeListener) editorPart).graphChanged(e);
+    }
+
+    static enum InputState {
+        VALID,
+        INVALID,
+        NON_EXISTENT;
+
+        public static InputState parse(boolean exists, boolean valid) {
+            if (!exists)
+                return NON_EXISTENT;
+            return valid ? VALID : INVALID;
+        }
+    }
+
+    static class Evaluation extends Tuple {
+        public Evaluation(IEditorPart editorPart, IEditorInput input, InputState state, String name, String tooltip) {
+            super(editorPart, input, state, name, tooltip);
+        }
+
+        public IEditorPart getEditorPart() {
+            return (IEditorPart) getField(0);
+        }
+
+        public IEditorInput getEditorInput() {
+            return (IEditorInput) getField(1);
+        }
+
+        public InputState getInputState() {
+            return (InputState) getField(2);
+        }
+    }
+
+    /**
+     * A read request that returns an {@link Evaluation} of the current state of
+     * <code>editorPart</code>.
+     * 
+     * <p>
+     * This request class is not static but has no parameters that could get
+     * stuck in the database client caches. UniqueRead does not need arguments
+     * and without custom hashCode/equals implementations, each instance of this
+     * request is a different one. This is exactly the behaviour we want in this
+     * case.
+     */
+    private class ValidationRequest extends UniqueRead<Evaluation> {
+        @Override
+        public Evaluation perform(ReadGraph graph) throws DatabaseException {
+            IEditorPart part = editorPart;
+            if (part == null)
+                return new Evaluation(null, null, InputState.INVALID, "", "");
+
+            IEditorInput input = part.getEditorInput();
+            IResourceEditorInput resourceInput = getResourceInput(part);
+
+            if (DEBUG)
+                LOGGER.trace("ValidationRequest: checking input " + input);
+
+            boolean exists = true;
+            boolean valid = true;
+            if (resourceInput != null) {
+                exists = resourceInput.exists(graph);
+                if (exists && inputValidator != null) {
+                    valid = graph.syncRequest(inputValidator.get(resourceInput));
+                }
+            } else {
+                exists = input.exists();
+            }
+
+            InputState state = InputState.parse(exists, valid);
+            if (state == InputState.VALID) {
+                // Make sure any cached data in the editor input is up-to-date.
+                if (resourceInput != null)
+                    resourceInput.update(graph);
+            }
+
+            Evaluation eval = new Evaluation(part, input, state, input.getName(), input.getToolTipText());
+            if (DEBUG)
+                LOGGER.trace("ValidationRequest: evaluation result: " + eval);
+            return eval;
+        }
+    }
+
+    private static class InputListener extends ListenerAdapter<Evaluation> {
+
+        private boolean disposed = false;
+
+        public void dispose() {
+            disposed = true;
+        }
+
+        @Override
+        public void execute(Evaluation evaluation) {
+            if (DEBUG)
+                LOGGER.trace("InputListener: " + evaluation);
+            switch (evaluation.getInputState()) {
+                case VALID:
+                    break;
+                case INVALID:
+                case NON_EXISTENT:
+                    scheduleEditorClose(evaluation.getEditorPart());
+                    break;
+            }
+        }
+
+        @Override
+        public void exception(Throwable t) {
+            ExceptionUtils.logError("ResourceEditorSupport.InputListener received an unexpected exception.", t);
+        }
+
+        @Override
+        public boolean isDisposed() {
+            return disposed;
+        }
+    }
+
+    private static void scheduleEditorClose(IEditorPart editorPart) {
+        if (editorPart == null)
+            return;
+        SWTUtils.asyncExec(editorPart.getSite().getWorkbenchWindow().getShell(), () -> {
+            // Don't have to check isDisposed since closeEditor
+            // will ignore already closed editor parts.
+            WorkbenchUtils.closeEditor(editorPart, false);
+        });
+    }
+
+}