mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-149210 Rework IDE notifications
This commit is contained in:
@@ -188,7 +188,7 @@ public class LinkLabel<T> extends JLabel {
|
||||
private final JBRectangle textR = new JBRectangle();
|
||||
private final JBRectangle viewR = new JBRectangle();
|
||||
|
||||
private boolean isInClickableArea(Point pt) {
|
||||
protected boolean isInClickableArea(Point pt) {
|
||||
iconR.clear();
|
||||
textR.clear();
|
||||
final Insets insets = getInsets(null);
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.*;
|
||||
import com.intellij.openapi.wm.impl.IdeFrameImpl;
|
||||
import com.intellij.ui.BalloonLayoutData;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.content.Content;
|
||||
@@ -49,9 +48,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -93,14 +90,8 @@ public class EventLog {
|
||||
}
|
||||
}
|
||||
|
||||
public static void showNotification(@NotNull String groupId, @NotNull String id) {
|
||||
Window frame = IdeFrameImpl.getActiveFrame();
|
||||
if (frame instanceof IdeFrame) {
|
||||
Project project = ((IdeFrame)frame).getProject();
|
||||
if (project != null) {
|
||||
getProjectComponent(project).showNotification(groupId, id);
|
||||
}
|
||||
}
|
||||
public static void showNotification(@NotNull Project project, @NotNull String groupId, @NotNull String id) {
|
||||
getProjectComponent(project).showNotification(groupId, id);
|
||||
}
|
||||
|
||||
private static EventLog getApplicationComponent() {
|
||||
@@ -478,7 +469,7 @@ public class EventLog {
|
||||
});
|
||||
}
|
||||
|
||||
void showNotification(@NotNull final String groupId, @NotNull final String id) {
|
||||
private void showNotification(@NotNull final String groupId, @NotNull final String id) {
|
||||
ToolWindow eventLog = getEventLog(myProject);
|
||||
if (eventLog != null) {
|
||||
activate(eventLog, groupId, new Runnable() {
|
||||
|
||||
@@ -30,4 +30,7 @@ public class NotificationGroupBean extends AbstractExtensionPointBean {
|
||||
|
||||
@Attribute("replaceTitle")
|
||||
public String replaceTitle;
|
||||
|
||||
@Attribute("shortTitle")
|
||||
public String shortTitle;
|
||||
}
|
||||
+11
@@ -35,6 +35,7 @@ public class NotificationParentGroup {
|
||||
private static Map<NotificationParentGroupBean, List<NotificationParentGroupBean>> myChildren;
|
||||
private static Map<String, NotificationParentGroupBean> myGroupToParent;
|
||||
private static Map<String, String> myReplaceTitles;
|
||||
private static Map<String, String> myShortTitles;
|
||||
|
||||
private static void prepareInfo() {
|
||||
if (myParents == null) {
|
||||
@@ -60,6 +61,7 @@ public class NotificationParentGroup {
|
||||
|
||||
myGroupToParent = new HashMap<>();
|
||||
myReplaceTitles = new HashMap<>();
|
||||
myShortTitles = new HashMap<>();
|
||||
for (NotificationGroupBean bean : EP_CHILD_NAME.getExtensions()) {
|
||||
NotificationParentGroupBean parent = myParents.get(bean.parentId);
|
||||
if (parent != null) {
|
||||
@@ -68,6 +70,9 @@ public class NotificationParentGroup {
|
||||
if (bean.replaceTitle != null) {
|
||||
myReplaceTitles.put(bean.groupId, bean.replaceTitle);
|
||||
}
|
||||
if (bean.shortTitle != null) {
|
||||
myShortTitles.put(bean.groupId, bean.shortTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +84,12 @@ public class NotificationParentGroup {
|
||||
return myReplaceTitles.get(groupId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getShortTitle(@NotNull String groupId) {
|
||||
prepareInfo();
|
||||
return myShortTitles.get(groupId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<NotificationParentGroupBean> getChildren(@NotNull NotificationParentGroupBean parent) {
|
||||
prepareInfo();
|
||||
|
||||
+64
-45
@@ -50,8 +50,10 @@ import com.intellij.ui.components.labels.LinkListener;
|
||||
import com.intellij.ui.components.panels.HorizontalLayout;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.FontUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.ui.AbstractLayoutManager;
|
||||
import com.intellij.util.ui.ButtonlessScrollBarUI;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
@@ -68,6 +70,7 @@ import javax.swing.text.BadLocationException;
|
||||
import java.awt.*;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
@@ -249,7 +252,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
layoutDataRef.set(layoutData);
|
||||
}
|
||||
else {
|
||||
List<BalloonLayoutData.MergeInfo> mergeData = ((BalloonLayoutImpl)layout).preMerge(notification);
|
||||
BalloonLayoutData.MergeInfo mergeData = ((BalloonLayoutImpl)layout).preMerge(notification);
|
||||
if (mergeData != null) {
|
||||
BalloonLayoutData layoutData = new BalloonLayoutData();
|
||||
layoutData.mergeData = mergeData;
|
||||
@@ -494,7 +497,6 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
if (NotificationsConfigurationImpl.getSettings(notification.getGroupId()).isShouldLog()) {
|
||||
layoutData.groupId = notification.getGroupId();
|
||||
layoutData.id = notification.id;
|
||||
layoutData.status = EventLog.formatForLog(notification, "").status;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -502,7 +504,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
}
|
||||
layoutDataRef.set(layoutData);
|
||||
|
||||
boolean actions = !notification.getActions().isEmpty() || layoutData.mergeData != null;
|
||||
boolean actions = !notification.getActions().isEmpty();
|
||||
boolean showFullContent = layoutData.showFullContent || notification instanceof NotificationActionProvider;
|
||||
|
||||
Color foregroundR = Gray._0;
|
||||
@@ -732,7 +734,11 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
}
|
||||
|
||||
if (buttons == null && actions) {
|
||||
createActionPanel(notification, layoutData.mergeData, centerPanel, layoutData.configuration.actionGap);
|
||||
createActionPanel(notification, centerPanel, layoutData.configuration.actionGap);
|
||||
}
|
||||
|
||||
if (layoutData.mergeData != null) {
|
||||
createMergeAction(layoutData, content);
|
||||
}
|
||||
|
||||
text.setSize(text.getPreferredSize());
|
||||
@@ -775,10 +781,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
return balloon;
|
||||
}
|
||||
|
||||
private static void createActionPanel(@NotNull final Notification notification,
|
||||
@Nullable final List<BalloonLayoutData.MergeInfo> mergeData,
|
||||
@NotNull JPanel centerPanel,
|
||||
int gap) {
|
||||
private static void createActionPanel(@NotNull final Notification notification, @NotNull JPanel centerPanel, int gap) {
|
||||
JPanel actionPanel = new NonOpaquePanel(new HorizontalLayout(gap, SwingConstants.CENTER));
|
||||
centerPanel.add(BorderLayout.SOUTH, actionPanel);
|
||||
|
||||
@@ -815,45 +818,61 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
}
|
||||
}, action));
|
||||
}
|
||||
}
|
||||
|
||||
if (mergeData != null) {
|
||||
final int size = mergeData.size();
|
||||
if (size == 1) {
|
||||
actionPanel.add(
|
||||
HorizontalLayout.RIGHT,
|
||||
new LinkLabel<BalloonLayoutData.MergeInfo>("History", null, new LinkListener<BalloonLayoutData.MergeInfo>() {
|
||||
@Override
|
||||
public void linkSelected(LinkLabel aSource, BalloonLayoutData.MergeInfo info) {
|
||||
EventLog.showNotification(info.groupId, info.id);
|
||||
}
|
||||
}, mergeData.get(0)) {
|
||||
@Override
|
||||
protected String getStatusBarText() {
|
||||
return getLinkData().status;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
actionPanel.add(
|
||||
HorizontalLayout.RIGHT,
|
||||
new DropDownAction("History", new LinkListener<Void>() {
|
||||
@Override
|
||||
public void linkSelected(LinkLabel link, Void aLinkData) {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
for (int i = 0; i < size; i++) {
|
||||
BalloonLayoutData.MergeInfo info = mergeData.get(i);
|
||||
group.add(new AnAction(String.valueOf(i + 1), info.status, null) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
EventLog.showNotification(info.groupId, info.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
showPopup(link, group);
|
||||
}
|
||||
}));
|
||||
}
|
||||
private static void createMergeAction(@NotNull final BalloonLayoutData layoutData, @NotNull JPanel panel) {
|
||||
StringBuilder title = new StringBuilder().append(layoutData.mergeData.count).append(" more");
|
||||
String shortTitle = NotificationParentGroup.getShortTitle(layoutData.groupId);
|
||||
if (shortTitle != null) {
|
||||
title.append(" from ").append(shortTitle);
|
||||
}
|
||||
|
||||
LinkLabel<BalloonLayoutData> action = new LinkLabel<BalloonLayoutData>(
|
||||
title.toString(), null,
|
||||
new LinkListener<BalloonLayoutData>() {
|
||||
@Override
|
||||
public void linkSelected(LinkLabel aSource, BalloonLayoutData layoutData) {
|
||||
EventLog.showNotification(layoutData.project, layoutData.groupId, layoutData.mergeData.linkId);
|
||||
}
|
||||
}, layoutData) {
|
||||
@Override
|
||||
protected boolean isInClickableArea(Point pt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Color getTextColor() {
|
||||
return new JBColor(0x666666, 0x8C8C8C);
|
||||
}
|
||||
};
|
||||
|
||||
action.setFont(FontUtil.minusOne(action.getFont()));
|
||||
action.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
action.setPaintUnderline(false);
|
||||
|
||||
AbstractLayoutManager layout = new AbstractLayoutManager() {
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent) {
|
||||
return new Dimension(parent.getWidth(), JBUI.scale(20) + 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container parent) {
|
||||
parent.getComponent(0).setBounds(2, 1, parent.getWidth() - 4, JBUI.scale(20));
|
||||
}
|
||||
};
|
||||
JPanel mergePanel = new NonOpaquePanel(layout) {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
g.setColor(new JBColor(0xE3E3E3, 0x3A3C3D));
|
||||
((Graphics2D)g).fill(new Rectangle2D.Double(1.5, 1, getWidth() - 2.5, getHeight() - 2));
|
||||
g.setColor(new JBColor(0xDBDBDB, 0x353738));
|
||||
((Graphics2D)g).draw(new Rectangle2D.Double(2, 0, getWidth() - 3.5, 0.5));
|
||||
}
|
||||
};
|
||||
mergePanel.add(action);
|
||||
panel.add(BorderLayout.SOUTH, mergePanel);
|
||||
}
|
||||
|
||||
public static int calculateContentHeight(int lines) {
|
||||
|
||||
@@ -17,8 +17,7 @@ package com.intellij.ui;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
@@ -26,8 +25,7 @@ import java.util.List;
|
||||
public class BalloonLayoutData {
|
||||
public String groupId;
|
||||
public String id;
|
||||
public String status;
|
||||
public List<MergeInfo> mergeData;
|
||||
public MergeInfo mergeData;
|
||||
|
||||
public boolean showFullContent;
|
||||
|
||||
@@ -50,17 +48,18 @@ public class BalloonLayoutData {
|
||||
|
||||
public Runnable lafHandler;
|
||||
|
||||
public MergeInfo getMergeInfo() {
|
||||
MergeInfo info = new MergeInfo();
|
||||
info.groupId = groupId;
|
||||
info.id = id;
|
||||
info.status = status;
|
||||
return info;
|
||||
@NotNull
|
||||
public MergeInfo merge() {
|
||||
return mergeData == null ? new MergeInfo(id, 1) : new MergeInfo(mergeData.linkId, mergeData.count + 1);
|
||||
}
|
||||
|
||||
public static class MergeInfo {
|
||||
public String groupId;
|
||||
public String id;
|
||||
public String status;
|
||||
public String linkId;
|
||||
public int count;
|
||||
|
||||
public MergeInfo(@NotNull String linkId, int count) {
|
||||
this.linkId = linkId;
|
||||
this.count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,6 +109,7 @@ public class BalloonLayoutImpl implements BalloonLayout {
|
||||
Balloon merge = merge(layoutData);
|
||||
if (merge == null) {
|
||||
if (NotificationsManagerImpl.newEnabled() &&
|
||||
getVisibleCount() > 0 &&
|
||||
layoutData instanceof BalloonLayoutData &&
|
||||
((BalloonLayoutData)layoutData).groupId != null) {
|
||||
int index = -1;
|
||||
@@ -123,7 +124,7 @@ public class BalloonLayoutImpl implements BalloonLayout {
|
||||
}
|
||||
}
|
||||
|
||||
if (count == getVisibleCount()) {
|
||||
if (count > 0 && count == getVisibleCount()) {
|
||||
remove(myBalloons.get(index));
|
||||
}
|
||||
}
|
||||
@@ -186,17 +187,12 @@ public class BalloonLayoutImpl implements BalloonLayout {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<BalloonLayoutData.MergeInfo> preMerge(@NotNull Notification notification) {
|
||||
public BalloonLayoutData.MergeInfo preMerge(@NotNull Notification notification) {
|
||||
Balloon balloon = merge(notification.getGroupId());
|
||||
if (balloon != null) {
|
||||
BalloonLayoutData layoutData = myLayoutData.get(balloon);
|
||||
if (layoutData != null) {
|
||||
List<BalloonLayoutData.MergeInfo> mergeData = new ArrayList<>();
|
||||
if (layoutData.mergeData != null) {
|
||||
mergeData.addAll(layoutData.mergeData);
|
||||
}
|
||||
mergeData.add(layoutData.getMergeInfo());
|
||||
return mergeData;
|
||||
return layoutData.merge();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -218,9 +214,8 @@ public class BalloonLayoutImpl implements BalloonLayout {
|
||||
myBalloons.remove(balloon);
|
||||
BalloonLayoutData layoutData = myLayoutData.remove(balloon);
|
||||
if (layoutData != null) {
|
||||
layoutData.id = null;
|
||||
layoutData.groupId = null;
|
||||
layoutData.status = null;
|
||||
layoutData.id = null;
|
||||
layoutData.mergeData = null;
|
||||
}
|
||||
if (hide) {
|
||||
|
||||
@@ -40,4 +40,9 @@ public class FontUtil {
|
||||
public static String spaceAndThinSpace() {
|
||||
return " " + canDisplay(UIUtil.getLabelFont(), '\u2009', " ");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Font minusOne(@NotNull Font font) {
|
||||
return font.deriveFont(font.getSize() - 1f);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user