| /* |
| * Copyright 2000-2014 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.openapi.externalSystem.service.notification; |
| |
| import com.intellij.ide.IdeTooltipManager; |
| import com.intellij.ide.errorTreeView.*; |
| import com.intellij.notification.Notification; |
| import com.intellij.notification.NotificationListener; |
| import com.intellij.openapi.actionSystem.*; |
| import com.intellij.pom.Navigatable; |
| import com.intellij.ui.*; |
| import com.intellij.util.containers.ContainerUtil; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.event.HyperlinkEvent; |
| import javax.swing.event.HyperlinkListener; |
| import javax.swing.text.AttributeSet; |
| import javax.swing.text.SimpleAttributeSet; |
| import javax.swing.text.Style; |
| import javax.swing.text.StyleConstants; |
| import javax.swing.text.html.HTML; |
| import javax.swing.text.html.HTMLDocument; |
| import javax.swing.tree.TreeCellEditor; |
| import javax.swing.tree.TreePath; |
| import java.awt.*; |
| import java.util.Map; |
| |
| /** |
| * @author Vladislav.Soroka |
| * @since 3/24/2014 |
| */ |
| public class EditableNotificationMessageElement extends NotificationMessageElement implements EditableMessageElement { |
| |
| @NotNull private final TreeCellEditor myRightTreeCellEditor; |
| @NotNull private final Notification myNotification; |
| @NotNull private final Map<String/*url*/, String/*link text to replace*/> disabledLinks; |
| |
| public EditableNotificationMessageElement(@NotNull Notification notification, |
| @NotNull ErrorTreeElementKind kind, |
| @Nullable GroupingElement parent, |
| String[] message, |
| Navigatable navigatable, |
| String exportText, String rendererTextPrefix) { |
| super(kind, parent, message, navigatable, exportText, rendererTextPrefix); |
| myNotification = notification; |
| disabledLinks = ContainerUtil.newHashMap(); |
| myRightTreeCellEditor = new MyCellEditor(); |
| } |
| |
| |
| public void addDisabledLink(@NotNull String url, @Nullable String text) { |
| disabledLinks.put(url, text); |
| } |
| |
| @NotNull |
| @Override |
| public TreeCellEditor getRightSelfEditor() { |
| return myRightTreeCellEditor; |
| } |
| |
| @Override |
| public boolean startEditingOnMouseMove() { |
| return true; |
| } |
| |
| public static void disableLink(@NotNull HyperlinkEvent event) { |
| disableLink(event, null); |
| } |
| |
| private static void disableLink(@NotNull final HyperlinkEvent event, @Nullable final String linkText) { |
| if (event.getSource() instanceof MyJEditorPane) { |
| UIUtil.invokeLaterIfNeeded(new Runnable() { |
| @Override |
| public void run() { |
| final MyJEditorPane editorPane = (MyJEditorPane)event.getSource(); |
| editorPane.myElement.addDisabledLink(event.getDescription(), linkText); |
| editorPane.myElement.updateStyle(editorPane, null, null, true, false); |
| } |
| }); |
| } |
| } |
| |
| protected void updateStyle(@NotNull JEditorPane editorPane, @Nullable JTree tree, Object value, boolean selected, boolean hasFocus) { |
| super.updateStyle(editorPane, tree, value, selected, hasFocus); |
| |
| final HTMLDocument htmlDocument = (HTMLDocument)editorPane.getDocument(); |
| final Style linkStyle = htmlDocument.getStyleSheet().getStyle(LINK_STYLE); |
| StyleConstants.setForeground(linkStyle, IdeTooltipManager.getInstance().getLinkForeground(false)); |
| StyleConstants.setItalic(linkStyle, true); |
| HTMLDocument.Iterator iterator = htmlDocument.getIterator(HTML.Tag.A); |
| while (iterator.isValid()) { |
| boolean disabledLink = false; |
| final AttributeSet attributes = iterator.getAttributes(); |
| if (attributes instanceof SimpleAttributeSet) { |
| final Object attribute = attributes.getAttribute(HTML.Attribute.HREF); |
| if (attribute instanceof String && disabledLinks.containsKey(attribute)) { |
| disabledLink = true; |
| //TODO [Vlad] add support for disabled link text update |
| ////final String linkText = disabledLinks.get(attribute); |
| //if (linkText != null) { |
| //} |
| ((SimpleAttributeSet)attributes).removeAttribute(HTML.Attribute.HREF); |
| } |
| if (attribute == null) { |
| disabledLink = true; |
| } |
| } |
| if (!disabledLink) { |
| htmlDocument.setCharacterAttributes( |
| iterator.getStartOffset(), iterator.getEndOffset() - iterator.getStartOffset(), linkStyle, false); |
| } |
| iterator.next(); |
| } |
| } |
| |
| private static class MyJEditorPane extends JEditorPane { |
| @NotNull |
| private final EditableNotificationMessageElement myElement; |
| |
| public MyJEditorPane(@NotNull EditableNotificationMessageElement element) { |
| myElement = element; |
| } |
| } |
| |
| private class MyCellEditor extends AbstractCellEditor implements TreeCellEditor { |
| private final JEditorPane editorComponent; |
| @Nullable |
| private JTree myTree; |
| |
| private MyCellEditor() { |
| editorComponent = installJep(new MyJEditorPane(EditableNotificationMessageElement.this)); |
| |
| HyperlinkListener hyperlinkListener = new ActivatedHyperlinkListener(); |
| editorComponent.addHyperlinkListener(hyperlinkListener); |
| editorComponent.addMouseListener(new PopupHandler() { |
| @Override |
| public void invokePopup(Component comp, int x, int y) { |
| if (myTree == null) return; |
| |
| final TreePath path = myTree.getLeadSelectionPath(); |
| if (path == null) { |
| return; |
| } |
| DefaultActionGroup group = new DefaultActionGroup(); |
| group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE)); |
| group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_COPY)); |
| |
| ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.COMPILER_MESSAGES_POPUP, group); |
| menu.getComponent().show(comp, x, y); |
| } |
| }); |
| } |
| |
| @Override |
| public Component getTreeCellEditorComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row) { |
| myTree = tree; |
| updateStyle(editorComponent, tree, value, selected, false); |
| return editorComponent; |
| } |
| |
| @Override |
| public Object getCellEditorValue() { |
| return null; |
| } |
| |
| private class ActivatedHyperlinkListener implements HyperlinkListener { |
| |
| @Override |
| public void hyperlinkUpdate(HyperlinkEvent e) { |
| if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { |
| final NotificationListener notificationListener = myNotification.getListener(); |
| if (notificationListener != null) { |
| notificationListener.hyperlinkUpdate(myNotification, e); |
| } |
| } |
| } |
| } |
| } |
| } |