mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-153807 Welcome screen notifications
This commit is contained in:
+64
-38
@@ -43,6 +43,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeBalloonLayoutImpl;
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.GradientViewport;
|
||||
@@ -81,6 +82,9 @@ import java.util.List;
|
||||
* @author spleaner
|
||||
*/
|
||||
public class NotificationsManagerImpl extends NotificationsManager {
|
||||
public static final Color FILL_COLOR = new JBColor(Gray._242, new Color(78, 80, 82));
|
||||
public static final Color BORDER_COLOR = new JBColor(Gray._178.withAlpha(205), new Color(86, 90, 92, 205));
|
||||
|
||||
public NotificationsManagerImpl() {
|
||||
ApplicationManager.getApplication().getMessageBus().connect().subscribe(Notifications.TOPIC, new MyNotificationListener(null));
|
||||
}
|
||||
@@ -180,6 +184,9 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
case BALLOON:
|
||||
default:
|
||||
Balloon balloon = notifyByBalloon(notification, type, project);
|
||||
if (project == null || project.isDefault()) {
|
||||
return;
|
||||
}
|
||||
if (!settings.isShouldLog() || type == NotificationDisplayType.STICKY_BALLOON) {
|
||||
if (balloon == null) {
|
||||
notification.expire();
|
||||
@@ -250,6 +257,8 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
if (project == null || project.isDefault()) {
|
||||
BalloonLayoutData layoutData = new BalloonLayoutData();
|
||||
layoutData.groupId = "";
|
||||
layoutData.welcomeScreen = layout instanceof WelcomeBalloonLayoutImpl;
|
||||
layoutData.type = notification.getType();
|
||||
layoutDataRef.set(layoutData);
|
||||
}
|
||||
else {
|
||||
@@ -286,7 +295,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
((BalloonImpl)balloon).setHideOnClickOutside(true);
|
||||
}
|
||||
else //noinspection ConstantConditions
|
||||
if (noProjects) {
|
||||
if (noProjects && !newEnabled()) {
|
||||
projectManager.addProjectManagerListener(new ProjectManagerAdapter() {
|
||||
@Override
|
||||
public void projectOpened(Project project) {
|
||||
@@ -512,8 +521,6 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
Color foregroundD = Gray._191;
|
||||
final Color foreground = new JBColor(foregroundR, foregroundD);
|
||||
|
||||
final JBColor fillColor = new JBColor(Gray._242, new Color(78, 80, 82));
|
||||
|
||||
final JEditorPane text = new JEditorPane() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
@@ -563,8 +570,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
text.setCaretPosition(0);
|
||||
}
|
||||
|
||||
final JScrollPane pane = ScrollPaneFactory.createScrollPane(text, true);
|
||||
pane.setOpaque(false);
|
||||
final JScrollPane pane = createBalloonScrollPane(text, false);
|
||||
|
||||
pane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
|
||||
@Override
|
||||
@@ -593,12 +599,15 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
layoutData.maxScrollHeight = Math.min(layoutData.fullHeight, calculateContentHeight(10));
|
||||
layoutData.configuration = BalloonLayoutConfiguration.create(notification, layoutData, actions);
|
||||
|
||||
if (!showFullContent && layoutData.maxScrollHeight != layoutData.fullHeight) {
|
||||
if (layoutData.welcomeScreen) {
|
||||
layoutData.maxScrollHeight = layoutData.fullHeight;
|
||||
}
|
||||
else if (!showFullContent && layoutData.maxScrollHeight != layoutData.fullHeight) {
|
||||
pane.setViewport(new GradientViewport(text, JBUI.insets(10, 0), true) {
|
||||
@Nullable
|
||||
@Override
|
||||
protected Color getViewColor() {
|
||||
return fillColor;
|
||||
return FILL_COLOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -610,13 +619,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
});
|
||||
}
|
||||
|
||||
pane.getViewport().setOpaque(false);
|
||||
if (!Registry.is("ide.scroll.new.layout")) {
|
||||
pane.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent());
|
||||
}
|
||||
pane.setBackground(fillColor);
|
||||
pane.getViewport().setBackground(fillColor);
|
||||
pane.getVerticalScrollBar().setBackground(fillColor);
|
||||
configureBalloonScrollPane(pane);
|
||||
|
||||
if (!showFullContent && layoutData.twoLineHeight < layoutData.fullHeight) {
|
||||
text.setPreferredSize(null);
|
||||
@@ -680,12 +683,12 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
|
||||
int height = title instanceof JEditorPane ? getFirstLineHeight((JEditorPane)title) : title.getHeight();
|
||||
|
||||
g.setColor(fillColor);
|
||||
g.setColor(FILL_COLOR);
|
||||
g.fillRect(x, y, width, height);
|
||||
|
||||
width = layoutData.configuration.beforeGearSpace;
|
||||
x -= width;
|
||||
((Graphics2D)g).setPaint(new GradientPaint(x, y, ColorUtil.withAlpha(fillColor, 0.2), x + width, y, fillColor));
|
||||
((Graphics2D)g).setPaint(new GradientPaint(x, y, ColorUtil.withAlpha(FILL_COLOR, 0.2), x + width, y, FILL_COLOR));
|
||||
g.fillRect(x, y, width, height);
|
||||
}
|
||||
}
|
||||
@@ -711,22 +714,24 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
}
|
||||
|
||||
if (notification.isContent()) {
|
||||
centerPanel.add(pane, BorderLayout.CENTER);
|
||||
centerPanel.add(layoutData.welcomeScreen ? text : pane, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
final Icon icon = NotificationsUtil.getIcon(notification);
|
||||
JComponent iconComponent = new JComponent() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
icon.paintIcon(this, g, layoutData.configuration.iconOffset.width, layoutData.configuration.iconOffset.height);
|
||||
}
|
||||
};
|
||||
iconComponent.setOpaque(false);
|
||||
iconComponent.setPreferredSize(
|
||||
new Dimension(layoutData.configuration.iconPanelWidth, 2 * layoutData.configuration.iconOffset.height + icon.getIconHeight()));
|
||||
if (!layoutData.welcomeScreen) {
|
||||
final Icon icon = NotificationsUtil.getIcon(notification);
|
||||
JComponent iconComponent = new JComponent() {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
icon.paintIcon(this, g, layoutData.configuration.iconOffset.width, layoutData.configuration.iconOffset.height);
|
||||
}
|
||||
};
|
||||
iconComponent.setOpaque(false);
|
||||
iconComponent.setPreferredSize(
|
||||
new Dimension(layoutData.configuration.iconPanelWidth, 2 * layoutData.configuration.iconOffset.height + icon.getIconHeight()));
|
||||
|
||||
content.add(iconComponent, BorderLayout.WEST);
|
||||
content.add(iconComponent, BorderLayout.WEST);
|
||||
}
|
||||
|
||||
JPanel buttons = createButtons(notification, content, listener);
|
||||
if (buttons != null) {
|
||||
@@ -753,10 +758,8 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
pane.setPreferredSize(new Dimension(maxWidth, paneSize.height + UIUtil.getScrollBarWidth()));
|
||||
}
|
||||
|
||||
JBColor borderColor = new JBColor(Gray._178.withAlpha(205), new Color(86, 90, 92, 205));
|
||||
|
||||
final BalloonBuilder builder = JBPopupFactory.getInstance().createBalloonBuilder(content);
|
||||
builder.setFillColor(fillColor)
|
||||
builder.setFillColor(FILL_COLOR)
|
||||
.setCloseButtonEnabled(buttons == null)
|
||||
.setShowCallout(showCallout)
|
||||
.setShadow(false)
|
||||
@@ -764,16 +767,16 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
.setHideOnAction(hideOnClickOutside)
|
||||
.setHideOnKeyOutside(hideOnClickOutside)
|
||||
.setHideOnFrameResize(false)
|
||||
.setBorderColor(borderColor)
|
||||
.setBorderColor(BORDER_COLOR)
|
||||
.setBorderInsets(new Insets(0, 0, 0, 0));
|
||||
|
||||
final BalloonImpl balloon = (BalloonImpl)builder.createBalloon();
|
||||
balloon.setAnimationEnabled(false);
|
||||
notification.setBalloon(balloon);
|
||||
|
||||
balloon.setShadowBorderProvider(new NotificationBalloonShadowBorderProvider(fillColor, borderColor));
|
||||
balloon.setShadowBorderProvider(new NotificationBalloonShadowBorderProvider(FILL_COLOR, BORDER_COLOR));
|
||||
|
||||
if (buttons == null) {
|
||||
if (!layoutData.welcomeScreen && buttons == null) {
|
||||
balloon.setActionProvider(
|
||||
new NotificationBalloonActionProvider(balloon, layout.getTitle(), layoutData, notification.getGroupId()));
|
||||
}
|
||||
@@ -782,6 +785,26 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
return balloon;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JScrollPane createBalloonScrollPane(@NotNull Component content, boolean configure) {
|
||||
JScrollPane pane = ScrollPaneFactory.createScrollPane(content, true);
|
||||
if (configure) {
|
||||
configureBalloonScrollPane(pane);
|
||||
}
|
||||
return pane;
|
||||
}
|
||||
|
||||
public static void configureBalloonScrollPane(@NotNull JScrollPane pane) {
|
||||
pane.setOpaque(false);
|
||||
pane.getViewport().setOpaque(false);
|
||||
if (!Registry.is("ide.scroll.new.layout")) {
|
||||
pane.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent());
|
||||
}
|
||||
pane.setBackground(FILL_COLOR);
|
||||
pane.getViewport().setBackground(FILL_COLOR);
|
||||
pane.getVerticalScrollBar().setBackground(FILL_COLOR);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -1006,7 +1029,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
private final JEditorPane myText;
|
||||
private final BalloonLayoutData myLayoutData;
|
||||
private Component myTitleComponent;
|
||||
private JScrollPane myCenteredComponent;
|
||||
private Component myCenteredComponent;
|
||||
private JPanel myActionPanel;
|
||||
private Component myExpandAction;
|
||||
|
||||
@@ -1021,7 +1044,10 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
return myTitleComponent;
|
||||
}
|
||||
if (myCenteredComponent != null) {
|
||||
return myCenteredComponent.getViewport().getView();
|
||||
if (myCenteredComponent instanceof JScrollPane) {
|
||||
return ((JScrollPane)myCenteredComponent).getViewport().getView();
|
||||
}
|
||||
return myCenteredComponent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1032,7 +1058,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
myTitleComponent = comp;
|
||||
}
|
||||
else if (BorderLayout.CENTER.equals(constraints)) {
|
||||
myCenteredComponent = (JScrollPane)comp;
|
||||
myCenteredComponent = comp;
|
||||
}
|
||||
else if (BorderLayout.SOUTH.equals(constraints)) {
|
||||
myActionPanel = (JPanel)comp;
|
||||
|
||||
+62
-9
@@ -19,6 +19,8 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.RecentProjectsManager;
|
||||
import com.intellij.internal.statistic.UsageTrigger;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.impl.IdeNotificationArea;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.MnemonicHelper;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
@@ -49,6 +51,7 @@ import com.intellij.ui.components.labels.ActionLink;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.popup.PopupFactoryImpl;
|
||||
import com.intellij.ui.popup.list.GroupedItemsListRenderer;
|
||||
import com.intellij.util.ParameterizedRunnable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.MouseEventAdapter;
|
||||
@@ -124,7 +127,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleCont
|
||||
}
|
||||
});
|
||||
|
||||
myBalloonLayout = new BalloonLayoutImpl(rootPane, JBUI.insets(8));
|
||||
myBalloonLayout = new WelcomeBalloonLayoutImpl(rootPane, JBUI.insets(8), myScreen.myEventListener, myScreen.myEventLocation);
|
||||
|
||||
WelcomeFrame.setupCloseAction(this);
|
||||
MnemonicHelper.init(this);
|
||||
@@ -140,6 +143,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleCont
|
||||
public void dispose() {
|
||||
saveLocation(getBounds());
|
||||
super.dispose();
|
||||
((WelcomeBalloonLayoutImpl)myBalloonLayout).dispose();
|
||||
Disposer.dispose(myScreen);
|
||||
WelcomeFrame.resetInstance();
|
||||
}
|
||||
@@ -185,6 +189,8 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleCont
|
||||
|
||||
private class FlatWelcomeScreen extends JPanel implements WelcomeScreen {
|
||||
private JBSlidingPanel mySlidingPanel = new JBSlidingPanel();
|
||||
public ParameterizedRunnable<List<NotificationType>> myEventListener;
|
||||
public Computable<Point> myEventLocation;
|
||||
|
||||
public FlatWelcomeScreen() {
|
||||
super(new BorderLayout());
|
||||
@@ -273,6 +279,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleCont
|
||||
}
|
||||
|
||||
toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS));
|
||||
toolbar.add(createEventsLink());
|
||||
toolbar.add(createActionLink("Configure", IdeActions.GROUP_WELCOME_SCREEN_CONFIGURE, AllIcons.General.GearPlain, !registeredVisible));
|
||||
toolbar.add(createActionLink("Get Help", IdeActions.GROUP_WELCOME_SCREEN_DOC, null, false));
|
||||
|
||||
@@ -283,6 +290,46 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleCont
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JComponent createEventsLink() {
|
||||
final Ref<ActionLink> actionLinkRef = new Ref<>();
|
||||
final JComponent panel = createActionLink("Events", AllIcons.Ide.Notification.NoEvents, actionLinkRef, new AnAction() {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
((WelcomeBalloonLayoutImpl)myBalloonLayout).showPopup();
|
||||
}
|
||||
});
|
||||
panel.setVisible(false);
|
||||
myEventListener = new ParameterizedRunnable<List<NotificationType>>() {
|
||||
@Override
|
||||
public void run(List<NotificationType> types) {
|
||||
NotificationType type = null;
|
||||
for (NotificationType t : types) {
|
||||
if (NotificationType.ERROR == t) {
|
||||
type = NotificationType.ERROR;
|
||||
break;
|
||||
}
|
||||
if (NotificationType.WARNING == t) {
|
||||
type = NotificationType.WARNING;
|
||||
}
|
||||
else if (type == null && NotificationType.INFORMATION == t) {
|
||||
type = NotificationType.INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
actionLinkRef.get().setIcon(IdeNotificationArea.createIconWithNotificationCount(actionLinkRef.get(), type, types.size()));
|
||||
panel.setVisible(true);
|
||||
}
|
||||
};
|
||||
myEventLocation = new Computable<Point>() {
|
||||
@Override
|
||||
public Point compute() {
|
||||
Point location = SwingUtilities.convertPoint(panel, 0, 0, getRootPane().getLayeredPane());
|
||||
return new Point(location.x, location.y + 5);
|
||||
}
|
||||
};
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JComponent createActionLink(final String text, final String groupId, Icon icon, boolean focusListOnLeft) {
|
||||
final Ref<ActionLink> ref = new Ref<ActionLink>(null);
|
||||
AnAction action = new AnAction() {
|
||||
@@ -296,16 +343,22 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleCont
|
||||
UsageTrigger.trigger("welcome.screen." + groupId);
|
||||
}
|
||||
};
|
||||
ref.set(new ActionLink(text, icon, action));
|
||||
ref.get().setPaintUnderline(false);
|
||||
ref.get().setNormalColor(getLinkNormalColor());
|
||||
JComponent panel = createActionLink(text, icon, ref, action);
|
||||
installFocusable(panel, action, KeyEvent.VK_UP, KeyEvent.VK_DOWN, focusListOnLeft);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JComponent createActionLink(String text, Icon icon, Ref<ActionLink> ref, AnAction action) {
|
||||
ActionLink link = new ActionLink(text, icon, action);
|
||||
ref.set(link);
|
||||
link.setPaintUnderline(false);
|
||||
link.setNormalColor(getLinkNormalColor());
|
||||
NonOpaquePanel panel = new NonOpaquePanel(new BorderLayout());
|
||||
panel.setBorder(JBUI.Borders.empty(4, 6, 4, 6));
|
||||
panel.add(ref.get());
|
||||
AccessibleContextUtil.setName(panel, ref.get());
|
||||
AccessibleContextUtil.setDescription(panel, ref.get());
|
||||
panel.add(createArrow(ref.get()), BorderLayout.EAST);
|
||||
installFocusable(panel, action, KeyEvent.VK_UP, KeyEvent.VK_DOWN, focusListOnLeft);
|
||||
panel.add(link);
|
||||
AccessibleContextUtil.setName(panel, link);
|
||||
AccessibleContextUtil.setDescription(panel, link);
|
||||
panel.add(createArrow(link), BorderLayout.EAST);
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.wm.impl.welcomeScreen;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.impl.NotificationsManagerImpl;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ParameterizedRunnable;
|
||||
import com.intellij.util.ui.AbstractLayoutManager;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.notification.impl.NotificationsManagerImpl.BORDER_COLOR;
|
||||
import static com.intellij.notification.impl.NotificationsManagerImpl.FILL_COLOR;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public class WelcomeBalloonLayoutImpl extends BalloonLayoutImpl {
|
||||
private static final String TYPE_KEY = "Type";
|
||||
|
||||
private final ParameterizedRunnable<List<NotificationType>> myListener;
|
||||
private final Computable<Point> myButtonLocation;
|
||||
private BalloonImpl myPopupBalloon;
|
||||
private final BalloonPanel myBalloonPanel = new BalloonPanel();
|
||||
private boolean myVisible;
|
||||
private List<Disposable> myDisposableList = new ArrayList<>();
|
||||
|
||||
public WelcomeBalloonLayoutImpl(@NotNull JRootPane parent,
|
||||
@NotNull Insets insets,
|
||||
@NotNull ParameterizedRunnable<List<NotificationType>> listener,
|
||||
@NotNull Computable<Point> buttonLocation) {
|
||||
super(parent, insets);
|
||||
myListener = listener;
|
||||
myButtonLocation = buttonLocation;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (myPopupBalloon != null) {
|
||||
for (Disposable disposable : new ArrayList<>(myDisposableList)) {
|
||||
Disposer.dispose(disposable);
|
||||
}
|
||||
Disposer.dispose(myPopupBalloon);
|
||||
myPopupBalloon = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(@NotNull Balloon balloon, @Nullable Object layoutData) {
|
||||
if (layoutData instanceof BalloonLayoutData && ((BalloonLayoutData)layoutData).welcomeScreen) {
|
||||
addToPopup((BalloonImpl)balloon, (BalloonLayoutData)layoutData);
|
||||
}
|
||||
else {
|
||||
super.add(balloon, layoutData);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToPopup(@NotNull BalloonImpl balloon, @NotNull BalloonLayoutData layoutData) {
|
||||
layoutData.doLayout = this::layoutPopup;
|
||||
layoutData.configuration = layoutData.configuration.replace(JBUI.scale(myPopupBalloon == null ? 7 : 5), JBUI.scale(12));
|
||||
|
||||
if (myPopupBalloon == null) {
|
||||
final JScrollPane pane = NotificationsManagerImpl.createBalloonScrollPane(myBalloonPanel, true);
|
||||
pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
pane.getVerticalScrollBar().addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
pane.setBorder(IdeBorderFactory.createEmptyBorder(SystemInfo.isMac ? 2 : 1, 0, 1, 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
pane.setBorder(IdeBorderFactory.createEmptyBorder());
|
||||
}
|
||||
});
|
||||
|
||||
myPopupBalloon =
|
||||
new BalloonImpl(pane, BORDER_COLOR, new Insets(0, 0, 0, 0), FILL_COLOR, true, false, false, false, true, 0, false, false, null,
|
||||
false, 0, 0, 0, 0, false, null, null, false, false, false, null, false);
|
||||
myPopupBalloon.setAnimationEnabled(false);
|
||||
myPopupBalloon.setShadowBorderProvider(
|
||||
new NotificationBalloonShadowBorderProvider(FILL_COLOR, BORDER_COLOR));
|
||||
myPopupBalloon.setHideListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myPopupBalloon.getComponent().setVisible(false);
|
||||
}
|
||||
});
|
||||
myPopupBalloon.setActionProvider(new BalloonImpl.ActionProvider() {
|
||||
private BalloonImpl.ActionButton myAction;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<BalloonImpl.ActionButton> createActions() {
|
||||
myAction = myPopupBalloon.new ActionButton(AllIcons.Ide.Notification.Close, null, null, Consumer.EMPTY_CONSUMER);
|
||||
return Collections.singletonList(myAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layout(@NotNull Rectangle bounds) {
|
||||
myAction.setBounds(0, 0, 0, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
myBalloonPanel.add(balloon.getContent());
|
||||
balloon.getContent().putClientProperty(TYPE_KEY, layoutData.type);
|
||||
Disposable disposable = new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
myDisposableList.remove(this);
|
||||
myBalloonPanel.remove(balloon.getContent());
|
||||
updatePopup();
|
||||
}
|
||||
};
|
||||
myDisposableList.add(disposable);
|
||||
Disposer.register(balloon, disposable);
|
||||
|
||||
updatePopup();
|
||||
}
|
||||
|
||||
public void showPopup() {
|
||||
layoutPopup();
|
||||
if (myVisible) {
|
||||
myPopupBalloon.getComponent().setVisible(true);
|
||||
}
|
||||
else {
|
||||
myPopupBalloon.show(myLayeredPane);
|
||||
myVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void layoutPopup() {
|
||||
Dimension layeredSize = myLayeredPane.getSize();
|
||||
Dimension size = new Dimension(myPopupBalloon.getPreferredSize());
|
||||
int x = layeredSize.width - size.width - 5;
|
||||
int fullHeight = myButtonLocation.compute().y;
|
||||
|
||||
if (size.height > fullHeight) {
|
||||
size.height = fullHeight;
|
||||
}
|
||||
|
||||
myPopupBalloon.setBounds(new Rectangle(x, fullHeight - size.height, size.width, size.height));
|
||||
}
|
||||
|
||||
private void updatePopup() {
|
||||
int count = myBalloonPanel.getComponentCount();
|
||||
List<NotificationType> types = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
types.add((NotificationType)((JComponent)myBalloonPanel.getComponent(i)).getClientProperty(TYPE_KEY));
|
||||
}
|
||||
myListener.run(types);
|
||||
|
||||
if (myVisible) {
|
||||
layoutPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private static class BalloonPanel extends NonOpaquePanel {
|
||||
public BalloonPanel() {
|
||||
super(new AbstractLayoutManager() {
|
||||
@Override
|
||||
public Dimension preferredLayoutSize(Container parent) {
|
||||
int count = parent.getComponentCount();
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
Dimension size = parent.getComponent(i).getPreferredSize();
|
||||
width = Math.max(width, size.width);
|
||||
height += size.height;
|
||||
}
|
||||
height += count - 1;
|
||||
return new Dimension(width + JBUI.scale(32), height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container parent) {
|
||||
int count = parent.getComponentCount();
|
||||
int width = parent.getWidth() - JBUI.scale(32);
|
||||
int height = parent.getHeight();
|
||||
if (count == 1) {
|
||||
parent.getComponent(0).setBounds(JBUI.scale(16), 0, width, height);
|
||||
}
|
||||
else {
|
||||
int y = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
Component component = parent.getComponent(i);
|
||||
Dimension size = component.getPreferredSize();
|
||||
component.setBounds(JBUI.scale(16), y, width, size.height);
|
||||
y += size.height + JBUI.scale(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
|
||||
int count = getComponentCount() - 1;
|
||||
if (count > 0) {
|
||||
int x2 = getWidth() - JBUI.scale(16);
|
||||
int y = 0;
|
||||
|
||||
g.setColor(new JBColor(0xD0D0D0, 0x717375));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Dimension size = getComponent(i).getPreferredSize();
|
||||
y += size.height + 1;
|
||||
g.drawLine(JBUI.scale(16), y, x2, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,12 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
|
||||
if (myHideOnMouse && id == MouseEvent.MOUSE_PRESSED) {
|
||||
if (!insideBalloon && !hasModalDialog(me) && !isWithinChildWindow(me)) {
|
||||
hide();
|
||||
if (myHideListener == null) {
|
||||
hide();
|
||||
}
|
||||
else {
|
||||
myHideListener.run();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -153,8 +158,14 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
}
|
||||
}
|
||||
|
||||
if (myHideOnKey && e instanceof KeyEvent && id == KeyEvent.KEY_PRESSED) {
|
||||
if ((myHideOnKey || myHideListener != null) && e instanceof KeyEvent && id == KeyEvent.KEY_PRESSED) {
|
||||
final KeyEvent ke = (KeyEvent)e;
|
||||
if (myHideListener != null) {
|
||||
if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
myHideListener.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ke.getKeyCode() != KeyEvent.VK_SHIFT &&
|
||||
ke.getKeyCode() != KeyEvent.VK_CONTROL &&
|
||||
ke.getKeyCode() != KeyEvent.VK_ALT &&
|
||||
@@ -266,6 +277,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
private boolean myDisposed;
|
||||
private final JComponent myContent;
|
||||
private boolean myHideOnMouse;
|
||||
private Runnable myHideListener;
|
||||
private final boolean myHideOnKey;
|
||||
private final boolean myHideOnAction;
|
||||
private final boolean myRequestFocus;
|
||||
@@ -666,6 +678,10 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
}
|
||||
}
|
||||
|
||||
public JComponent getContent() {
|
||||
return myContent;
|
||||
}
|
||||
|
||||
public Component getComponent() {
|
||||
return myComp;
|
||||
}
|
||||
@@ -990,6 +1006,11 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
|
||||
myHideOnMouse = hideOnMouse;
|
||||
}
|
||||
|
||||
public void setHideListener(@NotNull Runnable listener) {
|
||||
myHideListener = listener;
|
||||
myHideOnMouse = true;
|
||||
}
|
||||
|
||||
public void setShowPointer(final boolean show) {
|
||||
myShowPointer = show;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.ui.JBDimension;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@@ -98,6 +99,12 @@ public class BalloonLayoutConfiguration {
|
||||
return twoLines();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BalloonLayoutConfiguration replace(int topSpaceHeight, int bottomSpaceHeight) {
|
||||
return new BalloonLayoutConfiguration(iconPanelWidth, iconOffset, topSpaceHeight, titleContentSpaceHeight, contentActionsSpaceHeight,
|
||||
titleActionsSpaceHeight, bottomSpaceHeight, actionGap, null, 0, 0, 0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static BalloonLayoutConfiguration twoLines() {
|
||||
return new BalloonLayoutConfiguration(new JBDimension(10, 11),
|
||||
@@ -130,7 +137,7 @@ public class BalloonLayoutConfiguration {
|
||||
int titleActionsSpaceHeight,
|
||||
int bottomSpaceHeight,
|
||||
int actionGap,
|
||||
@NotNull Dimension rightActionsOffset,
|
||||
@Nullable Dimension rightActionsOffset,
|
||||
int afterGearSpace,
|
||||
int beforeCloseSpace,
|
||||
int beforeGearSpace) {
|
||||
@@ -142,11 +149,20 @@ public class BalloonLayoutConfiguration {
|
||||
this.titleActionsSpaceHeight = titleActionsSpaceHeight;
|
||||
this.bottomSpaceHeight = bottomSpaceHeight;
|
||||
this.actionGap = actionGap;
|
||||
this.rightActionsOffset = rightActionsOffset;
|
||||
|
||||
this.closeOffset = beforeCloseSpace + AllIcons.Ide.Notification.Close.getIconWidth() + rightActionsOffset.width;
|
||||
this.gearCloseSpace = afterGearSpace + beforeCloseSpace;
|
||||
this.allActionsOffset = closeOffset + afterGearSpace + AllIcons.Ide.Notification.Gear.getIconWidth();
|
||||
this.beforeGearSpace = beforeGearSpace;
|
||||
if (rightActionsOffset == null) {
|
||||
this.rightActionsOffset = new Dimension();
|
||||
this.closeOffset = 0;
|
||||
this.gearCloseSpace = 0;
|
||||
this.allActionsOffset = 0;
|
||||
this.beforeGearSpace = 0;
|
||||
}
|
||||
else {
|
||||
this.rightActionsOffset = rightActionsOffset;
|
||||
this.closeOffset = beforeCloseSpace + AllIcons.Ide.Notification.Close.getIconWidth() + rightActionsOffset.width;
|
||||
this.gearCloseSpace = afterGearSpace + beforeCloseSpace;
|
||||
this.allActionsOffset = closeOffset + afterGearSpace + AllIcons.Ide.Notification.Gear.getIconWidth();
|
||||
this.beforeGearSpace = beforeGearSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ui;
|
||||
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -29,6 +30,9 @@ public class BalloonLayoutData {
|
||||
|
||||
public boolean showFullContent;
|
||||
|
||||
public boolean welcomeScreen;
|
||||
public NotificationType type;
|
||||
|
||||
public int height;
|
||||
public int twoLineHeight;
|
||||
public int fullHeight;
|
||||
|
||||
Reference in New Issue
Block a user