/* * 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.ui; import com.intellij.codeInsight.intention.*; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorBundle; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.PlatformColors; import com.intellij.util.ui.UIUtil; import consulo.annotations.RequiredDispatchThread; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.HyperlinkEvent; import java.awt.*; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; /** * @author Dmitry Avdeev */ public class EditorNotificationPanel extends JPanel implements IntentionActionProvider { protected final JLabel myLabel = new JLabel(); protected final JLabel myGearLabel = new JLabel(); protected final JPanel myLinksPanel; private final Color myBackgroundColor; public EditorNotificationPanel() { this(null); } public EditorNotificationPanel(@Nullable Color backgroundColor) { super(new BorderLayout()); myBackgroundColor = backgroundColor; setBorder(JBUI.Borders.empty(1, 10, 1, 10)); setPreferredSize(JBUI.size(-1, 24)); add(myLabel, BorderLayout.CENTER); myLinksPanel = new JPanel(new FlowLayout()); myLinksPanel.setBackground(getBackground()); JPanel panel = new JPanel(new BorderLayout()); panel.setBackground(getBackground()); myGearLabel.setBorder(JBUI.Borders.empty(0, 3, 0, 0)); panel.add(myLinksPanel, BorderLayout.WEST); panel.add(myGearLabel, BorderLayout.EAST); add(panel, BorderLayout.EAST); } public void setText(String text) { myLabel.setText(text); } public EditorNotificationPanel text(@NotNull String text) { myLabel.setText(text); return this; } public EditorNotificationPanel icon(@NotNull Icon icon) { myLabel.setIcon(icon); return this; } @Override public final Color getBackground() { if (myBackgroundColor != null) { return myBackgroundColor; } Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.NOTIFICATION_BACKGROUND); return color == null ? UIUtil.getToolTipBackground() : color; } public HyperlinkLabel createActionLabel(final String text, @NonNls final String actionId) { return createActionLabel(text, () -> executeAction(actionId)); } public HyperlinkLabel createActionLabel(final String text, final Runnable action) { HyperlinkLabel label = new HyperlinkLabel(text, PlatformColors.BLUE, getBackground(), PlatformColors.BLUE); label.addHyperlinkListener(new HyperlinkAdapter() { @Override protected void hyperlinkActivated(HyperlinkEvent e) { action.run(); } }); myLinksPanel.add(label); return label; } @RequiredDispatchThread protected void executeAction(final String actionId) { final AnAction action = ActionManager.getInstance().getAction(actionId); final AnActionEvent event = new AnActionEvent(null, DataManager.getInstance().getDataContext(this), ActionPlaces.UNKNOWN, action.getTemplatePresentation(), ActionManager.getInstance(), 0); action.beforeActionPerformedUpdate(event); action.update(event); if (event.getPresentation().isEnabled() && event.getPresentation().isVisible()) { action.actionPerformed(event); } } @Override public Dimension getMinimumSize() { return new Dimension(0, 0); } @Nullable @Override public IntentionActionWithOptions getIntentionAction() { MyIntentionAction action = new MyIntentionAction(); return action.getOptions().isEmpty() ? null : action; } private class MyIntentionAction extends AbstractEmptyIntentionAction implements IntentionActionWithOptions, Iconable { private final List<IntentionAction> myOptions = new ArrayList<>(); private MyIntentionAction() { for (Component component : myLinksPanel.getComponents()) { if (component instanceof HyperlinkLabel) { myOptions.add(new MyLinkOption(((HyperlinkLabel)component))); } } if (myGearLabel.getIcon() != null) { myOptions.add(new MySettingsOption(myGearLabel)); } } @NotNull @Override public List<IntentionAction> getOptions() { return myOptions; } @Nls @NotNull @Override public String getText() { String text = myLabel.getText(); return StringUtil.isEmpty(text) ? EditorBundle.message("editor.notification.default.action.name") : StringUtil.shortenTextWithEllipsis(text, 50, 0); } @Nls @NotNull @Override public String getFamilyName() { return "Editor notification"; } @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { return true; } @Override public Icon getIcon(@IconFlags int flags) { return AllIcons.Actions.IntentionBulb; } } private static class MyLinkOption implements IntentionAction { private final HyperlinkLabel myLabel; private MyLinkOption(HyperlinkLabel label) { myLabel = label; } @Nls @NotNull @Override public String getText() { return myLabel.getText(); } @Nls @NotNull @Override public String getFamilyName() { return "Editor notification option"; } @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { return true; } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { myLabel.doClick(); } @Override public boolean startInWriteAction() { return false; } } private static class MySettingsOption implements IntentionAction, Iconable, LowPriorityAction { private final JLabel myLabel; private MySettingsOption(JLabel label) { myLabel = label; } @Nls @NotNull @Override public String getText() { return EditorBundle.message("editor.notification.settings.option.name"); } @Nls @NotNull @Override public String getFamilyName() { return "Editor notification settings"; } @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { return true; } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { myLabel.dispatchEvent(new MouseEvent(myLabel, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(), 0, 0, 0, 1, false)); myLabel.dispatchEvent(new MouseEvent(myLabel, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(), 0, 0, 0, 1, false)); myLabel.dispatchEvent(new MouseEvent(myLabel, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), 0, 0, 0, 1, false)); } @Override public boolean startInWriteAction() { return false; } @Override public Icon getIcon(@IconFlags int flags) { return myLabel.getIcon(); } } }