| /* |
| * Copyright 2000-2014 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.notification.impl; |
| |
| import com.intellij.icons.AllIcons; |
| import com.intellij.ide.DataManager; |
| import com.intellij.ide.ui.UISettings; |
| import com.intellij.ide.ui.UISettingsListener; |
| import com.intellij.notification.EventLog; |
| import com.intellij.notification.LogModel; |
| import com.intellij.notification.Notification; |
| import com.intellij.notification.NotificationType; |
| import com.intellij.openapi.actionSystem.CommonDataKeys; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.wm.CustomStatusBarWidget; |
| import com.intellij.openapi.wm.IconLikeCustomStatusBarWidget; |
| import com.intellij.openapi.wm.StatusBar; |
| import com.intellij.openapi.wm.ToolWindow; |
| import com.intellij.ui.ClickListener; |
| import com.intellij.ui.LayeredIcon; |
| import com.intellij.util.Alarm; |
| import com.intellij.util.ui.UIUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.event.MouseEvent; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author spleaner |
| */ |
| public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget, IconLikeCustomStatusBarWidget { |
| public static final String WIDGET_ID = "Notifications"; |
| |
| private StatusBar myStatusBar; |
| private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); |
| |
| public IdeNotificationArea() { |
| Disposer.register(this, myLogAlarm); |
| UISettings.getInstance().addUISettingsListener(new UISettingsListener() { |
| @Override |
| public void uiSettingsChanged(UISettings source) { |
| updateStatus(); |
| } |
| }, this); |
| new ClickListener() { |
| @Override |
| public boolean onClick(@NotNull MouseEvent e, int clickCount) { |
| EventLog.toggleLog(getProject(), null); |
| return true; |
| } |
| }.installOn(this); |
| |
| ApplicationManager.getApplication().getMessageBus().connect().subscribe(LogModel.LOG_MODEL_CHANGED, new Runnable() { |
| @Override |
| public void run() { |
| ApplicationManager.getApplication().invokeLater(new Runnable() { |
| @Override |
| public void run() { |
| updateStatus(); |
| } |
| }); |
| } |
| }); |
| } |
| |
| public WidgetPresentation getPresentation(@NotNull PlatformType type) { |
| return null; |
| } |
| |
| public void dispose() { |
| } |
| |
| public void install(@NotNull StatusBar statusBar) { |
| myStatusBar = statusBar; |
| updateStatus(); |
| } |
| |
| @Nullable |
| private Project getProject() { |
| return CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext((Component) myStatusBar)); |
| } |
| |
| @NotNull |
| public String ID() { |
| return WIDGET_ID; |
| } |
| |
| private void updateStatus() { |
| final Project project = getProject(); |
| ArrayList<Notification> notifications = EventLog.getLogModel(project).getNotifications(); |
| applyIconToStatusAndToolWindow(project, createIconWithNotificationCount(notifications)); |
| |
| int count = notifications.size(); |
| setToolTipText(count > 0 ? String.format("%s notification%s pending", count, count == 1 ? "" : "s") : "No new notifications"); |
| |
| myStatusBar.updateWidget(ID()); |
| } |
| |
| private void applyIconToStatusAndToolWindow(Project project, LayeredIcon icon) { |
| if (UISettings.getInstance().HIDE_TOOL_STRIPES || UISettings.getInstance().PRESENTATION_MODE) { |
| setVisible(true); |
| setIcon(icon); |
| } |
| else { |
| ToolWindow eventLog = EventLog.getEventLog(project); |
| if (eventLog != null) { |
| eventLog.setIcon(icon); |
| } |
| setVisible(false); |
| } |
| } |
| |
| private LayeredIcon createIconWithNotificationCount(ArrayList<Notification> notifications) { |
| LayeredIcon icon = new LayeredIcon(2); |
| Icon statusIcon = getPendingNotificationsIcon(AllIcons.Ide.Notifications, getMaximumType(notifications)); |
| icon.setIcon(statusIcon, 0); |
| if (notifications.size() > 0) { |
| icon.setIcon(new TextIcon(this, String.valueOf(notifications.size())), 1, statusIcon.getIconWidth() - 2, 0); |
| } |
| return icon; |
| } |
| |
| @Override |
| public JComponent getComponent() { |
| return this; |
| } |
| |
| private static Icon getPendingNotificationsIcon(Icon defIcon, final NotificationType maximumType) { |
| if (maximumType != null) { |
| switch (maximumType) { |
| case WARNING: return AllIcons.Ide.Warning_notifications; |
| case ERROR: return AllIcons.Ide.Error_notifications; |
| case INFORMATION: return AllIcons.Ide.Info_notifications; |
| } |
| } |
| return defIcon; |
| } |
| |
| @Nullable |
| private static NotificationType getMaximumType(List<Notification> notifications) { |
| NotificationType result = null; |
| for (Notification notification : notifications) { |
| if (NotificationType.ERROR == notification.getType()) { |
| return NotificationType.ERROR; |
| } |
| |
| if (NotificationType.WARNING == notification.getType()) { |
| result = NotificationType.WARNING; |
| } |
| else if (result == null && NotificationType.INFORMATION == notification.getType()) { |
| result = NotificationType.INFORMATION; |
| } |
| } |
| |
| return result; |
| } |
| |
| private static class TextIcon implements Icon { |
| private final String myStr; |
| private final JComponent myComponent; |
| private final int myWidth; |
| |
| public TextIcon(JComponent component, @NotNull String str) { |
| myStr = str; |
| myComponent = component; |
| myWidth = myComponent.getFontMetrics(calcFont()).stringWidth(myStr) + 1; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (!(o instanceof TextIcon)) return false; |
| |
| TextIcon icon = (TextIcon)o; |
| |
| if (myWidth != icon.myWidth) return false; |
| if (!myComponent.equals(icon.myComponent)) return false; |
| if (!myStr.equals(icon.myStr)) return false; |
| |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| int result = myStr.hashCode(); |
| result = 31 * result + myComponent.hashCode(); |
| result = 31 * result + myWidth; |
| return result; |
| } |
| |
| @Override |
| public void paintIcon(Component c, Graphics g, int x, int y) { |
| UIUtil.applyRenderingHints(g); |
| |
| Font originalFont = g.getFont(); |
| Color originalColor = g.getColor(); |
| g.setFont(calcFont()); |
| y += getIconHeight() - g.getFontMetrics().getDescent(); |
| |
| g.setColor(UIUtil.getLabelForeground()); |
| g.drawString(myStr, x, y); |
| |
| g.setFont(originalFont); |
| g.setColor(originalColor); |
| } |
| |
| private Font calcFont() { |
| return myComponent.getFont().deriveFont(Font.BOLD).deriveFont((float) getIconHeight() * 3 / 5); |
| } |
| |
| @Override |
| public int getIconWidth() { |
| return myWidth; |
| } |
| |
| @Override |
| public int getIconHeight() { |
| return AllIcons.Ide.Notifications.getIconHeight(); |
| } |
| } |
| } |