diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java index c9e9ce31020a..f57753ef7afc 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileContextImpl.java @@ -55,7 +55,7 @@ import java.util.*; public class CompileContextImpl extends UserDataHolderBase implements CompileContextEx { private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompileContextImpl"); private final Project myProject; - private final CompilerTask myTask; + private final CompilerTask myBuildSession; private final Map> myMessages = new EnumMap>(CompilerMessageCategory.class); private final boolean myShouldUpdateProblemsView; private CompileScope myCompileScope; @@ -77,7 +77,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon CompileScope compileScope, boolean isMake, boolean isRebuild) { myProject = project; - myTask = compilerSession; + myBuildSession = compilerSession; myCompileScope = compileScope; myMake = isMake; myIsRebuild = isRebuild; @@ -99,6 +99,10 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon myShouldUpdateProblemsView = workspaceConfig.MAKE_PROJECT_ON_SAVE; } + public CompilerTask getBuildSession() { + return myBuildSession; + } + public boolean shouldUpdateProblemsView() { return myShouldUpdateProblemsView; } @@ -154,7 +158,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon myMessages.put(msg.getCategory(), messages); } if (messages.add(msg)) { - myTask.addMessage(msg); + myBuildSession.addMessage(msg); } if (myShouldUpdateProblemsView && msg.getCategory() == CompilerMessageCategory.ERROR) { ProblemsView.SERVICE.getInstance(myProject).addMessage(msg, mySessionId); @@ -200,7 +204,7 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon } public ProgressIndicator getProgressIndicator() { - return myTask.getIndicator(); + return myBuildSession.getIndicator(); } public Module getModuleByFile(VirtualFile file) { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index 3ff7406c9f88..c40edf0f595c 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -29,6 +29,8 @@ import com.intellij.compiler.ProblemsView; import com.intellij.compiler.progress.CompilerTask; import com.intellij.compiler.server.BuildManager; import com.intellij.compiler.server.DefaultMessageHandler; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.*; import com.intellij.openapi.compiler.ex.CompilerPathsEx; @@ -53,10 +55,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.openapi.wm.StatusBar; -import com.intellij.openapi.wm.ToolWindowId; -import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.wm.*; import com.intellij.packaging.artifacts.Artifact; import com.intellij.packaging.impl.compiler.ArtifactCompilerUtil; import com.intellij.packaging.impl.compiler.ArtifactsCompiler; @@ -68,6 +67,7 @@ import com.intellij.util.ThrowableRunnable; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.MultiMap; import com.intellij.util.messages.MessageBus; +import com.intellij.util.text.DateFormatUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -79,7 +79,9 @@ import org.jetbrains.jps.api.RequestFuture; import org.jetbrains.jps.model.java.JavaSourceRootType; import javax.swing.*; +import javax.swing.event.HyperlinkEvent; import java.io.File; +import java.lang.ref.WeakReference; import java.util.*; import java.util.concurrent.TimeUnit; @@ -502,9 +504,24 @@ public class CompileDriver { if (duration > ONE_MINUTE_MS && CompilerWorkspaceConfiguration.getInstance(myProject).DISPLAY_NOTIFICATION_POPUP) { ToolWindowManager.getInstance(myProject).notifyByBalloon(ToolWindowId.MESSAGES_WINDOW, messageType, statusMessage); } - CompilerManager.NOTIFICATION_GROUP.createNotification(statusMessage, messageType).notify(myProject); + + final String wrappedMessage = _status != ExitStatus.UP_TO_DATE? "" + statusMessage + "" : statusMessage; + final Notification notification = CompilerManager.NOTIFICATION_GROUP.createNotification( + "", wrappedMessage, + messageType.toNotificationType(), + new MessagesActivationListener(compileContext) + ); + compileContext.getBuildSession().registerCloseAction(new Runnable() { + @Override + public void run() { + notification.expire(); + } + }); + notification.notify(myProject); + if (_status != ExitStatus.UP_TO_DATE && compileContext.getMessageCount(null) > 0) { - compileContext.addMessage(CompilerMessageCategory.INFORMATION, statusMessage, null, -1, -1); + final String msg = DateFormatUtil.formatDateTime(new Date()) + " - " + statusMessage; + compileContext.addMessage(CompilerMessageCategory.INFORMATION, msg, null, -1, -1); } } } @@ -785,4 +802,28 @@ public class CompileDriver { private void showConfigurationDialog(String moduleNameToSelect, String tabNameToSelect) { ProjectSettingsService.getInstance(myProject).showModuleConfigurationDialog(moduleNameToSelect, tabNameToSelect); } + + private static class MessagesActivationListener extends NotificationListener.Adapter { + private final WeakReference myProjectRef; + private final Object myContentId; + + public MessagesActivationListener(CompileContextImpl compileContext) { + myProjectRef = new WeakReference(compileContext.getProject()); + myContentId = compileContext.getBuildSession().getContentId(); + } + + @Override + protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) { + final Project project = myProjectRef.get(); + if (project != null && !project.isDisposed() && CompilerTask.showCompilerContent(project, myContentId)) { + final ToolWindow tw = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.MESSAGES_WINDOW); + if (tw != null) { + tw.activate(null, false); + } + } + else { + notification.expire(); + } + } + } } diff --git a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java index f568f2d06364..2f9f023bc52a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java +++ b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java @@ -22,12 +22,11 @@ package com.intellij.compiler.progress; import com.intellij.compiler.CompilerManagerImpl; -import com.intellij.compiler.CompilerMessageImpl; import com.intellij.compiler.impl.CompilerErrorTreeView; import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel; import com.intellij.ide.errorTreeView.impl.ErrorTreeViewConfiguration; import com.intellij.ide.impl.ProjectUtil; -import com.intellij.openapi.application.Application; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.compiler.*; @@ -42,6 +41,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; @@ -120,6 +120,26 @@ public class CompilerTask extends Task.Backgroundable { mySessionId = sessionId; } + @NotNull + public Object getContentId() { + return myContentId; + } + + public void registerCloseAction(final Runnable onClose) { + synchronized (myMessageViewLock) { + if (myErrorTreeView != null) { + Disposer.register(myErrorTreeView, new Disposable() { + @Override + public void dispose() { + onClose.run(); + } + }); + return; + } + } + onClose.run(); + } + @Override public String getProcessId() { return "compilation"; @@ -221,13 +241,15 @@ public class CompilerTask extends Task.Backgroundable { private void addIndicatorDelegate() { ProgressIndicator indicator = myIndicator; - if (!(indicator instanceof ProgressIndicatorEx)) return; + if (!(indicator instanceof ProgressIndicatorEx)) { + return; + } ((ProgressIndicatorEx)indicator).addStateDelegate(new ProgressIndicatorBase() { @Override public void cancel() { super.cancel(); - closeUI(); + selectFirstMessage(); stopAppIconProgress(); } @@ -235,11 +257,26 @@ public class CompilerTask extends Task.Backgroundable { public void stop() { super.stop(); if (!isCanceled()) { - closeUI(); + selectFirstMessage(); } stopAppIconProgress(); } + private void selectFirstMessage() { + if (!isHeadlessMode()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + synchronized (myMessageViewLock) { + if (myErrorTreeView != null) { + myErrorTreeView.selectFirstMessage(); + } + } + } + }); + } + } + private void stopAppIconProgress() { UIUtil.invokeLaterIfNeeded(new Runnable() { @Override @@ -249,7 +286,8 @@ public class CompilerTask extends Task.Backgroundable { if (myErrorCount > 0) { appIcon.setErrorBadge(myProject, String.valueOf(myErrorCount)); appIcon.requestAttention(myProject, true); - } else if (!myCompilationStartedAutomatically) { + } + else if (!myCompilationStartedAutomatically) { appIcon.setOkBadge(myProject, true); appIcon.requestAttention(myProject, false); } @@ -450,18 +488,22 @@ public class CompilerTask extends Task.Backgroundable { public void showCompilerContent() { synchronized (myMessageViewLock) { if (myErrorTreeView != null) { - final MessageView messageView = MessageView.SERVICE.getInstance(myProject); - Content[] contents = messageView.getContentManager().getContents(); - for (Content content : contents) { - if (CONTENT_ID_KEY.get(content) == myContentId) { - messageView.getContentManager().setSelectedContent(content); - return; - } - } + showCompilerContent(myProject, myContentId); } } } + public static boolean showCompilerContent(final Project project, final Object contentId) { + final MessageView messageView = MessageView.SERVICE.getInstance(project); + for (Content content : messageView.getContentManager().getContents()) { + if (CONTENT_ID_KEY.get(content) == contentId) { + messageView.getContentManager().setSelectedContent(content); + return true; + } + } + return false; + } + private void removeAllContents(Project project, Content notRemove) { if (project.isDisposed()) { return; @@ -488,7 +530,7 @@ public class CompilerTask extends Task.Backgroundable { private void activateMessageView() { synchronized (myMessageViewLock) { - if (myErrorTreeView != null) { + if (myErrorTreeView != null && myProject != null) { final ToolWindow tw = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.MESSAGES_WINDOW); if (tw != null) { tw.activate(null, false); @@ -497,34 +539,6 @@ public class CompilerTask extends Task.Backgroundable { } } - private void closeUI() { - if (isHeadlessMode()) { - return; - } - Window window = getWindow(); - ModalityState modalityState = window != null ? ModalityState.stateForComponent(window) : ModalityState.NON_MODAL; - final Application application = ApplicationManager.getApplication(); - application.invokeLater(new Runnable() { - @Override - public void run() { - synchronized (myMessageViewLock) { - if (myErrorTreeView != null) { - final boolean shouldRetainView = myErrorCount > 0 || myWarningCount > 0 && !myErrorTreeView.isHideWarnings(); - if (shouldRetainView) { - addMessage(new CompilerMessageImpl(myProject, CompilerMessageCategory.STATISTICS, CompilerBundle.message("statistics.error.count", myErrorCount))); - addMessage(new CompilerMessageImpl(myProject, CompilerMessageCategory.STATISTICS, CompilerBundle.message("statistics.warnings.count", myWarningCount))); - //activateMessageView(); - myErrorTreeView.selectFirstMessage(); - } - else { - removeAllContents(myProject, null); - } - } - } - } - }, modalityState); - } - public Window getWindow(){ return null; } @@ -607,7 +621,7 @@ public class CompilerTask extends Task.Backgroundable { if (event.getContent() == myContent) { synchronized (myMessageViewLock) { if (myErrorTreeView != null) { - myErrorTreeView.dispose(); + Disposer.dispose(myErrorTreeView); myErrorTreeView = null; if (myIndicator.isRunning()) { cancel();