IDEA-153807 Welcome screen notifications

This commit is contained in:
Alexander Lobas
2016-04-15 21:14:37 +03:00
parent 1adf5b9d02
commit 4a148f1ceb
6 changed files with 423 additions and 55 deletions
@@ -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;
@@ -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;
}
@@ -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;