Extract InspectionPopupManager from EditorMarkupModelImpl

GitOrigin-RevId: 4b1848db5038e2d8d806893755c28d6ae96e74a8
This commit is contained in:
Kirill Kirichenko
2020-06-05 15:28:13 +03:00
committed by intellij-monorepo-bot
parent 545251fbea
commit ca282e6629
2 changed files with 391 additions and 335 deletions
@@ -9,13 +9,10 @@ import com.intellij.icons.AllIcons;
import com.intellij.ide.ActivityTracker;
import com.intellij.ide.DataManager;
import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.PowerSaveMode;
import com.intellij.ide.actions.ActionsCollector;
import com.intellij.ide.ui.LafManagerListener;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.UISettingsListener;
import com.intellij.internal.statistic.eventLog.FeatureUsageData;
import com.intellij.internal.statistic.service.fus.collectors.FUCounterUsageLogger;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.*;
@@ -38,7 +35,7 @@ import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.fileEditor.impl.EditorWindowHolder;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
@@ -47,13 +44,8 @@ import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBScrollBar;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.labels.DropDownLink;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.popup.util.PopupState;
import com.intellij.ui.scale.JBUIScale;
import com.intellij.util.Alarm;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.ObjectUtils;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
@@ -61,15 +53,12 @@ import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.*;
import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import com.intellij.xml.util.XmlStringUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.LabelUI;
import javax.swing.plaf.ScrollBarUI;
@@ -157,7 +146,7 @@ public final class EditorMarkupModelImpl extends MarkupModelImpl
private boolean isAnalyzing;
private boolean showNavigation;
private boolean reportErrorStripeInconsistency = true;
private InspectionPopupManager myPopupManager = new InspectionPopupManager();
private InspectionPopupManager myPopupManager;
private final Disposable resourcesDisposable = Disposer.newDisposable();
EditorMarkupModelImpl(@NotNull EditorImpl editor) {
@@ -166,6 +155,7 @@ public final class EditorMarkupModelImpl extends MarkupModelImpl
myEditorFragmentRenderer = new EditorFragmentRenderer(editor);
setMinMarkHeight(DaemonCodeAnalyzerSettings.getInstance().getErrorStripeMarkMinHeight());
myPopupManager = new InspectionPopupManager(() -> analyzerStatus, editor, new CompactViewAction());
showToolbar = EditorSettingsExternalizable.getInstance().isShowInspectionWidget();
trafficLightVisible = true;
@@ -1453,8 +1443,6 @@ public final class EditorMarkupModelImpl extends MarkupModelImpl
private static final Key<List<StatusItem>> EXPANDED_STATUS = new Key<>("EXPANDED_STATUS");
private static final Key<Boolean> TRANSLUCENT_STATE = new Key<>("TRANSLUCENT_STATE");
private static final int DELTA_X = 6;
private static final int DELTA_Y = 6;
private class StatusAction extends DumbAwareAction implements CustomComponentAction {
@Override
@@ -1857,329 +1845,33 @@ public final class EditorMarkupModelImpl extends MarkupModelImpl
}
}
private class InspectionPopupManager {
private final JPanel myContent = new JPanel(new GridBagLayout());
private final ComponentPopupBuilder myPopupBuilder;
private final Map<String, JProgressBar> myProgressBarMap = new HashMap<>();
private final AncestorListener myAncestorListener;
private final JBPopupListener myPopupListener;
private final PopupState myPopupState = new PopupState();
private final Alarm popupAlarm = new Alarm();
private JBPopup myPopup;
private boolean insidePopup;
private InspectionPopupManager() {
myContent.setOpaque(true);
myContent.setBackground(UIUtil.getToolTipBackground());
myPopupBuilder = JBPopupFactory.getInstance().createComponentPopupBuilder(myContent, null).
setCancelOnClickOutside(true).
setCancelCallback(() -> analyzerStatus == null || analyzerStatus.getController().canClosePopup());
myAncestorListener = new AncestorListenerAdapter() {
@Override
public void ancestorMoved(AncestorEvent event) {
hidePopup();
}
};
myPopupListener = new JBPopupListener() {
@Override
public void onClosed(@NotNull LightweightWindowEvent event) {
if (analyzerStatus != null) {
analyzerStatus.getController().onClosePopup();
}
myEditor.getComponent().removeAncestorListener(myAncestorListener);
}
};
myContent.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent event) {
insidePopup = true;
}
@Override
public void mouseExited(MouseEvent event) {
if (!myContent.getBounds().contains(event.getPoint())) {
insidePopup = false;
hidePopup();
}
}
});
}
private void updateUI() {
IJSwingUtilities.updateComponentTreeUI(myContent);
}
private void scheduleShow(@NotNull InputEvent event) {
popupAlarm.cancelAllRequests();
popupAlarm.addRequest(() -> showPopup(event), Registry.intValue("ide.tooltip.initialReshowDelay"));
}
private void scheduleHide() {
popupAlarm.cancelAllRequests();
popupAlarm.addRequest(() -> {
if (!insidePopup) {
hidePopup();
}
}, Registry.intValue("ide.tooltip.initialDelay.highlighter"));
}
private void showPopup(@NotNull InputEvent event) {
hidePopup();
if (myPopupState.isRecentlyHidden()) return; // do not show new popup
updateContentPanel(analyzerStatus.getController());
myPopup = myPopupBuilder.createPopup();
myPopup.addListener(myPopupListener);
myPopup.addListener(myPopupState);
myEditor.getComponent().addAncestorListener(myAncestorListener);
JComponent owner = (JComponent)event.getComponent();
Dimension size = myContent.getPreferredSize();
size.width = Math.max(size.width, JBUIScale.scale(296));
RelativePoint point = new RelativePoint(owner,
new Point(owner.getWidth() - owner.getInsets().right + JBUIScale.scale(DELTA_X) - size.width,
owner.getHeight() + JBUIScale.scale(DELTA_Y)));
myPopup.setSize(size);
myPopup.show(point);
}
private void hidePopup() {
if (myPopup != null && !myPopup.isDisposed()) {
myPopup.cancel();
}
myPopup = null;
}
private void updateContentPanel(@NotNull UIController controller) {
List<PassWrapper> passes = analyzerStatus.getPasses();
Set<String> presentableNames = ContainerUtil.map2Set(passes, p -> p.getPresentableName());
if (!presentableNames.isEmpty() && myProgressBarMap.keySet().equals(presentableNames)) {
for (PassWrapper pass : passes) {
myProgressBarMap.get(pass.getPresentableName()).setValue(pass.toPercent());
}
return;
}
myContent.removeAll();
GridBag gc = new GridBag().nextLine().next().
anchor(GridBagConstraints.LINE_START).
weightx(1).
fillCellHorizontally().
insets(10, 10, 10, 0);
boolean hasTitle = StringUtil.isNotEmpty(analyzerStatus.getTitle());
if (hasTitle) {
myContent.add(new JLabel(XmlStringUtil.wrapInHtml(analyzerStatus.getTitle())), gc);
}
else if (StringUtil.isNotEmpty(analyzerStatus.getDetails())) {
myContent.add(new JLabel(XmlStringUtil.wrapInHtml(analyzerStatus.getDetails())), gc);
}
else if (analyzerStatus.getExpandedStatus().size() > 0 && analyzerStatus.getAnalyzingType() != AnalyzingType.EMPTY) {
myContent.add(createDetailsPanel(), gc);
}
Presentation presentation = new Presentation();
presentation.setIcon(AllIcons.Actions.More);
presentation.putClientProperty(ActionButton.HIDE_DROPDOWN_ICON, Boolean.TRUE);
List<AnAction> actions = controller.getActions();
if (!actions.isEmpty()) {
ActionButton menuButton = new ActionButton(new MenuAction(actions),
presentation,
ActionPlaces.EDITOR_POPUP,
ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE);
myContent.add(menuButton, gc.next().anchor(GridBagConstraints.LINE_END).weightx(0).insets(10, 6, 10, 6));
}
myProgressBarMap.clear();
JPanel myProgressPanel = new NonOpaquePanel(new GridBagLayout());
GridBag progressGC = new GridBag();
for (PassWrapper pass : passes) {
myProgressPanel.add(new JLabel(pass.getPresentableName() + ": "),
progressGC.nextLine().next().anchor(GridBagConstraints.LINE_START).weightx(0).insets(0, 10, 0, 6));
JProgressBar pb = new JProgressBar(0, 100);
pb.setValue(pass.toPercent());
myProgressPanel.add(pb, progressGC.next().anchor(GridBagConstraints.LINE_START).weightx(1).fillCellHorizontally().insets(0, 0, 0, 6));
myProgressBarMap.put(pass.getPresentableName(), pb);
}
myContent.add(myProgressPanel, gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1));
if (hasTitle) {
int topIndent = !myProgressBarMap.isEmpty() ? 10 : 0;
gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1).insets(topIndent, 10, 10, 6);
if (StringUtil.isNotEmpty(analyzerStatus.getDetails())) {
myContent.add(new JLabel(XmlStringUtil.wrapInHtml(analyzerStatus.getDetails())), gc);
}
else if (analyzerStatus.getExpandedStatus().size() > 0 && analyzerStatus.getAnalyzingType() != AnalyzingType.EMPTY) {
myContent.add(createDetailsPanel(), gc);
}
}
if (!Experiments.getInstance().isFeatureEnabled("problems.view.enabled")) {
JLabel openProblemsViewLabel = new TrackableLinkLabel(EditorBundle.message("iw.open.problems.view"), () -> {
hidePopup();
controller.openProblemsView();
});
myContent.add(openProblemsViewLabel,
gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1).insets(10, 10, 10, 0));
}
myContent.add(createLowerPanel(controller),
gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1));
}
private void updateVisiblePopup() {
if (myPopup != null && myPopup.isVisible()) {
updateContentPanel(analyzerStatus.getController());
Dimension size = myContent.getPreferredSize();
size.width = Math.max(size.width, JBUIScale.scale(296));
myPopup.setSize(size);
}
}
private @NotNull JComponent createDetailsPanel() {
StringBuilder text = new StringBuilder();
for (int i = 0; i < analyzerStatus.getExpandedStatus().size(); i++) {
boolean last = i == analyzerStatus.getExpandedStatus().size() - 1;
StatusItem item = analyzerStatus.getExpandedStatus().get(i);
text.append(item.getText()).append(" ").append(item.getType());
if (!last) {
text.append(", ");
}
else if (analyzerStatus.getAnalyzingType() != AnalyzingType.COMPLETE) {
text.append(" ").append(EditorBundle.message("iw.found.so.far.suffix"));
}
}
return new JLabel(text.toString());
}
private @NotNull JPanel createLowerPanel(@NotNull UIController controller) {
JPanel panel = new JPanel(new GridBagLayout());
GridBag gc = new GridBag().nextLine();
if (PowerSaveMode.isEnabled()) {
panel.add(new TrackableLinkLabel(EditorBundle.message("iw.disable.powersave"), () ->{
PowerSaveMode.setEnabled(false);
hidePopup();
}),
gc.next().anchor(GridBagConstraints.LINE_START));
}
else {
List<LanguageHighlightLevel> levels = controller.getHighlightLevels();
if (levels.size() == 1) {
JLabel highlightLabel = new JLabel(EditorBundle.message("iw.highlight.label") + " ");
highlightLabel.setForeground(JBUI.CurrentTheme.Link.linkColor());
panel.add(highlightLabel, gc.next().anchor(GridBagConstraints.LINE_START));
panel.add(createDropDownLink(levels.get(0), controller), gc.next());
}
else if (levels.size() > 1) {
for(LanguageHighlightLevel level: levels) {
JLabel highlightLabel = new JLabel(level.getLangID() + ": ");
highlightLabel.setForeground(JBUI.CurrentTheme.Link.linkColor());
panel.add(highlightLabel, gc.next().anchor(GridBagConstraints.LINE_START).gridx > 0 ? gc.insetLeft(8) : gc);
panel.add(createDropDownLink(level, controller), gc.next());
}
}
}
panel.add(Box.createHorizontalGlue(), gc.next().fillCellHorizontally().weightx(1.0));
controller.fillHectorPanels(panel, gc);
panel.setOpaque(true);
panel.setBackground(UIUtil.getToolTipActionBackground());
panel.setBorder(JBUI.Borders.empty(4, 10));
return panel;
}
private @NotNull DropDownLink<InspectionsLevel> createDropDownLink(@NotNull LanguageHighlightLevel level, @NotNull UIController controller) {
return new DropDownLink<>(level.getLevel(),
controller.getAvailableLevels(),
inspectionsLevel -> {
controller.setHighLightLevel(level.copy(level.getLangID(), inspectionsLevel));
myContent.revalidate();
Dimension size = myContent.getPreferredSize();
size.width = Math.max(size.width, JBUIScale.scale(296));
myPopup.setSize(size);
// Update statistics
FeatureUsageData data = new FeatureUsageData().
addProject(myEditor.getProject()).
addLanguage(level.getLangID()).
addData("level", inspectionsLevel.toString());
FUCounterUsageLogger.getInstance().logEvent("inspection.widget", "highlight.level.changed", data);
}, true);
}
}
private class MenuAction extends DefaultActionGroup implements HintManagerImpl.ActionToIgnore {
private MenuAction(@NotNull List<? extends AnAction> actions) {
setPopup(true);
addAll(actions);
add(new ToggleAction(EditorBundle.message("iw.compact.view")) {
@Override
public boolean isSelected(@NotNull AnActionEvent e) {
return !showToolbar;
}
@Override
public void setSelected(@NotNull AnActionEvent e, boolean state) {
showToolbar = !state;
EditorSettingsExternalizable.getInstance().setShowInspectionWidget(showToolbar);
updateTrafficLightVisibility();
ActionsCollector.getInstance().record(e.getProject(), this, e, null);
}
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);
e.getPresentation().setEnabled(analyzerStatus == null || analyzerStatus.getController().enableToolbar());
}
@Override
public boolean isDumbAware() {
return true;
}
});
}
}
private static class TrackableLinkLabel extends LinkLabel<Object> {
private InputEvent myEvent;
private TrackableLinkLabel(@NotNull String text, @NotNull Runnable action) {
super(text, null);
setListener((__, ___) -> {
action.run();
ActionsCollector.getInstance().record(null, myEvent, getClass());
}, null);
public class CompactViewAction extends ToggleAction {
CompactViewAction() {
super (EditorBundle.message("iw.compact.view"));
}
@Override
public void doClick(InputEvent e) {
myEvent = e;
super.doClick(e);
public boolean isSelected(@NotNull AnActionEvent e) {
return !showToolbar;
}
@Override
public void setSelected(@NotNull AnActionEvent e, boolean state) {
showToolbar = !state;
EditorSettingsExternalizable.getInstance().setShowInspectionWidget(showToolbar);
updateTrafficLightVisibility();
ActionsCollector.getInstance().record(e.getProject(), this, e, null);
}
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);
e.getPresentation().setEnabled(analyzerStatus == null || analyzerStatus.getController().enableToolbar());
}
@Override
public boolean isDumbAware() {
return true;
}
}
}
@@ -0,0 +1,364 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.editor.impl;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.icons.AllIcons;
import com.intellij.ide.PowerSaveMode;
import com.intellij.ide.actions.ActionsCollector;
import com.intellij.internal.statistic.eventLog.FeatureUsageData;
import com.intellij.internal.statistic.service.fus.collectors.FUCounterUsageLogger;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.application.Experiments;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorBundle;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.AncestorListenerAdapter;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.labels.DropDownLink;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.popup.util.PopupState;
import com.intellij.ui.scale.JBUIScale;
import com.intellij.util.Alarm;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
class InspectionPopupManager {
private static final int DELTA_X = 6;
private static final int DELTA_Y = 6;
private final Supplier<AnalyzerStatus> statusSupplier;
private final Editor myEditor;
private final AnAction compactViewAction;
private final JPanel myContent = new JPanel(new GridBagLayout());
private final ComponentPopupBuilder myPopupBuilder;
private final Map<String, JProgressBar> myProgressBarMap = new HashMap<>();
private final AncestorListener myAncestorListener;
private final JBPopupListener myPopupListener;
private final PopupState myPopupState = new PopupState();
private final Alarm popupAlarm = new Alarm();
private JBPopup myPopup;
private boolean insidePopup;
InspectionPopupManager(@NotNull Supplier<AnalyzerStatus> statusSupplier, @NotNull Editor editor, @NotNull AnAction compactViewAction) {
this.statusSupplier = statusSupplier;
this.myEditor = editor;
this.compactViewAction = compactViewAction;
myContent.setOpaque(true);
myContent.setBackground(UIUtil.getToolTipBackground());
myPopupBuilder = JBPopupFactory.getInstance().createComponentPopupBuilder(myContent, null).
setCancelOnClickOutside(true).
setCancelCallback(() -> getAnalyzerStatus() == null || getAnalyzerStatus().getController().canClosePopup());
myAncestorListener = new AncestorListenerAdapter() {
@Override
public void ancestorMoved(AncestorEvent event) {
hidePopup();
}
};
myPopupListener = new JBPopupListener() {
@Override
public void onClosed(@NotNull LightweightWindowEvent event) {
if (statusSupplier.get() != null) {
statusSupplier.get().getController().onClosePopup();
}
myEditor.getComponent().removeAncestorListener(myAncestorListener);
}
};
myContent.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent event) {
insidePopup = true;
}
@Override
public void mouseExited(MouseEvent event) {
if (!myContent.getBounds().contains(event.getPoint())) {
insidePopup = false;
hidePopup();
}
}
});
}
void updateUI() {
IJSwingUtilities.updateComponentTreeUI(myContent);
}
void scheduleShow(@NotNull InputEvent event) {
popupAlarm.cancelAllRequests();
popupAlarm.addRequest(() -> showPopup(event), Registry.intValue("ide.tooltip.initialReshowDelay"));
}
void scheduleHide() {
popupAlarm.cancelAllRequests();
popupAlarm.addRequest(() -> {
if (!insidePopup) {
hidePopup();
}
}, Registry.intValue("ide.tooltip.initialDelay.highlighter"));
}
void showPopup(@NotNull InputEvent event) {
hidePopup();
if (myPopupState.isRecentlyHidden()) return; // do not show new popup
updateContentPanel(getAnalyzerStatus().getController());
myPopup = myPopupBuilder.createPopup();
myPopup.addListener(myPopupListener);
myPopup.addListener(myPopupState);
myEditor.getComponent().addAncestorListener(myAncestorListener);
JComponent owner = (JComponent)event.getComponent();
Dimension size = myContent.getPreferredSize();
size.width = Math.max(size.width, JBUIScale.scale(296));
RelativePoint point = new RelativePoint(owner,
new Point(owner.getWidth() - owner.getInsets().right + JBUIScale.scale(DELTA_X) - size.width,
owner.getHeight() + JBUIScale.scale(DELTA_Y)));
myPopup.setSize(size);
myPopup.show(point);
}
void hidePopup() {
if (myPopup != null && !myPopup.isDisposed()) {
myPopup.cancel();
}
myPopup = null;
}
private AnalyzerStatus getAnalyzerStatus() {
return statusSupplier.get();
}
private void updateContentPanel(@NotNull UIController controller) {
java.util.List<PassWrapper> passes = getAnalyzerStatus().getPasses();
Set<String> presentableNames = ContainerUtil.map2Set(passes, p -> p.getPresentableName());
if (!presentableNames.isEmpty() && myProgressBarMap.keySet().equals(presentableNames)) {
for (PassWrapper pass : passes) {
myProgressBarMap.get(pass.getPresentableName()).setValue(pass.toPercent());
}
return;
}
myContent.removeAll();
GridBag gc = new GridBag().nextLine().next().
anchor(GridBagConstraints.LINE_START).
weightx(1).
fillCellHorizontally().
insets(10, 10, 10, 0);
boolean hasTitle = StringUtil.isNotEmpty(getAnalyzerStatus().getTitle());
if (hasTitle) {
myContent.add(new JLabel(XmlStringUtil.wrapInHtml(getAnalyzerStatus().getTitle())), gc);
}
else if (StringUtil.isNotEmpty(getAnalyzerStatus().getDetails())) {
myContent.add(new JLabel(XmlStringUtil.wrapInHtml(getAnalyzerStatus().getDetails())), gc);
}
else if (getAnalyzerStatus().getExpandedStatus().size() > 0 && getAnalyzerStatus().getAnalyzingType() != AnalyzingType.EMPTY) {
myContent.add(createDetailsPanel(), gc);
}
Presentation presentation = new Presentation();
presentation.setIcon(AllIcons.Actions.More);
presentation.putClientProperty(ActionButton.HIDE_DROPDOWN_ICON, Boolean.TRUE);
java.util.List<AnAction> actions = controller.getActions();
if (!actions.isEmpty()) {
ActionButton menuButton = new ActionButton(new MenuAction(actions, compactViewAction),
presentation,
ActionPlaces.EDITOR_POPUP,
ActionToolbar.DEFAULT_MINIMUM_BUTTON_SIZE);
myContent.add(menuButton, gc.next().anchor(GridBagConstraints.LINE_END).weightx(0).insets(10, 6, 10, 6));
}
myProgressBarMap.clear();
JPanel myProgressPanel = new NonOpaquePanel(new GridBagLayout());
GridBag progressGC = new GridBag();
for (PassWrapper pass : passes) {
myProgressPanel.add(new JLabel(pass.getPresentableName() + ": "),
progressGC.nextLine().next().anchor(GridBagConstraints.LINE_START).weightx(0).insets(0, 10, 0, 6));
JProgressBar pb = new JProgressBar(0, 100);
pb.setValue(pass.toPercent());
myProgressPanel.add(pb, progressGC.next().anchor(GridBagConstraints.LINE_START).weightx(1).fillCellHorizontally().insets(0, 0, 0, 6));
myProgressBarMap.put(pass.getPresentableName(), pb);
}
myContent.add(myProgressPanel, gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1));
if (hasTitle) {
int topIndent = !myProgressBarMap.isEmpty() ? 10 : 0;
gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1).insets(topIndent, 10, 10, 6);
if (StringUtil.isNotEmpty(getAnalyzerStatus().getDetails())) {
myContent.add(new JLabel(XmlStringUtil.wrapInHtml(getAnalyzerStatus().getDetails())), gc);
}
else if (getAnalyzerStatus().getExpandedStatus().size() > 0 && getAnalyzerStatus().getAnalyzingType() != AnalyzingType.EMPTY) {
myContent.add(createDetailsPanel(), gc);
}
}
if (!Experiments.getInstance().isFeatureEnabled("problems.view.enabled")) {
JLabel openProblemsViewLabel = new TrackableLinkLabel(EditorBundle.message("iw.open.problems.view"), () -> {
hidePopup();
controller.openProblemsView();
});
myContent.add(openProblemsViewLabel,
gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1).insets(10, 10, 10, 0));
}
myContent.add(createLowerPanel(controller),
gc.nextLine().next().anchor(GridBagConstraints.LINE_START).fillCellHorizontally().coverLine().weightx(1));
}
void updateVisiblePopup() {
if (myPopup != null && myPopup.isVisible()) {
updateContentPanel(getAnalyzerStatus().getController());
Dimension size = myContent.getPreferredSize();
size.width = Math.max(size.width, JBUIScale.scale(296));
myPopup.setSize(size);
}
}
private @NotNull JComponent createDetailsPanel() {
StringBuilder text = new StringBuilder();
for (int i = 0; i < getAnalyzerStatus().getExpandedStatus().size(); i++) {
boolean last = i == getAnalyzerStatus().getExpandedStatus().size() - 1;
StatusItem item = getAnalyzerStatus().getExpandedStatus().get(i);
text.append(item.getText()).append(" ").append(item.getType());
if (!last) {
text.append(", ");
}
else if (getAnalyzerStatus().getAnalyzingType() != AnalyzingType.COMPLETE) {
text.append(" ").append(EditorBundle.message("iw.found.so.far.suffix"));
}
}
return new JLabel(text.toString());
}
private @NotNull JPanel createLowerPanel(@NotNull UIController controller) {
JPanel panel = new JPanel(new GridBagLayout());
GridBag gc = new GridBag().nextLine();
if (PowerSaveMode.isEnabled()) {
panel.add(new TrackableLinkLabel(EditorBundle.message("iw.disable.powersave"), () ->{
PowerSaveMode.setEnabled(false);
hidePopup();
}),
gc.next().anchor(GridBagConstraints.LINE_START));
}
else {
java.util.List<LanguageHighlightLevel> levels = controller.getHighlightLevels();
if (levels.size() == 1) {
JLabel highlightLabel = new JLabel(EditorBundle.message("iw.highlight.label") + " ");
highlightLabel.setForeground(JBUI.CurrentTheme.Link.linkColor());
panel.add(highlightLabel, gc.next().anchor(GridBagConstraints.LINE_START));
panel.add(createDropDownLink(levels.get(0), controller), gc.next());
}
else if (levels.size() > 1) {
for(LanguageHighlightLevel level: levels) {
JLabel highlightLabel = new JLabel(level.getLangID() + ": ");
highlightLabel.setForeground(JBUI.CurrentTheme.Link.linkColor());
panel.add(highlightLabel, gc.next().anchor(GridBagConstraints.LINE_START).gridx > 0 ? gc.insetLeft(8) : gc);
panel.add(createDropDownLink(level, controller), gc.next());
}
}
}
panel.add(Box.createHorizontalGlue(), gc.next().fillCellHorizontally().weightx(1.0));
controller.fillHectorPanels(panel, gc);
panel.setOpaque(true);
panel.setBackground(UIUtil.getToolTipActionBackground());
panel.setBorder(JBUI.Borders.empty(4, 10));
return panel;
}
private @NotNull DropDownLink<InspectionsLevel> createDropDownLink(@NotNull LanguageHighlightLevel level, @NotNull UIController controller) {
return new DropDownLink<>(level.getLevel(),
controller.getAvailableLevels(),
inspectionsLevel -> {
controller.setHighLightLevel(level.copy(level.getLangID(), inspectionsLevel));
myContent.revalidate();
Dimension size = myContent.getPreferredSize();
size.width = Math.max(size.width, JBUIScale.scale(296));
myPopup.setSize(size);
// Update statistics
FeatureUsageData data = new FeatureUsageData().
addProject(myEditor.getProject()).
addLanguage(level.getLangID()).
addData("level", inspectionsLevel.toString());
FUCounterUsageLogger.getInstance().logEvent("inspection.widget", "highlight.level.changed", data);
}, true);
}
private static class MenuAction extends DefaultActionGroup implements HintManagerImpl.ActionToIgnore {
private MenuAction(@NotNull List<? extends AnAction> actions, @NotNull AnAction compactViewAction) {
setPopup(true);
addAll(actions);
add(compactViewAction);
}
}
private static class TrackableLinkLabel extends LinkLabel<Object> {
private InputEvent myEvent;
private TrackableLinkLabel(@NotNull String text, @NotNull Runnable action) {
super(text, null);
setListener((__, ___) -> {
action.run();
ActionsCollector.getInstance().record(null, myEvent, getClass());
}, null);
}
@Override
public void doClick(InputEvent e) {
myEvent = e;
super.doClick(e);
}
}
}