From 04b7f72e55f26480b5b1d378637ba0e7fca4efcb Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 8 Jul 2011 19:11:06 +0200 Subject: [PATCH] a generic way of providing links for log --- .../impl/EditorHyperlinkSupport.java | 10 ++++ .../com/intellij/notification/EventLog.java | 45 ++++++++++++++++- .../notification/EventLogConsole.java | 48 ++++++++----------- .../openapi/wm/impl/status/StatusPanel.java | 2 +- 4 files changed, 73 insertions(+), 32 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java index d1b0e396b681..85832860109c 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java @@ -109,6 +109,16 @@ public class EditorHyperlinkSupport { return myHighlighterToMessageInfoMap.get(findLinkRangeAt(offset)); } + @Nullable + public RangeHighlighter findHyperlinkRange(HyperlinkInfo info) { + for (RangeHighlighter highlighter : myHighlighterToMessageInfoMap.keySet()) { + if (info == myHighlighterToMessageInfoMap.get(highlighter)) { + return highlighter; + } + } + return null; + } + private static boolean containsOffset(final int offset, final RangeHighlighter highlighter) { return highlighter.getStartOffset() <= offset && offset <= highlighter.getEndOffset(); } diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index 31e8c4637239..cd49addcf370 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -16,8 +16,10 @@ package com.intellij.notification; +import com.intellij.execution.filters.HyperlinkInfo; import com.intellij.notification.impl.NotificationsConfigurable; import com.intellij.notification.impl.NotificationsConfiguration; +import com.intellij.notification.impl.NotificationsManagerImpl; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.AbstractProjectComponent; @@ -31,17 +33,21 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.SimpleToolWindowPanel; +import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -93,7 +99,7 @@ public class EventLog implements Notifications { return getLogModel(project).getStatusMessage(); } - public static Pair formatForLog(@NotNull final Notification notification) { + public static LogEntry formatForLog(@NotNull final Notification notification) { boolean showLink = notification.getListener() != null; String content = notification.getContent(); String mainText = notification.getTitle(); @@ -111,7 +117,42 @@ public class EventLog implements Notifications { } mainText = mainText.replaceAll("<[^>]*>", ""); - return Pair.create(mainText, showLink); + + String status = mainText; + + List> links = new ArrayList>(); + if (showLink) { + mainText += " more "; + links.add(new Pair(TextRange.from(mainText.length() - 5, 4), new HyperlinkInfo() { + @Override + public void navigate(Project project) { + Balloon balloon = notification.getBalloon(); + if (balloon != null) { + balloon.hide(); + } + + RelativePoint target = EventLog.getProjectComponent(project).myConsole.getHyperlinkLocation(this); + if (target != null) { + balloon = NotificationsManagerImpl.createBalloon(notification, true, true, false); + balloon.show(target, Balloon.Position.above); + } + } + })); + } + + return new LogEntry(mainText, status, links); + } + + public static class LogEntry { + public final String message; + public final String status; + public final List> links; + + public LogEntry(String message, String status, List> links) { + this.message = message; + this.status = status; + this.links = links; + } } private static int eolIndex(String mainText) { diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java index ebf03c18461a..06e2deb0b0b4 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java @@ -36,11 +36,12 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.EditorPopupHandler; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -114,7 +115,7 @@ class EventLogConsole { append(document, DateFormat.getTimeInstance(DateFormat.MEDIUM).format(notification.getCreationTime()) + " "); - Pair pair = EventLog.formatForLog(notification); + EventLog.LogEntry pair = EventLog.formatForLog(notification); final NotificationType type = notification.getType(); TextAttributesKey key = type == NotificationType.ERROR @@ -124,40 +125,17 @@ class EventLogConsole { : ConsoleViewContentType.LOG_WARNING_OUTPUT_KEY; int msgStart = document.getTextLength(); - String message = pair.first; + String message = pair.message; append(document, message); TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(key); int layer = HighlighterLayer.CARET_ROW + 1; myLogEditor.getMarkupModel().addRangeHighlighter(msgStart, document.getTextLength(), layer, attributes, HighlighterTargetArea.EXACT_RANGE); - if (pair.second) { - String s = " "; - append(document, s); - - final int linkStart = document.getTextLength(); - append(document, "more"); - myHyperlinkSupport.addHyperlink(linkStart, document.getTextLength(), null, new HyperlinkInfo() { - @Override - public void navigate(Project project) { - Balloon balloon = notification.getBalloon(); - if (balloon != null) { - balloon.hide(); - } - - Window window = NotificationsManagerImpl.findWindowForBalloon(project); - if (window != null) { - Point point = EventLogConsole.this.myLogEditor - .visualPositionToXY(EventLogConsole.this.myLogEditor.offsetToVisualPosition(linkStart)); - Point target = SwingUtilities.convertPoint(EventLogConsole.this.myLogEditor.getContentComponent(), point, window); - balloon = NotificationsManagerImpl.createBalloon(notification, true, true, false); - balloon.show(new RelativePoint(window, target), Balloon.Position.above); - } - } - }); - - append(document, " "); + for (Pair link : pair.links) { + myHyperlinkSupport.addHyperlink(link.first.getStartOffset() + msgStart, link.first.getEndOffset() + msgStart, null, link.second); } + append(document, "\n"); if (scroll) { @@ -192,6 +170,18 @@ class EventLogConsole { return myLogEditor; } + @Nullable + public RelativePoint getHyperlinkLocation(HyperlinkInfo info) { + Project project = myLogEditor.getProject(); + RangeHighlighter range = myHyperlinkSupport.findHyperlinkRange(info); + Window window = NotificationsManagerImpl.findWindowForBalloon(project); + if (range != null && window != null) { + Point point = this.myLogEditor.visualPositionToXY(this.myLogEditor.offsetToVisualPosition(range.getStartOffset())); + return new RelativePoint(window, SwingUtilities.convertPoint(this.myLogEditor.getContentComponent(), point, window)); + } + return null; + } + private static void append(Document document, String s) { document.insertString(document.getTextLength(), s); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java index a8a8def2dcaf..c96accedd0a1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java @@ -118,7 +118,7 @@ class StatusPanel extends JPanel { new Runnable() { @Override public void run() { - String text = EventLog.formatForLog(statusMessage).first; + String text = EventLog.formatForLog(statusMessage).status; if (myDirty || System.currentTimeMillis() - statusMessage.getCreationTime() >= DateFormatUtil.MINUTE) { text += " (" + StringUtil.decapitalize(DateFormatUtil.formatPrettyDateTime(statusMessage.getCreationTime())) + ")"; }