From 9926cce708e7338cb481eabe73a5377a7ab73f07 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sat, 12 Jan 2019 21:17:18 +0100 Subject: [PATCH] add FrameStateListener message bus topic --- .../intellij/debugger/ui/impl/TipManager.java | 12 +- .../com/intellij/ide/FrameStateListener.java | 8 +- .../com/intellij/ide/FrameStateManager.java | 27 +- .../ide/FileChangedNotificationProvider.java | 11 +- .../intellij/ide/FrameStateManagerImpl.java | 42 +-- .../intellij/ide/SaveAndSyncHandlerImpl.kt | 290 ++++++++---------- .../updater/StatisticsJobsScheduler.java | 18 +- .../impl/NotificationsManagerImpl.java | 7 +- .../src/com/intellij/ui/BalloonImpl.java | 12 +- .../configurationStore/StateStorageManager.kt | 3 +- .../testFramework/PlatformTestUtil.java | 4 +- .../src/org/jetbrains/idea/svn/SvnVcs.java | 27 +- 12 files changed, 202 insertions(+), 259 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java index 4111009f7e3d..d5a581315911 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java @@ -1,8 +1,8 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.debugger.ui.impl; +import com.intellij.application.Topics; import com.intellij.ide.FrameStateListener; -import com.intellij.ide.FrameStateManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -43,7 +43,6 @@ public class TipManager implements Disposable, PopupMenuListener { boolean isFocusOwner(); } - private boolean isOverTip(MouseEvent e) { if (myCurrentTooltip != null) { if(!myCurrentTooltip.isShowing()) { @@ -222,7 +221,7 @@ public class TipManager implements Disposable, PopupMenuListener { public void hideTooltip() { hideTooltip(true); } - + public void hideTooltip(boolean now) { if (myTipPopup == null) return; @@ -246,7 +245,6 @@ public class TipManager implements Disposable, PopupMenuListener { private final JComponent myComponent; private MouseListener myMouseListener = new MyMouseListener(); private MouseMotionListener myMouseMotionListener = new MyMouseMotionListener(); - private FrameStateListener myFrameStateListener = new MyFrameStateListener(); private final Alarm myShowAlarm = new Alarm(); private final Alarm myHideAlarm = new Alarm(); @@ -300,7 +298,7 @@ public class TipManager implements Disposable, PopupMenuListener { myHideCanceller = new MyAwtPreprocessor(); Toolkit.getDefaultToolkit().addAWTEventListener(myHideCanceller, AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK); - FrameStateManager.getInstance().addListener(myFrameStateListener); + Topics.subscribe(FrameStateListener.TOPIC, this, new MyFrameStateListener()); } @Override @@ -315,8 +313,6 @@ public class TipManager implements Disposable, PopupMenuListener { myShowAlarm.cancelAllRequests(); myMouseListener = null; myMouseMotionListener = null; - FrameStateManager.getInstance().removeListener(myFrameStateListener); - myFrameStateListener = null; } private class MyAwtPreprocessor implements AWTEventListener { diff --git a/platform/platform-api/src/com/intellij/ide/FrameStateListener.java b/platform/platform-api/src/com/intellij/ide/FrameStateListener.java index 00491cf9a89c..d68fffb50724 100644 --- a/platform/platform-api/src/com/intellij/ide/FrameStateListener.java +++ b/platform/platform-api/src/com/intellij/ide/FrameStateListener.java @@ -1,14 +1,16 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide; +import com.intellij.util.messages.Topic; + /** * Listener for receiving notifications when the IDEA window is activated or deactivated. * * @since 5.0.2 - * @see FrameStateManager#addListener(FrameStateListener) - * @see FrameStateManager#removeListener(FrameStateListener) */ public interface FrameStateListener { + Topic TOPIC = new Topic<>("FrameStateListener", FrameStateListener.class); + /** * Called when the IDEA window is deactivated. */ diff --git a/platform/platform-api/src/com/intellij/ide/FrameStateManager.java b/platform/platform-api/src/com/intellij/ide/FrameStateManager.java index 7d8ccc5b561d..b48bbda67c41 100644 --- a/platform/platform-api/src/com/intellij/ide/FrameStateManager.java +++ b/platform/platform-api/src/com/intellij/ide/FrameStateManager.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2009 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide; import com.intellij.openapi.Disposable; @@ -27,7 +13,6 @@ import org.jetbrains.annotations.Nullable; * * @since 5.0.2 */ - public abstract class FrameStateManager { /** * Returns the global {@code FrameStateManager} instance. @@ -39,11 +24,15 @@ public abstract class FrameStateManager { } /** - * Adds a listener which is called when the IDEA window is activated or deactivated. - * - * @param listener the listener instance. + * @deprecated Use message bus {@link FrameStateListener#TOPIC} */ + @Deprecated public abstract void addListener(@NotNull FrameStateListener listener); + + /** + * @deprecated Use message bus {@link FrameStateListener#TOPIC} + */ + @Deprecated public abstract void addListener(@NotNull FrameStateListener listener, @Nullable Disposable disposable); /** diff --git a/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java b/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java index 0be6ea681995..2ef65a35a03d 100644 --- a/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java +++ b/platform/platform-impl/src/com/intellij/ide/FileChangedNotificationProvider.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide; import com.intellij.openapi.application.ApplicationManager; @@ -32,10 +32,12 @@ public class FileChangedNotificationProvider extends EditorNotifications.Provide private final Project myProject; - public FileChangedNotificationProvider(@NotNull Project project, @NotNull FrameStateManager frameStateManager) { + public FileChangedNotificationProvider(@NotNull Project project) { myProject = project; - frameStateManager.addListener(new FrameStateListener() { + MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(myProject); + + connection.subscribe(FrameStateListener.TOPIC, new FrameStateListener() { @Override public void onFrameActivated() { if (!myProject.isDisposed() && !GeneralSettings.getInstance().isSyncOnFrameActivation()) { @@ -45,9 +47,8 @@ public class FileChangedNotificationProvider extends EditorNotifications.Provide } } } - }, project); + }); - MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(myProject); connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { @Override public void after(@NotNull List events) { diff --git a/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java index d6f29a78a3f1..1a9bf874a34e 100644 --- a/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/FrameStateManagerImpl.java @@ -1,26 +1,11 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationActivationListener; -import com.intellij.openapi.application.impl.ApplicationImpl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.BusyObject; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.IdeFrame; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -32,18 +17,16 @@ public class FrameStateManagerImpl extends FrameStateManager { private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); private final BusyObject.Impl myActive; - private final ApplicationImpl myApp; - public FrameStateManagerImpl(final ApplicationImpl app) { - myApp = app; + public FrameStateManagerImpl() { myActive = new BusyObject.Impl() { @Override public boolean isReady() { - return myApp.isActive(); + return ApplicationManager.getApplication().isActive(); } }; - app.getMessageBus().connect().subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener() { + ApplicationManager.getApplication().getMessageBus().connect().subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener() { @Override public void applicationActivated(@NotNull IdeFrame ideFrame) { System.setProperty("com.jetbrains.suppressWindowRaise", "false"); @@ -54,7 +37,7 @@ public class FrameStateManagerImpl extends FrameStateManager { @Override public void applicationDeactivated(@NotNull IdeFrame ideFrame) { System.setProperty("com.jetbrains.suppressWindowRaise", "true"); - if (!app.isDisposed()) { + if (!ApplicationManager.getApplication().isDisposed()) { fireDeactivationEvent(); } } @@ -80,19 +63,16 @@ public class FrameStateManagerImpl extends FrameStateManager { @Override public void addListener(@NotNull FrameStateListener listener) { - addListener(listener, null); + myListeners.add(listener); } @Override public void addListener(@NotNull final FrameStateListener listener, @Nullable Disposable disposable) { - myListeners.add(listener); if (disposable != null) { - Disposer.register(disposable, new Disposable() { - @Override - public void dispose() { - removeListener(listener); - } - }); + ApplicationManager.getApplication().getMessageBus().connect(disposable).subscribe(FrameStateListener.TOPIC, listener); + } + else { + myListeners.add(listener); } } diff --git a/platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandlerImpl.kt b/platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandlerImpl.kt index d30e19d5ce96..c1284baa1371 100644 --- a/platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandlerImpl.kt +++ b/platform/platform-impl/src/com/intellij/ide/SaveAndSyncHandlerImpl.kt @@ -1,202 +1,162 @@ -/* - * Copyright 2000-2017 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.ide; +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.ide -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.application.TransactionGuard; -import com.intellij.openapi.application.impl.LaterInvocator; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.newvfs.ManagingFS; -import com.intellij.openapi.vfs.newvfs.NewVirtualFile; -import com.intellij.openapi.vfs.newvfs.RefreshQueue; -import com.intellij.openapi.vfs.newvfs.RefreshSession; -import com.intellij.util.SingleAlarm; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.application.TransactionGuard +import com.intellij.openapi.application.impl.LaterInvocator +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.diagnostic.debug +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.project.ProjectManager +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.newvfs.ManagingFS +import com.intellij.openapi.vfs.newvfs.NewVirtualFile +import com.intellij.openapi.vfs.newvfs.RefreshQueue +import com.intellij.util.SingleAlarm +import java.beans.PropertyChangeListener +import java.util.concurrent.atomic.AtomicInteger -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; +private val LOG = Logger.getInstance(SaveAndSyncHandler::class.java) -/** - * @author Anton Katilin - * @author Vladimir Kondratyev - */ -public class SaveAndSyncHandlerImpl extends SaveAndSyncHandler implements Disposable { - private static final Logger LOG = Logger.getInstance(SaveAndSyncHandler.class); +class SaveAndSyncHandlerImpl(private val settings: GeneralSettings, fileDocumentManager: FileDocumentManager) : SaveAndSyncHandler(), Disposable { + private val generalSettingsListener: PropertyChangeListener + private val refreshDelayAlarm = SingleAlarm(Runnable { this.doScheduledRefresh() }, delay = 300, parentDisposable = this) + private val blockSaveOnFrameDeactivationCount = AtomicInteger() + private val blockSyncOnFrameActivationCount = AtomicInteger() + @Volatile + private var refreshSessionId: Long = 0 - private final Runnable myIdleListener; - private final PropertyChangeListener myGeneralSettingsListener; - private final GeneralSettings mySettings; - private final ProgressManager myProgressManager; - private final SingleAlarm myRefreshDelayAlarm = new SingleAlarm(this::doScheduledRefresh, 300, this); - private final AtomicInteger myBlockSaveOnFrameDeactivationCount = new AtomicInteger(); - private final AtomicInteger myBlockSyncOnFrameActivationCount = new AtomicInteger(); - private volatile long myRefreshSessionId; - - public SaveAndSyncHandlerImpl(@NotNull GeneralSettings generalSettings, - @NotNull ProgressManager progressManager, - @NotNull FrameStateManager frameStateManager, - @NotNull FileDocumentManager fileDocumentManager) { - mySettings = generalSettings; - myProgressManager = progressManager; - - myIdleListener = () -> { - if (mySettings.isAutoSaveIfInactive() && canSyncOrSave()) { - TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> ((FileDocumentManagerImpl)fileDocumentManager).saveAllDocuments(false)); + private val idleListener = { + if (settings.isAutoSaveIfInactive && canSyncOrSave()) { + submitTransaction { + (fileDocumentManager as FileDocumentManagerImpl).saveAllDocuments(false) } - }; - IdeEventQueue.getInstance().addIdleListener(myIdleListener, mySettings.getInactiveTimeout() * 1000); + } + } - myGeneralSettingsListener = new PropertyChangeListener() { - @Override - public void propertyChange(@NotNull PropertyChangeEvent e) { - if (GeneralSettings.PROP_INACTIVE_TIMEOUT.equals(e.getPropertyName())) { - IdeEventQueue eventQueue = IdeEventQueue.getInstance(); - eventQueue.removeIdleListener(myIdleListener); - Integer timeout = (Integer)e.getNewValue(); - eventQueue.addIdleListener(myIdleListener, timeout.intValue() * 1000); - } + init { + IdeEventQueue.getInstance().addIdleListener(idleListener, settings.inactiveTimeout * 1000) + + generalSettingsListener = PropertyChangeListener { e -> + if (GeneralSettings.PROP_INACTIVE_TIMEOUT == e.propertyName) { + val eventQueue = IdeEventQueue.getInstance() + eventQueue.removeIdleListener(idleListener) + eventQueue.addIdleListener(idleListener, (e.newValue as Int) * 1000) } - }; - mySettings.addPropertyChangeListener(myGeneralSettingsListener); + } + settings.addPropertyChangeListener(generalSettingsListener) - frameStateManager.addListener(new FrameStateListener() { - @Override - public void onFrameDeactivated() { - LOG.debug("save(): enter"); - TransactionGuard.submitTransaction(ApplicationManager.getApplication(), () -> { + val busConnection = ApplicationManager.getApplication().messageBus.connect(this) + busConnection.subscribe(FrameStateListener.TOPIC, object : FrameStateListener { + override fun onFrameDeactivated() { + LOG.debug("save(): enter") + submitTransaction { if (canSyncOrSave()) { - saveProjectsAndDocuments(); + saveProjectsAndDocuments() } - LOG.debug("save(): exit"); - }); - } - - @Override - public void onFrameActivated() { - if (!ApplicationManager.getApplication().isDisposed() && mySettings.isSyncOnFrameActivation()) { - scheduleRefresh(); + LOG.debug("save(): exit") } } - }); - } - @Override - public void dispose() { - RefreshQueue.getInstance().cancelSession(myRefreshSessionId); - mySettings.removePropertyChangeListener(myGeneralSettingsListener); - IdeEventQueue.getInstance().removeIdleListener(myIdleListener); - } - - private boolean canSyncOrSave() { - return !LaterInvocator.isInModalContext() && !myProgressManager.hasModalProgressIndicator(); - } - - @Override - public void saveProjectsAndDocuments() { - Application app = ApplicationManager.getApplication(); - if (!app.isDisposed() && - mySettings.isSaveOnFrameDeactivation() && - myBlockSaveOnFrameDeactivationCount.get() == 0) { - app.saveAll(); - } - } - - @Override - public void scheduleRefresh() { - myRefreshDelayAlarm.cancelAndRequest(); - } - - private void doScheduledRefresh() { - TransactionGuard.submitTransaction(this, () -> { - if (canSyncOrSave()) { - refreshOpenFiles(); + override fun onFrameActivated() { + if (!ApplicationManager.getApplication().isDisposed && settings.isSyncOnFrameActivation) { + scheduleRefresh() + } } - maybeRefresh(ModalityState.NON_MODAL); - }); + }) } - public void maybeRefresh(@NotNull ModalityState modalityState) { - if (myBlockSyncOnFrameActivationCount.get() == 0 && mySettings.isSyncOnFrameActivation()) { - RefreshQueue queue = RefreshQueue.getInstance(); - queue.cancelSession(myRefreshSessionId); + override fun dispose() { + RefreshQueue.getInstance().cancelSession(refreshSessionId) + settings.removePropertyChangeListener(generalSettingsListener) + IdeEventQueue.getInstance().removeIdleListener(idleListener) + } - RefreshSession session = queue.createSession(true, true, null, modalityState); - session.addAllFiles(ManagingFS.getInstance().getLocalRoots()); - myRefreshSessionId = session.getId(); - session.launch(); - LOG.debug("vfs refreshed"); - } - else if (LOG.isDebugEnabled()) { - LOG.debug("vfs refresh rejected, blocked: " + (myBlockSyncOnFrameActivationCount.get() != 0) - + ", isSyncOnFrameActivation: " + mySettings.isSyncOnFrameActivation()); + private fun canSyncOrSave(): Boolean { + return !LaterInvocator.isInModalContext() && !ProgressManager.getInstance().hasModalProgressIndicator() + } + + override fun saveProjectsAndDocuments() { + val app = ApplicationManager.getApplication() + if (!app.isDisposed && + settings.isSaveOnFrameDeactivation && + blockSaveOnFrameDeactivationCount.get() == 0) { + app.saveAll() } } - @Override - public void refreshOpenFiles() { - List files = ContainerUtil.newArrayList(); + override fun scheduleRefresh() { + refreshDelayAlarm.cancelAndRequest() + } - for (Project project : ProjectManager.getInstance().getOpenProjects()) { - for (VirtualFile file : FileEditorManager.getInstance(project).getSelectedFiles()) { - if (file instanceof NewVirtualFile) { - files.add(file); + private fun doScheduledRefresh() { + submitTransaction { + if (canSyncOrSave()) { + refreshOpenFiles() + } + maybeRefresh(ModalityState.NON_MODAL) + } + } + + fun maybeRefresh(modalityState: ModalityState) { + if (blockSyncOnFrameActivationCount.get() == 0 && settings.isSyncOnFrameActivation) { + val queue = RefreshQueue.getInstance() + queue.cancelSession(refreshSessionId) + + val session = queue.createSession(true, true, null, modalityState) + session.addAllFiles(*ManagingFS.getInstance().localRoots) + refreshSessionId = session.id + session.launch() + LOG.debug("vfs refreshed") + } + else { + LOG.debug { "vfs refresh rejected, blocked: ${blockSyncOnFrameActivationCount.get() != 0}, isSyncOnFrameActivation: ${settings.isSyncOnFrameActivation}" } + } + } + + override fun refreshOpenFiles() { + val files = ArrayList() + + for (project in ProjectManager.getInstance().openProjects) { + for (file in FileEditorManager.getInstance(project).selectedFiles) { + if (file is NewVirtualFile) { + files.add(file) } } } if (!files.isEmpty()) { // refresh open files synchronously so it doesn't wait for potentially longish refresh request in the queue to finish - RefreshQueue.getInstance().refresh(false, false, null, files); + RefreshQueue.getInstance().refresh(false, false, null, files) } } - @Override - public void blockSaveOnFrameDeactivation() { - LOG.debug("save blocked"); - myBlockSaveOnFrameDeactivationCount.incrementAndGet(); + override fun blockSaveOnFrameDeactivation() { + LOG.debug("save blocked") + blockSaveOnFrameDeactivationCount.incrementAndGet() } - @Override - public void unblockSaveOnFrameDeactivation() { - myBlockSaveOnFrameDeactivationCount.decrementAndGet(); - LOG.debug("save unblocked"); + override fun unblockSaveOnFrameDeactivation() { + blockSaveOnFrameDeactivationCount.decrementAndGet() + LOG.debug("save unblocked") } - @Override - public void blockSyncOnFrameActivation() { - LOG.debug("sync blocked"); - myBlockSyncOnFrameActivationCount.incrementAndGet(); + override fun blockSyncOnFrameActivation() { + LOG.debug("sync blocked") + blockSyncOnFrameActivationCount.incrementAndGet() } - @Override - public void unblockSyncOnFrameActivation() { - myBlockSyncOnFrameActivationCount.decrementAndGet(); - LOG.debug("sync unblocked"); + override fun unblockSyncOnFrameActivation() { + blockSyncOnFrameActivationCount.decrementAndGet() + LOG.debug("sync unblocked") } -} \ No newline at end of file + + private inline fun submitTransaction(crossinline handler: () -> Unit) { + TransactionGuard.submitTransaction(this, Runnable { handler() }) + } +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java b/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java index 0644799b2f81..5fe21b559ad9 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/updater/StatisticsJobsScheduler.java @@ -1,20 +1,22 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.internal.statistic.updater; +import com.intellij.application.Topics; import com.intellij.concurrency.JobScheduler; import com.intellij.ide.FrameStateListener; -import com.intellij.ide.FrameStateManager; import com.intellij.internal.statistic.connect.StatisticsService; import com.intellij.internal.statistic.eventLog.FeatureUsageLogger; import com.intellij.internal.statistic.service.fus.collectors.FUStatisticRecorder; import com.intellij.internal.statistic.service.fus.collectors.FUStatisticsStateService; import com.intellij.internal.statistic.utils.StatisticsUploadAssistant; import com.intellij.notification.impl.NotificationsConfigurationImpl; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.BaseComponent; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.IdeFrameImpl; @@ -41,8 +43,6 @@ public class StatisticsJobsScheduler implements BaseComponent { public static final int PERSIST_SESSIONS_INITIAL_DELAY_IN_MIN = 30; public static final int PERSIST_SESSIONS_DELAY_IN_MIN = 12 * 60; - private final FrameStateManager myFrameStateManager; - private static final Map myPersistStatisticsSessionsMap = Collections.synchronizedMap(new HashMap<>()); @Override @@ -53,9 +53,8 @@ public class StatisticsJobsScheduler implements BaseComponent { runStatisticsSessionsPersistence(); } - public StatisticsJobsScheduler(@NotNull FrameStateManager frameStateManager) { + public StatisticsJobsScheduler() { NotificationsConfigurationImpl.remove("SendUsagesStatistics"); - myFrameStateManager = frameStateManager; } private static boolean isEmpty(Window window) { @@ -69,15 +68,16 @@ public class StatisticsJobsScheduler implements BaseComponent { return false; } - private void runStatisticsService() { + private static void runStatisticsService() { if (StatisticsUploadAssistant.isShouldShowNotification()) { - myFrameStateManager.addListener(new FrameStateListener() { + Disposable disposable = Disposer.newDisposable(); + Topics.subscribe(FrameStateListener.TOPIC, disposable, new FrameStateListener() { @Override public void onFrameActivated() { if (isEmpty(((WindowManagerEx)WindowManager.getInstance()).getMostRecentFocusedWindow())) { final StatisticsService statisticsService = StatisticsUploadAssistant.getApprovedGroupsStatisticsService(); ApplicationManager.getApplication().invokeLater(() -> StatisticsNotificationManager.showNotification(statisticsService)); - myFrameStateManager.removeListener(this); + Disposer.dispose(disposable); } } }); diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java index ba1676de54c8..e6e9c6550a7f 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java @@ -1,6 +1,7 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.notification.impl; +import com.intellij.application.Topics; import com.intellij.codeInsight.hint.TooltipController; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; @@ -289,13 +290,13 @@ public class NotificationsManagerImpl extends NotificationsManager { callback.run(); } else { - FrameStateManager.getInstance().addListener(new FrameStateListener() { + Topics.subscribe(FrameStateListener.TOPIC, balloon, new FrameStateListener() { @Override public void onFrameActivated() { FrameStateManager.getInstance().removeListener(this); callback.run(); } - }, balloon); + }); } } diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index d6c76b38b5d6..d9190ec32acd 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -1,9 +1,13 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui; +import com.intellij.application.Topics; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.icons.AllIcons; -import com.intellij.ide.*; +import com.intellij.ide.FrameStateListener; +import com.intellij.ide.IdeEventQueue; +import com.intellij.ide.IdeTooltip; +import com.intellij.ide.RemoteDesktopService; import com.intellij.openapi.MnemonicHelper; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -881,7 +885,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { public void startSmartFadeoutTimer(int delay) { mySmartFadeout = true; mySmartFadeoutDelay = delay; - FrameStateManager.getInstance().addListener(new FrameStateListener() { + Topics.subscribe(FrameStateListener.TOPIC, this, new FrameStateListener() { @Override public void onFrameDeactivated() { if (myFadeoutAlarm.getActiveRequestCount() > 0) { @@ -892,7 +896,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { } } } - }, this); + }); } public void startFadeoutTimer(final int fadeoutDelay) { diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/StateStorageManager.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/StateStorageManager.kt index f95d38a4777a..f4ac4851ebd0 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/StateStorageManager.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/StateStorageManager.kt @@ -39,7 +39,8 @@ interface StorageCreator { } /** - * Low-level method to save component manager state store. Intended for Java clients only. + * Low-level method to save component manager state store. Use it with care and only if you understand what are you doing. + * Intended for Java clients only. Do not use in Kotlin. */ @JvmOverloads fun saveComponentManager(componentManager: ComponentManager, isForceSavingAllSettings: Boolean = false) { diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java index 4eb720095cf3..e74343435bcd 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java @@ -598,9 +598,9 @@ public class PlatformTestUtil { saveProject(project, false); } - public static void saveProject(@NotNull Project project, boolean isForce) { + public static void saveProject(@NotNull Project project, boolean isForceSavingAllSettings) { ProjectManagerEx.getInstanceEx().flushChangedProjectFileAlarm(); - StateStorageManagerKt.saveComponentManager(project, isForce); + StateStorageManagerKt.saveComponentManager(project, isForceSavingAllSettings); } static void waitForAllBackgroundActivityToCalmDown() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index a12856708fc9..4951fe831b2f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -1,11 +1,11 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.idea.svn; import com.intellij.ide.FrameStateListener; -import com.intellij.ide.FrameStateManager; import com.intellij.idea.RareLogger; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -15,6 +15,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.annotate.AnnotationProvider; @@ -116,7 +117,8 @@ public class SvnVcs extends AbstractVcs { private SvnCopiesRefreshManager myCopiesRefreshManager; private SvnFileUrlMappingImpl myMapping; - private final MyFrameStateListener myFrameStateListener; + + private Disposable myFrameStateListenerDisposable; //Consumer public static final Topic ROOTS_RELOADED = new Topic<>("ROOTS_RELOADED", Consumer.class); @@ -164,8 +166,6 @@ public class SvnVcs extends AbstractVcs { myVcsListener = () -> invokeRefreshSvnRoots(); } - myFrameStateListener = project.isDefault() ? null : new MyFrameStateListener(ChangeListManager.getInstance(project), - VcsDirtyScopeManager.getInstance(project)); myChecker = new SvnExecutableChecker(this); Application app = ApplicationManager.getApplication(); @@ -298,9 +298,10 @@ public class SvnVcs extends AbstractVcs { @Override public void activate() { + MessageBusConnection busConnection = myProject.getMessageBus().connect(); if (!myProject.isDefault()) { ChangeListManager.getInstance(myProject).addChangeListListener(myChangeListListener); - myProject.getMessageBus().connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, myVcsListener); + busConnection.subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, myVcsListener); } SvnApplicationSettings.getInstance().svnActivated(); @@ -309,7 +310,11 @@ public class SvnVcs extends AbstractVcs { } // this will initialize its inner listener for committed changes upload LoadedRevisionsCache.getInstance(myProject); - FrameStateManager.getInstance().addListener(myFrameStateListener); + if (myFrameStateListenerDisposable == null && !myProject.isDefault()) { + myFrameStateListenerDisposable = Disposer.newDisposable(); + busConnection.subscribe(FrameStateListener.TOPIC, new MyFrameStateListener(ChangeListManager.getInstance(myProject), + VcsDirtyScopeManager.getInstance(myProject))); + } myAuthNotifier.init(); mySvnBranchPointsCalculator = new SvnBranchPointsCalculator(this); @@ -336,7 +341,7 @@ public class SvnVcs extends AbstractVcs { }, SvnBundle.message("refreshing.working.copies.roots.progress.text"), true, myProject);*/ }); - myProject.getMessageBus().connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, myRootsToWorkingCopies); + busConnection.subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, myRootsToWorkingCopies); myLoadedBranchesStorage.activate(); } @@ -355,7 +360,11 @@ public class SvnVcs extends AbstractVcs { @Override public void deactivate() { - FrameStateManager.getInstance().removeListener(myFrameStateListener); + Disposable frameStateListenerDisposable = myFrameStateListenerDisposable; + if (frameStateListenerDisposable != null) { + myFrameStateListenerDisposable = null; + Disposer.dispose(frameStateListenerDisposable); + } if (myEntriesFileListener != null) { VirtualFileManager.getInstance().removeVirtualFileListener(myEntriesFileListener);