event-driven event log toolwindow icon update, no battery-consuming polling (IDEA-88837)

This commit is contained in:
peter
2012-09-06 12:57:00 +02:00
parent e84b370593
commit b908ccf9a2
3 changed files with 59 additions and 29 deletions
@@ -17,12 +17,14 @@ package com.intellij.notification;
import com.intellij.notification.impl.NotificationsConfigurationImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.Topic;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
@@ -34,6 +36,8 @@ import java.util.*;
* @author peter
*/
public class LogModel implements Disposable {
public static final Topic<Runnable> LOG_MODEL_CHANGED = Topic.create("LOG_MODEL_CHANGED", Runnable.class, Topic.BroadcastDirection.NONE);
private final List<Notification> myNotifications = new ArrayList<Notification>();
private final Map<Notification, Long> myStamps = Collections.synchronizedMap(new WeakHashMap<Notification, Long>());
private Trinity<Notification, String, Long> myStatusMessage;
@@ -55,14 +59,21 @@ public class LogModel implements Disposable {
}
myStamps.put(notification, stamp);
setStatusMessage(notification, stamp);
fireModelChanged();
}
private static void fireModelChanged() {
ApplicationManager.getApplication().getMessageBus().syncPublisher(LOG_MODEL_CHANGED).run();
}
List<Notification> takeNotifications() {
final ArrayList<Notification> result;
synchronized (myNotifications) {
final ArrayList<Notification> result = getNotifications();
result = getNotifications();
myNotifications.clear();
return result;
}
fireModelChanged();
return result;
}
void setStatusMessage(@Nullable Notification statusMessage, long stamp) {
@@ -116,6 +127,7 @@ public class LogModel implements Disposable {
if (oldStatus != null && notification == oldStatus.first) {
setStatusToImportant();
}
fireModelChanged();
}
private void setStatusToImportant() {
@@ -137,6 +149,7 @@ public class LogModel implements Disposable {
}
public Project getProject() {
//noinspection ConstantConditions
return myProject;
}
@@ -24,6 +24,7 @@ import com.intellij.notification.LogModel;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.CustomStatusBarWidget;
@@ -66,6 +67,18 @@ public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget
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) {
@@ -77,15 +90,7 @@ public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget
public void install(@NotNull StatusBar statusBar) {
myStatusBar = statusBar;
new Runnable() {
@Override
public void run() {
updateStatus();
myLogAlarm.addRequest(this, 100, true);
}
}.run();
updateStatus();
}
@Nullable
@@ -100,28 +105,38 @@ public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget
private void updateStatus() {
final Project project = getProject();
LogModel logModel = EventLog.getLogModel(project);
ToolWindow eventLog = EventLog.getEventLog(project);
boolean stripesVisible = !UISettings.getInstance().HIDE_TOOL_STRIPES;
ArrayList<Notification> notifications = logModel.getNotifications();
LayeredIcon icon = new LayeredIcon(2);
Icon statusIcon = getPendingNotificationsIcon(AllIcons.Ide.Notifications, getMaximumType(notifications));
icon.setIcon(statusIcon, 0);
final int count = notifications.size();
if (count > 0) {
icon.setIcon(new TextIcon(this, String.valueOf(count)), 1, statusIcon.getIconWidth() - 2, 0);
}
if (stripesVisible && eventLog != null) {
eventLog.setIcon(icon);
setIcon(null);
} else {
setIcon(icon);
}
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) {
setIcon(icon);
}
else {
ToolWindow eventLog = EventLog.getEventLog(project);
if (eventLog != null) {
eventLog.setIcon(icon);
}
setIcon(null);
}
}
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;
@@ -242,7 +242,9 @@
<virtualFileSystem key="http" implementationClass="com.intellij.openapi.vfs.impl.http.HttpFileSystemImpl"/>
<virtualFileSystem key="https" implementationClass="com.intellij.openapi.vfs.impl.http.HttpsFileSystem"/>
<toolWindow id="Event Log" anchor="bottom" secondary="true" factoryClass="com.intellij.notification.EventLogToolWindowFactory"/>
<toolWindow id="Event Log" anchor="bottom" secondary="true"
icon="AllIcons.Ide.Notifications"
factoryClass="com.intellij.notification.EventLogToolWindowFactory"/>
<projectService serviceInterface="com.intellij.openapi.wm.impl.ProjectFrameBounds"
serviceImplementation="com.intellij.openapi.wm.impl.ProjectFrameBounds"/>