/* * Copyright 2003-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.ide; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.SwingUtilities; import java.lang.reflect.InvocationTargetException; /** * Interface to platform-specific access to Event Dispatch Thread. * For IDEA, use <code>ApplicationManager.getApplication()</code> */ public class ThreadUtils { @Nullable public static Exception runInUIThreadAndWait(Runnable r) { LogExceptionsRunnable wrap = new LogExceptionsRunnable(LogManager.getLogger(ThreadUtils.class), r); if (ApplicationManager.getApplication() != null) { // Application#invokeAndWait() executes runnable immediately if in EDT thread (well, at least it is stated in javadoc) ApplicationManager.getApplication().invokeAndWait(wrap, ModalityState.defaultModalityState()); } else { if (isInEDT()) { wrap.run(); } else { try { SwingUtilities.invokeAndWait(wrap); } catch (InterruptedException e) { LogManager.getLogger(ThreadUtils.class).error(e.getMessage(), e); return e; } catch (InvocationTargetException e) { LogManager.getLogger(ThreadUtils.class).error(e.getMessage(), e); return e; } } } return wrap.getException(); } public static void runInUIThreadNoWait(Runnable r) { LogExceptionsRunnable wrap = new LogExceptionsRunnable(LogManager.getLogger(ThreadUtils.class), r); if (isInEDT()) { wrap.run(); } else { if (ApplicationManager.getApplication() != null) { ApplicationManager.getApplication().invokeLater(wrap); } else { SwingUtilities.invokeLater(wrap); } } } private static class LogExceptionsRunnable implements Runnable { private final Logger myLog; private final Runnable myDelegate; private Exception myException; public LogExceptionsRunnable(Logger log, Runnable delegate) { myLog = log; myDelegate = delegate; } @Override public void run() { try { myDelegate.run(); } catch (Exception e) { myLog.error(ThreadUtils.class.getName(), e); myException = e; } } @Nullable public Exception getException() { return myException; } } /** * Handy wrap for {@link #runInUIThreadAndWait(Runnable)} and {@link #runInUIThreadNoWait(Runnable)} as a Runnable * one could pass to a facility that accepts Runnable */ public static class RunInUIRunnable implements Runnable { private final Runnable myDelegate; private final boolean myWaitDelegateToComplete; public RunInUIRunnable(@NotNull Runnable delegate, boolean wait) { myDelegate = delegate; myWaitDelegateToComplete = wait; } @Override public void run() { if (myWaitDelegateToComplete) { runInUIThreadAndWait(myDelegate); } else { runInUIThreadNoWait(myDelegate); } } } public static boolean isInEDT() { final Application ideaApp = ApplicationManager.getApplication(); return ideaApp == null ? SwingUtilities.isEventDispatchThread() : ideaApp.isDispatchThread(); } public static void assertEDT() { final Application ideaApp = ApplicationManager.getApplication(); if (ideaApp != null) { ideaApp.assertIsDispatchThread(); } else { if (!SwingUtilities.isEventDispatchThread()) { LogManager.getLogger(ThreadUtils.class).error("NOT EDT THREAD", new Throwable()); } assert false; } } }