show the notifications icon next to the memory indicator, let it toggle the log

This commit is contained in:
peter
2011-06-29 14:45:48 +02:00
parent 924dde5961
commit f62070eeb4
5 changed files with 55 additions and 176 deletions
@@ -131,6 +131,18 @@ public class EventLog implements Notifications {
return project == null ? null : ToolWindowManager.getInstance(project).getToolWindow(LOG_TOOL_WINDOW_ID);
}
public static void toggleLog(final Project project) {
final ToolWindow eventLog = getEventLog(project);
if (eventLog != null) {
if (!eventLog.isVisible()) {
eventLog.activate(null, true);
getLogModel(project).logShown();
} else {
eventLog.hide(null);
}
}
}
public static class ProjectTracker extends AbstractProjectComponent {
private volatile EventLogConsole myConsole;
private List<Notification> myInitial = new CopyOnWriteArrayList<Notification>();
@@ -16,15 +16,17 @@
package com.intellij.notification.impl;
import com.intellij.ide.DataManager;
import com.intellij.notification.Notification;
import com.intellij.notification.EventLog;
import com.intellij.notification.LogModel;
import com.intellij.notification.NotificationType;
import com.intellij.notification.impl.ui.NotificationsListPanel;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.StatusBarWidget;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,22 +34,23 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.lang.ref.WeakReference;
/**
* @author spleaner
*/
public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.IconPresentation, NotificationModelListener {
public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.IconPresentation {
private static final Icon EMPTY_ICON = IconLoader.getIcon("/ide/notifications.png");
private static final Icon ERROR_ICON = IconLoader.getIcon("/ide/error_notifications.png");
private static final Icon WARNING_ICON = IconLoader.getIcon("/ide/warning_notifications.png");
private static final Icon INFO_ICON = IconLoader.getIcon("/ide/info_notifications.png");
private WeakReference<JBPopup> myPopupRef;
private Icon myCurrentIcon = EMPTY_ICON;
private StatusBar myStatusBar;
private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
public IdeNotificationArea() {
Disposer.register(this, myLogAlarm);
}
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
@@ -55,23 +58,24 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
}
public void dispose() {
cancelPopup();
}
public void install(@NotNull StatusBar statusBar) {
myStatusBar = statusBar;
getManager().addListener(this,this);
}
private void cancelPopup() {
if (myPopupRef != null) {
final JBPopup popup = myPopupRef.get();
if (popup != null) {
popup.cancel();
new Runnable() {
@Override
public void run() {
LogModel logModel = EventLog.getLogModel(getProject());
ToolWindow eventLog = EventLog.getEventLog(getProject());
if (eventLog != null && eventLog.isVisible()) {
logModel.logShown();
}
updateStatus();
myLogAlarm.addRequest(this, 50);
}
}.run();
myPopupRef = null;
}
}
@Nullable
@@ -82,31 +86,11 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
public Consumer<MouseEvent> getClickConsumer() {
return new Consumer<MouseEvent>() {
public void consume(MouseEvent mouseEvent) {
toggleList();
EventLog.toggleLog(getProject());
}
};
}
private static NotificationsManagerImpl getManager() {
return NotificationsManagerImpl.getNotificationsManagerImpl();
}
private void toggleList() {
JBPopup popup = null;
if (myPopupRef != null) {
popup = myPopupRef.get();
myPopupRef = null;
}
if (popup != null && popup.isVisible()) {
popup.cancel();
}
else {
JBPopup jbPopup = NotificationsListPanel.show(getProject(), (JComponent)myStatusBar);
myPopupRef = new WeakReference<JBPopup>(jbPopup);
}
}
@NotNull
public Icon getIcon() {
return myCurrentIcon;
@@ -127,18 +111,12 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
return "Notifications";
}
public void updateStatus() {
final NotificationsManagerImpl manager = getManager();
myCurrentIcon = getPendingNotificationsIcon(EMPTY_ICON, manager.getMaximumType(getProject()));
if (manager.count(getProject()) == 0) {
cancelPopup();
}
private void updateStatus() {
myCurrentIcon = getPendingNotificationsIcon(EMPTY_ICON, NotificationModel.getMaximumType(EventLog.getLogModel(getProject()).getNotifications()));
myStatusBar.updateWidget(ID());
}
public static Icon getPendingNotificationsIcon(Icon defIcon, final NotificationType maximumType) {
private static Icon getPendingNotificationsIcon(Icon defIcon, final NotificationType maximumType) {
if (maximumType != null) {
switch (maximumType) {
case WARNING: return WARNING_ICON;
@@ -149,28 +127,4 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico
return defIcon;
}
public void notificationsAdded(@NotNull final Notification... notifications) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updateStatus();
}
});
}
public void notificationsRead(@NotNull Notification... notification) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updateStatus();
}
});
}
@SuppressWarnings({"SSBasedInspection"})
public void notificationsRemoved(@NotNull final Notification... notifications) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updateStatus();
}
});
}
}
@@ -19,6 +19,7 @@ import com.intellij.ide.AppLifecycleListener;
import com.intellij.ide.DataManager;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.ide.ui.UISettings;
import com.intellij.notification.impl.IdeNotificationArea;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.MnemonicHelper;
import com.intellij.openapi.actionSystem.DataProvider;
@@ -297,6 +298,9 @@ public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider {
private void installDefaultProjectStatusBarWidgets(@NotNull final Project project) {
final StatusBar statusBar = getStatusBar();
IdeNotificationArea notificationArea = new IdeNotificationArea();
statusBar.addWidget(notificationArea, "before Memory");
final PositionPanel positionPanel = new PositionPanel(project);
statusBar.addWidget(positionPanel, "before FatalError");
@@ -114,7 +114,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge
myRefreshAndInfoPanel.setLayout(new BorderLayout());
myRefreshAndInfoPanel.setOpaque(false);
myRefreshAndInfoPanel.add(myRefreshIcon, BorderLayout.WEST);
myRefreshAndInfoPanel.add(myInfoPanel, BorderLayout.CENTER);
myRefreshAndInfoPanel.add(myInfoPanel.geTextPanel(), BorderLayout.CENTER);
myProgressIcon = new AsyncProcessIcon("Background process");
myProgressIcon.setOpaque(false);
@@ -16,63 +16,41 @@
package com.intellij.openapi.wm.impl.status;
import com.intellij.notification.EventLog;
import com.intellij.notification.LogModel;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.impl.IdeNotificationArea;
import com.intellij.notification.impl.NotificationModel;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.util.Alarm;
import com.intellij.util.text.DateFormatUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
/**
* @author peter
*/
class StatusPanel extends JPanel {
private static final Icon ourShowLogIcon = IconLoader.getIcon("/general/hideSideUp.png");
private static final Icon ourHideLogIcon = IconLoader.getIcon("/general/hideSideDown.png");
class StatusPanel {
private boolean myLogMode;
private boolean myDirty;
private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
private final TextPanel myTextPanel = new TextPanel();
private final JLabel myShowLog = new JLabel();
StatusPanel() {
super(new BorderLayout());
setOpaque(isOpaque() && !SystemInfo.isMac);
myShowLog.addMouseListener(new MouseAdapter() {
myTextPanel.setBorder(new EmptyBorder(0, 5, 0, 0));
myTextPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final ToolWindow eventLog = getEventLog();
if (eventLog != null) {
if (!eventLog.isVisible()) {
eventLog.activate(null, true);
EventLog.getLogModel(getActiveProject()).logShown();
} else {
eventLog.hide(null);
}
if (myLogMode) {
EventLog.toggleLog(getActiveProject());
}
}
});
add(myShowLog, BorderLayout.WEST);
add(myTextPanel, BorderLayout.CENTER);
}
@Nullable
@@ -80,18 +58,13 @@ class StatusPanel extends JPanel {
// a better way of finding a project would be great
for (Project project : ProjectManager.getInstance().getOpenProjects()) {
final JComponent frame = WindowManager.getInstance().getIdeFrame(project).getComponent();
if (SwingUtilities.isDescendingFrom(this, frame)) {
if (SwingUtilities.isDescendingFrom(myTextPanel, frame)) {
return project;
}
}
return null;
}
@Nullable
private ToolWindow getEventLog() {
return EventLog.getEventLog(getActiveProject());
}
public void setLogMessage(String text) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -105,11 +78,10 @@ class StatusPanel extends JPanel {
final Project project = getActiveProject();
final Notification statusMessage = EventLog.getStatusMessage(project);
myLogMode = logAllowed && StringUtil.isEmpty(nonLogText) && project != null;
myShowLog.setVisible(myLogMode);
myLogMode = logAllowed && StringUtil.isEmpty(nonLogText) && statusMessage != null;
if (myLogMode) {
myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
new Runnable() {
@Override
public void run() {
@@ -126,45 +98,8 @@ class StatusPanel extends JPanel {
myLogAlarm.addRequest(this, 30000);
}
}.run();
new Runnable() {
@Override
public void run() {
final ToolWindow eventLog = getEventLog();
if (eventLog == null) {
myShowLog.setVisible(false);
return;
}
assert project != null;
final boolean visible = eventLog.isVisible();
LogModel logModel = EventLog.getLogModel(project);
if (visible) {
logModel.logShown();
}
ArrayList<Notification> notifications = logModel.getNotifications();
final int count = notifications.size();
final NotificationType maximumType = count > 0 ? NotificationModel.getMaximumType(notifications) : null;
Icon icon = visible
? ourHideLogIcon
: maximumType == null
? ourShowLogIcon
: statusMessage != null && maximumType == statusMessage.getType()
? IdeNotificationArea.getPendingNotificationsIcon(ourShowLogIcon, maximumType)
: new PendingNotificationsIcon(ourShowLogIcon, maximumType == NotificationType.ERROR ? Color.red : maximumType == NotificationType.WARNING ? Color.orange : Color.green.darker());
myShowLog.setIcon(icon);
myShowLog.setToolTipText(visible ? "" : count > 0 ? count + " " + StringUtil.pluralize("notification", count) + " pending" : "Click to open the event log");
myShowLog.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 20 - icon.getIconWidth()));
myLogAlarm.addRequest(this, 50);
}
}.run();
} else {
myTextPanel.setCursor(Cursor.getDefaultCursor());
myDirty = true;
myTextPanel.setText(nonLogText);
myLogAlarm.cancelAllRequests();
@@ -172,36 +107,6 @@ class StatusPanel extends JPanel {
return myLogMode;
}
private static class PendingNotificationsIcon implements Icon {
private final Icon myBase;
private final Color myColor;
private PendingNotificationsIcon(Icon base, Color color) {
myBase = base;
myColor = color;
}
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
myBase.paintIcon(c, g, x, y);
g.setColor(Color.white);
int size = 4;
g.drawRect(x, y, size + 1, size + 1);
g.setColor(myColor);
g.fillRect(x + 1, y + 1, size, size);
}
@Override
public int getIconWidth() {
return myBase.getIconWidth();
}
@Override
public int getIconHeight() {
return myBase.getIconHeight();
}
}
public void hideLog() {
if (myLogMode) {
updateText(false, "");
@@ -222,4 +127,8 @@ class StatusPanel extends JPanel {
public String getText() {
return myTextPanel.getText();
}
public TextPanel geTextPanel() {
return myTextPanel;
}
}