diff --git a/platform/platform-api/src/com/intellij/notification/NotificationGroup.java b/platform/platform-api/src/com/intellij/notification/NotificationGroup.java index 4c9000af7fba..7285a8e1ffd6 100644 --- a/platform/platform-api/src/com/intellij/notification/NotificationGroup.java +++ b/platform/platform-api/src/com/intellij/notification/NotificationGroup.java @@ -15,15 +15,25 @@ */ package com.intellij.notification; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.MessageType; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; + /** * @author peter */ -public class NotificationGroup { - private final String myDisplayId; +public final class NotificationGroup { + private static final Logger LOG = Logger.getInstance("#com.intellij.notification.NotificationGroup"); + private static final Map ourRegisteredGroups = ContainerUtil.newConcurrentMap(); + + @NotNull private final String myDisplayId; + @NotNull private final NotificationDisplayType myDisplayType; + private final boolean myLogByDefault; + @Nullable private final String myToolWindowId; public NotificationGroup(@NotNull String displayId, @NotNull NotificationDisplayType defaultDisplayType, boolean logByDefault) { this(displayId, defaultDisplayType, logByDefault, null); @@ -34,12 +44,14 @@ public class NotificationGroup { boolean logByDefault, @Nullable String toolWindowId) { myDisplayId = displayId; + myDisplayType = defaultDisplayType; + myLogByDefault = logByDefault; + myToolWindowId = toolWindowId; - NotificationsConfiguration configuration = NotificationsConfiguration.getNotificationsConfiguration(); - configuration.register(displayId, defaultDisplayType, logByDefault); - if (toolWindowId != null) { - configuration.registerToolWindowCapability(displayId, toolWindowId); + if (ourRegisteredGroups.containsKey(displayId)) { + LOG.info("Notification group " + displayId + " is already registered", new Throwable()); } + ourRegisteredGroups.put(displayId, this); } public static NotificationGroup balloonGroup(@NotNull String displayId) { @@ -72,4 +84,29 @@ public class NotificationGroup { @Nullable NotificationListener listener) { return new Notification(myDisplayId, title, content, type, listener); } + + @NotNull + public NotificationDisplayType getDisplayType() { + return myDisplayType; + } + + public boolean isLogByDefault() { + return myLogByDefault; + } + + @Nullable + public String getToolWindowId() { + return myToolWindowId; + } + + @Nullable + public static NotificationGroup findRegisteredGroup(String displayId) { + return ourRegisteredGroups.get(displayId); + } + + @NotNull + public static Iterable getAllRegisteredGroups() { + return ourRegisteredGroups.values(); + } + } diff --git a/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java b/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java index bfaf9c762351..b2f55dd3de9e 100644 --- a/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java +++ b/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java @@ -25,5 +25,6 @@ public abstract class NotificationsConfiguration extends NotificationsAdapter { return ApplicationManager.getApplication().getComponent(NotificationsConfiguration.class); } + @Deprecated public abstract void registerToolWindowCapability(@NotNull String groupId, @NotNull String toolWindowId); } diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java index 770a3471f766..24ecbd5468d3 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java @@ -23,11 +23,11 @@ import org.jetbrains.annotations.Nullable; /** * @author spleaner */ -public class NotificationSettings { +public final class NotificationSettings { private final String myGroupId; - private NotificationDisplayType myDisplayType; - private boolean myShouldLog; - private boolean myShouldReadAloud; + private final NotificationDisplayType myDisplayType; + private final boolean myShouldLog; + private final boolean myShouldReadAloud; public NotificationSettings(String groupId, NotificationDisplayType displayType, boolean shouldLog, boolean shouldReadAloud) { myGroupId = groupId; @@ -50,18 +50,21 @@ public class NotificationSettings { return myShouldLog; } - public void setShouldLog(boolean shouldLog) { - myShouldLog = shouldLog; + public NotificationSettings withShouldLog(boolean shouldLog) { + return new NotificationSettings(myGroupId, myDisplayType, shouldLog, myShouldReadAloud); } public boolean isShouldReadAloud() { return myShouldReadAloud; } - public void setShouldReadAloud(boolean shouldReadAloud) { - myShouldReadAloud = shouldReadAloud; + public NotificationSettings withShouldReadAloud(boolean shouldReadAloud) { + return new NotificationSettings(myGroupId, myDisplayType, myShouldLog, shouldReadAloud); } + public NotificationSettings withDisplayType(NotificationDisplayType displayType) { + return new NotificationSettings(myGroupId, displayType, myShouldLog, myShouldReadAloud); + } @Nullable public static NotificationSettings load(@NotNull final Element element) { @@ -104,7 +107,27 @@ public class NotificationSettings { return result; } - public void setDisplayType(final NotificationDisplayType displayType) { - myDisplayType = displayType; + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof NotificationSettings)) return false; + + NotificationSettings settings = (NotificationSettings)o; + + if (myShouldLog != settings.myShouldLog) return false; + if (myShouldReadAloud != settings.myShouldReadAloud) return false; + if (myDisplayType != settings.myDisplayType) return false; + if (!myGroupId.equals(settings.myGroupId)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myGroupId.hashCode(); + result = 31 * result + myDisplayType.hashCode(); + result = 31 * result + (myShouldLog ? 1 : 0); + result = 31 * result + (myShouldReadAloud ? 1 : 0); + return result; } } diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java index d946f5ce72c9..98694bb235d8 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java @@ -15,14 +15,13 @@ */ package com.intellij.notification.impl; -import com.intellij.notification.Notification; import com.intellij.notification.NotificationDisplayType; +import com.intellij.notification.NotificationGroup; import com.intellij.notification.NotificationsConfiguration; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.Function; -import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import org.jdom.Element; @@ -62,12 +61,13 @@ public class NotificationsConfigurationImpl extends NotificationsConfiguration i } public synchronized boolean hasToolWindowCapability(@NotNull String groupId) { - return myToolWindowCapable.containsKey(groupId); + return getToolWindowId(groupId) != null || myToolWindowCapable.containsKey(groupId); } @Nullable - public synchronized String getToolWindowId(@NotNull String groupId) { - return myToolWindowCapable.get(groupId); + public String getToolWindowId(@NotNull String groupId) { + NotificationGroup group = NotificationGroup.findRegisteredGroup(groupId); + return group == null ? null : group.getToolWindowId(); } public static NotificationSettings[] getAllSettings() { @@ -91,11 +91,15 @@ public class NotificationsConfigurationImpl extends NotificationsConfiguration i private synchronized void _remove(String... toRemove) { for (final String id : toRemove) { myIdToSettingsMap.remove(id); + myToolWindowCapable.remove(id); } } private synchronized NotificationSettings[] _getAllSettings() { - Collection settings = myIdToSettingsMap.values(); + Collection settings = ContainerUtil.newHashSet(myIdToSettingsMap.values()); + for (NotificationGroup group : NotificationGroup.getAllRegisteredGroups()) { + settings.add(getSettings(group.getDisplayId())); + } NotificationSettings[] result = settings.toArray(new NotificationSettings[settings.size()]); Arrays.sort(result, new Comparator() { @Override @@ -114,7 +118,16 @@ public class NotificationsConfigurationImpl extends NotificationsConfiguration i @NotNull public static NotificationSettings getSettings(@NotNull final String groupId) { final NotificationSettings settings = getNotificationsConfigurationImpl()._getSettings(groupId); - return settings == null ? new NotificationSettings(groupId, NotificationDisplayType.BALLOON, true, false) : settings; + return settings == null ? getDefaultSettings(groupId) : settings; + } + + @NotNull + private static NotificationSettings getDefaultSettings(String groupId) { + NotificationGroup group = NotificationGroup.findRegisteredGroup(groupId); + if (group != null) { + return new NotificationSettings(groupId, group.getDisplayType(), group.isLogByDefault(), false); + } + return new NotificationSettings(groupId, NotificationDisplayType.BALLOON, true, false); } @Override @@ -154,19 +167,27 @@ public class NotificationsConfigurationImpl extends NotificationsConfiguration i changeSettings(groupDisplayName, displayType, shouldLog, shouldReadAloud); } else if (displayType == NotificationDisplayType.TOOL_WINDOW && !hasToolWindowCapability(groupDisplayName)) { // the first time with tool window capability - ObjectUtils.assertNotNull(_getSettings(groupDisplayName)).setDisplayType(NotificationDisplayType.TOOL_WINDOW); + changeSettings(getSettings(groupDisplayName).withDisplayType(NotificationDisplayType.TOOL_WINDOW)); myToolWindowCapable.put(groupDisplayName, null); } - } @Override public void changeSettings(String groupDisplayName, NotificationDisplayType displayType, boolean shouldLog, boolean shouldReadAloud) { - myIdToSettingsMap.put(groupDisplayName, new NotificationSettings(groupDisplayName, displayType, shouldLog, shouldReadAloud)); + changeSettings(new NotificationSettings(groupDisplayName, displayType, shouldLog, shouldReadAloud)); + } + + public synchronized void changeSettings(NotificationSettings settings) { + String groupDisplayName = settings.getGroupId(); + if (settings.equals(getDefaultSettings(groupDisplayName))) { + myIdToSettingsMap.remove(groupDisplayName); + } else { + myIdToSettingsMap.put(groupDisplayName, settings); + } } public synchronized boolean isRegistered(@NotNull final String id) { - return myIdToSettingsMap.containsKey(id); + return myIdToSettingsMap.containsKey(id) || NotificationGroup.findRegisteredGroup(id) != null; } @Override @@ -178,6 +199,12 @@ public class NotificationsConfigurationImpl extends NotificationsConfiguration i for (String entry: myToolWindowCapable.keySet()) { element.addContent(new Element("toolWindow").setAttribute("group", entry)); } + for (NotificationGroup group : NotificationGroup.getAllRegisteredGroups()) { + String displayId = group.getDisplayId(); + if (!myToolWindowCapable.containsKey(displayId) && group.getToolWindowId() != null) { + element.addContent(new Element("toolWindow").setAttribute("group", displayId)); + } + } //noinspection NonPrivateFieldAccessedInSynchronizedContext if (!SHOW_BALLOONS) { element.setAttribute(SHOW_BALLOONS_ATTRIBUTE, "false"); diff --git a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java index c1e316eb555f..73af2c304beb 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java @@ -236,20 +236,16 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable } } - private static class SettingsWrapper extends NotificationSettings { - private final NotificationSettings myOriginal; + private static class SettingsWrapper { private boolean myRemoved = false; + private NotificationSettings myVersion; - private SettingsWrapper(@NotNull final NotificationSettings original) { - super(original.getGroupId(), original.getDisplayType(), original.isShouldLog(), original.isShouldReadAloud()); - myOriginal = original; + private SettingsWrapper(NotificationSettings settings) { + myVersion = settings; } public boolean hasChanged() { - return !getDisplayType().equals(myOriginal.getDisplayType()) - || isShouldLog() != myOriginal.isShouldLog() - || isShouldReadAloud() != myOriginal.isShouldReadAloud() - || myRemoved; + return myRemoved || !getOriginalSettings().equals(myVersion); } public void remove() { @@ -260,24 +256,27 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable return myRemoved; } + @NotNull + private NotificationSettings getOriginalSettings() { + return NotificationsConfigurationImpl.getSettings(getGroupId()); + } + public void apply() { if (myRemoved) { - NotificationsConfigurationImpl.remove(myOriginal.getGroupId()); + NotificationsConfigurationImpl.remove(getGroupId()); } else { - if (hasChanged()) { - myOriginal.setDisplayType(getDisplayType()); - myOriginal.setShouldLog(isShouldLog()); - myOriginal.setShouldReadAloud(isShouldReadAloud()); - } + NotificationsConfigurationImpl.getNotificationsConfigurationImpl().changeSettings(myVersion); } } public void reset() { - if (hasChanged()) { - setDisplayType(myOriginal.getDisplayType()); - myRemoved = false; - } + myVersion = getOriginalSettings(); + myRemoved = false; + } + + String getGroupId() { + return myVersion.getGroupId(); } } @@ -285,9 +284,8 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable private final List mySettings; public NotificationsTableModel() { - final NotificationSettings[] settings = NotificationsConfigurationImpl.getAllSettings(); final List list = new ArrayList(); - for (NotificationSettings setting : settings) { + for (NotificationSettings setting : NotificationsConfigurationImpl.getAllSettings()) { list.add(new SettingsWrapper(setting)); } @@ -300,17 +298,17 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable @Override public void setValueAt(final Object value, final int rowIndex, final int columnIndex) { - final NotificationSettings settings = getSettings(rowIndex); + final SettingsWrapper wrapper = getSettings(rowIndex); switch (columnIndex) { case NotificationsTable.DISPLAY_TYPE_COLUMN: - settings.setDisplayType((NotificationDisplayType)value); + wrapper.myVersion = wrapper.myVersion.withDisplayType((NotificationDisplayType)value); break; case NotificationsTable.LOG_COLUMN: - settings.setShouldLog((Boolean)value); + wrapper.myVersion = wrapper.myVersion.withShouldLog((Boolean)value); break; case NotificationsTable.READ_ALOUD_COLUMN: - settings.setShouldReadAloud((Boolean)value); + wrapper.myVersion = wrapper.myVersion.withShouldReadAloud((Boolean)value); break; } } @@ -319,7 +317,7 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable return getSettings().size(); } - public NotificationSettings getSettings(int row) { + public SettingsWrapper getSettings(int row) { return getSettings().get(row); } @@ -366,12 +364,12 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable case NotificationsTable.ID_COLUMN: return getSettings().get(rowIndex).getGroupId(); case NotificationsTable.LOG_COLUMN: - return getSettings().get(rowIndex).isShouldLog(); + return getSettings().get(rowIndex).myVersion.isShouldLog(); case NotificationsTable.READ_ALOUD_COLUMN: - return getSettings().get(rowIndex).isShouldReadAloud(); + return getSettings().get(rowIndex).myVersion.isShouldReadAloud(); case NotificationsTable.DISPLAY_TYPE_COLUMN: default: - return getSettings().get(rowIndex).getDisplayType(); + return getSettings().get(rowIndex).myVersion.getDisplayType(); } }