blob: ba2129073fdc04f3fb54f44c59e3797051fd5622 [file] [log] [blame]
/*
* Copyright 2000-2012 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 com.intellij.notification;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.impl.ConsoleViewUtil;
import com.intellij.execution.impl.EditorHyperlinkSupport;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.icons.AllIcons;
import com.intellij.notification.impl.NotificationsManagerImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.ex.EditorMarkupModel;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.JBColor;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.EditorPopupHandler;
import com.intellij.util.text.DateFormatUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
/**
* @author peter
*/
class EventLogConsole {
private final NotNullLazyValue<Editor> myLogEditor = new NotNullLazyValue<Editor>() {
@NotNull
@Override
protected Editor compute() {
return createLogEditor();
}
};
private final NotNullLazyValue<EditorHyperlinkSupport> myHyperlinkSupport = new NotNullLazyValue<EditorHyperlinkSupport>() {
@NotNull
@Override
protected EditorHyperlinkSupport compute() {
return new EditorHyperlinkSupport(myLogEditor.getValue(), myProjectModel.getProject());
}
};
private final LogModel myProjectModel;
EventLogConsole(LogModel model) {
myProjectModel = model;
}
private Editor createLogEditor() {
Project project = myProjectModel.getProject();
final Editor editor = ConsoleViewUtil.setupConsoleEditor(project, false, false);
Disposer.register(myProjectModel, new Disposable() {
@Override
public void dispose() {
EditorFactory.getInstance().releaseEditor(editor);
}
});
((EditorMarkupModel)editor.getMarkupModel()).setErrorStripeVisible(true);
final ClearLogAction clearLog = new ClearLogAction(this);
clearLog.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.CONSOLE_CLEAR_ALL).getShortcutSet(), editor.getContentComponent());
editor.addEditorMouseListener(new EditorPopupHandler() {
public void invokePopup(final EditorMouseEvent event) {
final ActionManager actionManager = ActionManager.getInstance();
final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_POPUP, createPopupActions(actionManager, clearLog));
final MouseEvent mouseEvent = event.getMouseEvent();
menu.getComponent().show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
}
});
return editor;
}
private DefaultActionGroup createPopupActions(ActionManager actionManager, ClearLogAction action) {
AnAction[] children = ((ActionGroup)actionManager.getAction(IdeActions.GROUP_CONSOLE_EDITOR_POPUP)).getChildren(null);
DefaultActionGroup group = new DefaultActionGroup(children);
group.addSeparator();
group.add(action);
return group;
}
void doPrintNotification(final Notification notification) {
Editor editor = myLogEditor.getValue();
if (editor.isDisposed()) {
return;
}
Document document = editor.getDocument();
boolean scroll = document.getTextLength() == editor.getCaretModel().getOffset() || !editor.getContentComponent().hasFocus();
Long notificationTime = myProjectModel.getNotificationTime(notification);
if (notificationTime == null) {
return;
}
String date = DateFormatUtil.formatTimeWithSeconds(notificationTime) + " ";
append(document, date);
int startLine = document.getLineCount() - 1;
EventLog.LogEntry pair = EventLog.formatForLog(notification, StringUtil.repeatSymbol(' ', date.length()));
final NotificationType type = notification.getType();
TextAttributesKey key = type == NotificationType.ERROR
? ConsoleViewContentType.LOG_ERROR_OUTPUT_KEY
: type == NotificationType.INFORMATION
? ConsoleViewContentType.NORMAL_OUTPUT_KEY
: ConsoleViewContentType.LOG_WARNING_OUTPUT_KEY;
int msgStart = document.getTextLength();
String message = pair.message;
append(document, message);
TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(key);
int layer = HighlighterLayer.CARET_ROW + 1;
editor.getMarkupModel().addRangeHighlighter(msgStart, document.getTextLength(), layer, attributes, HighlighterTargetArea.EXACT_RANGE);
for (Pair<TextRange, HyperlinkInfo> link : pair.links) {
myHyperlinkSupport.getValue().addHyperlink(link.first.getStartOffset() + msgStart, link.first.getEndOffset() + msgStart, null,
link.second);
}
append(document, "\n");
if (scroll) {
editor.getCaretModel().moveToOffset(document.getTextLength());
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
}
if (notification.isImportant()) {
highlightNotification(notification, pair.status, startLine, document.getLineCount() - 1);
}
}
private void highlightNotification(final Notification notification,
String message, final int line1, final int line2) {
final MarkupModel markupModel = myLogEditor.getValue().getMarkupModel();
TextAttributes bold = new TextAttributes(null, null, null, null, Font.BOLD);
final List<RangeHighlighter> lineColors = new ArrayList<RangeHighlighter>();
for (int line = line1; line < line2; line++) {
final RangeHighlighter lineHighlighter = markupModel.addLineHighlighter(line, HighlighterLayer.CARET_ROW + 1, bold);
Color color = notification.getType() == NotificationType.ERROR
? JBColor.RED
: notification.getType() == NotificationType.WARNING ? JBColor.YELLOW : JBColor.GREEN;
lineHighlighter.setErrorStripeMarkColor(color);
lineHighlighter.setErrorStripeTooltip(message);
lineColors.add(lineHighlighter);
}
myProjectModel.removeHandlers.put(notification, new Runnable() {
@Override
public void run() {
for (RangeHighlighter color : lineColors) {
markupModel.removeHighlighter(color);
}
TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(ConsoleViewContentType.LOG_EXPIRED_ENTRY);
for (int line = line1; line < line2; line++) {
markupModel.addLineHighlighter(line, HighlighterLayer.CARET_ROW + 1, attributes);
}
TextAttributes italic = new TextAttributes(null, null, null, null, Font.ITALIC);
for (int line = line1; line < line2; line++) {
for (RangeHighlighter highlighter : myHyperlinkSupport.getValue().findAllHyperlinksOnLine(line)) {
markupModel.addRangeHighlighter(highlighter.getStartOffset(), highlighter.getEndOffset(), HighlighterLayer.CARET_ROW + 2, italic, HighlighterTargetArea.EXACT_RANGE);
myHyperlinkSupport.getValue().removeHyperlink(highlighter);
}
}
}
});
}
public Editor getConsoleEditor() {
return myLogEditor.getValue();
}
@Nullable
public RelativePoint getHyperlinkLocation(HyperlinkInfo info) {
Editor editor = myLogEditor.getValue();
Project project = editor.getProject();
RangeHighlighter range = myHyperlinkSupport.getValue().findHyperlinkRange(info);
Window window = NotificationsManagerImpl.findWindowForBalloon(project);
if (range != null && window != null) {
Point point = editor.visualPositionToXY(editor.offsetToVisualPosition(range.getStartOffset()));
return new RelativePoint(window, SwingUtilities.convertPoint(editor.getContentComponent(), point, window));
}
return null;
}
private static void append(Document document, String s) {
document.insertString(document.getTextLength(), s);
}
public static class ClearLogAction extends DumbAwareAction {
private EventLogConsole myConsole;
public ClearLogAction(EventLogConsole console) {
super("Clear All", "Clear the contents of the Event Log", AllIcons.Actions.GC);
myConsole = console;
}
@Override
public void update(AnActionEvent e) {
Editor editor = e.getData(CommonDataKeys.EDITOR);
e.getPresentation().setEnabled(editor != null && editor.getDocument().getTextLength() > 0);
}
public void actionPerformed(final AnActionEvent e) {
LogModel model = myConsole.myProjectModel;
for (Notification notification : model.getNotifications()) {
notification.expire();
model.removeNotification(notification);
}
model.setStatusMessage(null, 0);
final Editor editor = e.getData(CommonDataKeys.EDITOR);
if (editor != null) {
editor.getDocument().deleteString(0, editor.getDocument().getTextLength());
}
}
}
}