From 449465ed963b1da0ee0b73e36e13105da003f339 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 18 Dec 2019 18:15:46 +0300 Subject: [PATCH] vcs: Refactor "CommittedChangesPanel" and inheritors GitOrigin-RevId: b65cabf3f1d8fa3cadb061633bc06649efe7c0cf --- .../committed/CommittedChangesPanel.kt | 96 ++++---- .../committed/ProjectCommittedChangesPanel.kt | 144 +++++------- .../committed/RefreshCommittedAction.java | 9 +- ...RepositoryLocationCommittedChangesPanel.kt | 213 ++++++++---------- 4 files changed, 194 insertions(+), 268 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.kt index 365358f088e0..bfea2fe9004e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesPanel.kt @@ -1,71 +1,53 @@ // 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.openapi.vcs.changes.committed -package com.intellij.openapi.vcs.changes.committed; +import com.intellij.openapi.Disposable +import com.intellij.openapi.actionSystem.ActionGroup +import com.intellij.openapi.actionSystem.ActionManager +import com.intellij.openapi.actionSystem.CommonShortcuts +import com.intellij.openapi.actionSystem.DataProvider +import com.intellij.openapi.actionSystem.EmptyAction.registerWithShortcutSet +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Disposer +import com.intellij.util.ui.components.BorderLayoutPanel +import javax.swing.Box +import javax.swing.BoxLayout +import javax.swing.JPanel -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +abstract class CommittedChangesPanel(protected val project: Project) : BorderLayoutPanel(), DataProvider, Disposable { -import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; -import java.util.Collections; + protected val browser: CommittedChangesTreeBrowser = + CommittedChangesTreeBrowser(project, emptyList()).also { Disposer.register(this, it) } -public abstract class CommittedChangesPanel extends JPanel implements DataProvider, Disposable { - @NotNull protected final CommittedChangesTreeBrowser myBrowser; - @NotNull protected final Project myProject; + protected fun setup(extraActions: ActionGroup?, auxiliaryView: VcsCommittedViewAuxiliary?) { + addToCenter(browser) - public CommittedChangesPanel(@NotNull Project project) { - super(new BorderLayout()); - myProject = project; - myBrowser = new CommittedChangesTreeBrowser(project, new ArrayList<>()); - Disposer.register(this, myBrowser); - } + val group = ActionManager.getInstance().getAction("CommittedChangesToolbar") as ActionGroup + val toolBar = browser.createGroupFilterToolbar(project, group, extraActions, auxiliaryView?.toolbarActions.orEmpty()) + val filterComponent = CommittedChangesFilterComponent() + Disposer.register(this, filterComponent) - protected void setup(@Nullable ActionGroup extraActions, @Nullable VcsCommittedViewAuxiliary auxiliary) { - add(myBrowser, BorderLayout.CENTER); + val toolbarPanel = JPanel().apply { + layout = BoxLayout(this, BoxLayout.X_AXIS) - JPanel toolbarPanel = new JPanel(); - toolbarPanel.setLayout(new BoxLayout(toolbarPanel, BoxLayout.X_AXIS)); - - ActionGroup group = (ActionGroup)ActionManager.getInstance().getAction("CommittedChangesToolbar"); - - ActionToolbar toolBar = myBrowser.createGroupFilterToolbar(myProject, group, extraActions, - auxiliary != null ? auxiliary.getToolbarActions() : Collections.emptyList()); - CommittedChangesFilterComponent filterComponent = new CommittedChangesFilterComponent(); - Disposer.register(this, filterComponent); - - toolbarPanel.add(toolBar.getComponent()); - toolbarPanel.add(Box.createHorizontalGlue()); - toolbarPanel.add(filterComponent); - filterComponent.setMinimumSize(filterComponent.getPreferredSize()); - filterComponent.setMaximumSize(filterComponent.getPreferredSize()); - myBrowser.setToolBar(toolbarPanel); - - if (auxiliary != null) { - Disposer.register(this, () -> auxiliary.getCalledOnViewDispose()); - myBrowser.setTableContextMenu(group, auxiliary.getPopupActions()); - } - else { - myBrowser.setTableContextMenu(group, Collections.emptyList()); + add(toolBar.component) + add(Box.createHorizontalGlue()) + add(filterComponent) } + filterComponent.minimumSize = filterComponent.preferredSize + filterComponent.maximumSize = filterComponent.preferredSize + browser.setToolBar(toolbarPanel) - EmptyAction.registerWithShortcutSet("CommittedChanges.Refresh", CommonShortcuts.getRerun(), this); - myBrowser.addFilter(filterComponent); + auxiliaryView?.let { Disposer.register(this, Disposable { it.calledOnViewDispose }) } + browser.setTableContextMenu(group, auxiliaryView?.popupActions.orEmpty()) + browser.addFilter(filterComponent) + + registerWithShortcutSet("CommittedChanges.Refresh", CommonShortcuts.getRerun(), this) } - public abstract void refreshChanges(); + abstract fun refreshChanges() - @Nullable - @Override - public Object getData(@NotNull String dataId) { - return myBrowser.getData(dataId); - } + override fun getData(dataId: String): Any? = browser.getData(dataId) - @Override - public void dispose() { - } -} + override fun dispose() = Unit +} \ No newline at end of file diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ProjectCommittedChangesPanel.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ProjectCommittedChangesPanel.kt index cbe8442a960c..8d3b9b0e1525 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ProjectCommittedChangesPanel.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ProjectCommittedChangesPanel.kt @@ -1,104 +1,70 @@ // 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.openapi.vcs.changes.committed; +package com.intellij.openapi.vcs.changes.committed -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.AbstractVcsHelper; -import com.intellij.openapi.vcs.CommittedChangesProvider; -import com.intellij.openapi.vcs.VcsBundle; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.application.runInEdt +import com.intellij.openapi.project.Project +import com.intellij.openapi.vcs.AbstractVcsHelper +import com.intellij.openapi.vcs.CommittedChangesProvider +import com.intellij.openapi.vcs.VcsBundle.message +import com.intellij.openapi.vcs.VcsException +import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList +import com.intellij.openapi.vfs.VirtualFile -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +internal class ProjectCommittedChangesPanel( + project: Project, + var provider: CommittedChangesProvider<*, *> +) : CommittedChangesPanel(project) { -public class ProjectCommittedChangesPanel extends CommittedChangesPanel { - @NotNull private CommittedChangesProvider myProvider; + private val cache = CommittedChangesCache.getInstance(project) - public ProjectCommittedChangesPanel(@NotNull Project project, @NotNull CommittedChangesProvider provider) { - super(project); - myProvider = provider; - - setup(null, provider.createActions(myBrowser, null)); + init { + setup(null, provider.createActions(browser, null)) } - @NotNull - public CommittedChangesProvider getProvider() { - return myProvider; - } - - public void setProvider(@NotNull CommittedChangesProvider provider) { - myProvider = provider; - } - - @Override - public void refreshChanges() { - final CommittedChangesCache cache = CommittedChangesCache.getInstance(myProject); - cache.hasCachesForAnyRoot(notEmpty -> { - if (!notEmpty) { - myBrowser.getEmptyText().setText(VcsBundle.message("committed.changes.not.loaded.message")); - return; - } - cache.getProjectChangesAsync( - myProvider.createDefaultSettings(), 0, true, - committedChangeLists -> updateFilteredModel(committedChangeLists, false), - vcsExceptions -> AbstractVcsHelper - .getInstance(myProject).showErrors(vcsExceptions, "Error refreshing VCS history") - ); - }); - } - - public void clearCaches() { - final CommittedChangesCache cache = CommittedChangesCache.getInstance(myProject); - cache.clearCaches( - () -> ApplicationManager.getApplication() - .invokeLater(() -> updateFilteredModel(Collections.emptyList(), true), ModalityState.NON_MODAL, myProject.getDisposed()) - ); - } - - public void passCachedListsToListener(@NotNull VcsConfigurationChangeListener.DetailedNotification notification, - @Nullable VirtualFile root) { - final List resultList = new ArrayList<>(); - myBrowser.reportLoadedLists(new CommittedChangeListsListener() { - @Override - public void onBeforeStartReport() { + override fun refreshChanges() = + cache.hasCachesForAnyRoot { hasCaches -> + if (!hasCaches) { + browser.emptyText.text = message("committed.changes.not.loaded.message") + return@hasCachesForAnyRoot } - @Override - public boolean report(@NotNull CommittedChangeList list) { - resultList.add(list); - return false; + val changeListsConsumer = { changeLists: List -> + browser.emptyText.text = message("committed.changes.empty.message") + browser.setItems(changeLists, CommittedChangesBrowserUseCase.COMMITTED) + } + val errorHandler = { errors: List -> + AbstractVcsHelper.getInstance(project).showErrors(errors, "Error refreshing VCS history") + } + cache.getProjectChangesAsync(provider.createDefaultSettings(), 0, true, changeListsConsumer, errorHandler) + } + + fun clearCaches() = + cache.clearCaches { + runInEdt(ModalityState.NON_MODAL) { + if (project.isDisposed) return@runInEdt + + browser.emptyText.text = message("committed.changes.not.loaded.message") + browser.setItems(emptyList(), CommittedChangesBrowserUseCase.COMMITTED) + } + } + + fun passCachedListsToListener(notification: VcsConfigurationChangeListener.DetailedNotification, root: VirtualFile?) { + val changeLists = mutableListOf() + + browser.reportLoadedLists(object : CommittedChangeListsListener { + override fun onBeforeStartReport() = Unit + + override fun report(list: CommittedChangeList): Boolean { + changeLists.add(list) + return false } - @Override - public void onAfterEndReport() { - if (!resultList.isEmpty()) { - notification.execute(myProject, root, resultList); + override fun onAfterEndReport() { + if (changeLists.isNotEmpty()) { + notification.execute(project, root, changeLists) } } - }); - } - - private void updateFilteredModel(List committedChangeLists, final boolean reset) { - if (committedChangeLists == null) { - return; - } - setEmptyMessage(!reset); - myBrowser.setItems(committedChangeLists, CommittedChangesBrowserUseCase.COMMITTED); - } - - private void setEmptyMessage(boolean changesLoaded) { - String emptyText; - if (!changesLoaded) { - emptyText = VcsBundle.message("committed.changes.not.loaded.message"); - } - else { - emptyText = VcsBundle.message("committed.changes.empty.message"); - } - myBrowser.getEmptyText().setText(emptyText); + }) } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RefreshCommittedAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RefreshCommittedAction.java index 5e3d453e8cdd..59533f9a6def 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RefreshCommittedAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RefreshCommittedAction.java @@ -18,7 +18,6 @@ public class RefreshCommittedAction extends AnAction implements DumbAware { Project project = e.getData(CommonDataKeys.PROJECT); CommittedChangesPanel panel = ChangesViewContentManager.getInstance(project).getActiveComponent(CommittedChangesPanel.class); assert panel != null; - if (isLoading(panel)) return; if (panel instanceof RepositoryLocationCommittedChangesPanel) { panel.refreshChanges(); } @@ -32,14 +31,12 @@ public class RefreshCommittedAction extends AnAction implements DumbAware { Project project = e.getData(CommonDataKeys.PROJECT); if (project != null) { CommittedChangesPanel panel = ChangesViewContentManager.getInstance(project).getActiveComponent(CommittedChangesPanel.class); - e.getPresentation().setEnabled(panel != null && !isLoading(panel)); + boolean isLoading = + panel instanceof RepositoryLocationCommittedChangesPanel && ((RepositoryLocationCommittedChangesPanel)panel).isLoading(); + e.getPresentation().setEnabled(panel != null && !isLoading); } else { e.getPresentation().setEnabled(false); } } - - private static boolean isLoading(@NotNull CommittedChangesPanel panel) { - return panel instanceof RepositoryLocationCommittedChangesPanel && ((RepositoryLocationCommittedChangesPanel)panel).isLoading(); - } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCommittedChangesPanel.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCommittedChangesPanel.kt index 6fb233f3dd7f..b7a38192e969 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCommittedChangesPanel.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/RepositoryLocationCommittedChangesPanel.kt @@ -1,135 +1,116 @@ // 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.openapi.vcs.changes.committed; +package com.intellij.openapi.vcs.changes.committed -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.CommittedChangesProvider; -import com.intellij.openapi.vcs.RepositoryLocation; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import com.intellij.util.AsynchConsumer; -import com.intellij.util.BufferedListConsumer; -import com.intellij.util.Consumer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.openapi.actionSystem.DefaultActionGroup +import com.intellij.openapi.application.ModalityState +import com.intellij.openapi.application.runInEdt +import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.progress.Task.Backgroundable +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.Messages.showErrorDialog +import com.intellij.openapi.vcs.CommittedChangesProvider +import com.intellij.openapi.vcs.RepositoryLocation +import com.intellij.openapi.vcs.VcsDataKeys.REMOTE_HISTORY_CHANGED_LISTENER +import com.intellij.openapi.vcs.VcsDataKeys.REMOTE_HISTORY_LOCATION +import com.intellij.openapi.vcs.VcsException +import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings +import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList +import com.intellij.util.AsynchConsumer +import com.intellij.util.BufferedListConsumer +import com.intellij.util.Consumer -import java.util.List; +private val LOG = logger>() -import static com.intellij.openapi.vcs.VcsDataKeys.REMOTE_HISTORY_CHANGED_LISTENER; -import static com.intellij.openapi.vcs.VcsDataKeys.REMOTE_HISTORY_LOCATION; -import static com.intellij.util.WaitForProgressToShow.runOrInvokeLaterAboveProgress; +internal class RepositoryLocationCommittedChangesPanel( + project: Project, + val provider: CommittedChangesProvider<*, S>, + val repositoryLocation: RepositoryLocation, + extraActions: DefaultActionGroup +) : CommittedChangesPanel(project) { -public class RepositoryLocationCommittedChangesPanel extends CommittedChangesPanel { - private static final Logger LOG = Logger.getInstance(RepositoryLocationCommittedChangesPanel.class); + @Volatile + private var isDisposed = false - @NotNull private final CommittedChangesProvider myProvider; - @NotNull private final RepositoryLocation myRepositoryLocation; + var maxCount: Int = 0 - private S mySettings; - private int myMaxCount; - private volatile boolean isLoading; - private volatile boolean myDisposed; + var settings: S = provider.createDefaultSettings() - public RepositoryLocationCommittedChangesPanel(@NotNull Project project, - @NotNull CommittedChangesProvider provider, - @NotNull RepositoryLocation repositoryLocation, - @NotNull ActionGroup extraActions) { - super(project); - myProvider = provider; - myRepositoryLocation = repositoryLocation; - mySettings = provider.createDefaultSettings(); + var isLoading: Boolean = false + private set - setup(extraActions, myProvider.createActions(myBrowser, myRepositoryLocation)); + init { + setup(extraActions, provider.createActions(browser, repositoryLocation)) } - public void setSettings(@NotNull S settings) { - mySettings = settings; + fun setChangesFilter() { + val dialog = CommittedChangesFilterDialog(project, provider.createFilterUI(true), settings) + if (!dialog.showAndGet()) return + + @Suppress("UNCHECKED_CAST") + settings = dialog.settings as S + refreshChanges() } - public void setMaxCount(int maxCount) { - myMaxCount = maxCount; + override fun refreshChanges() = LoadCommittedChangesTask().queue() + + override fun getData(dataId: String): Any? = + when { + REMOTE_HISTORY_CHANGED_LISTENER.`is`(dataId) -> Consumer { refreshChanges() } + REMOTE_HISTORY_LOCATION.`is`(dataId) -> repositoryLocation + else -> super.getData(dataId) + } + + override fun dispose() { + isDisposed = true } - public boolean isLoading() { - return isLoading; - } + private inner class LoadCommittedChangesTask : Backgroundable(project, "Loading Changes", true) { + private var error: VcsException? = null - public void setChangesFilter() { - CommittedChangesFilterDialog filterDialog = new CommittedChangesFilterDialog(myProject, myProvider.createFilterUI(true), mySettings); - if (filterDialog.showAndGet()) { - //noinspection unchecked - mySettings = (S)filterDialog.getSettings(); - refreshChanges(); + init { + browser.reset() + isLoading = true + browser.setLoading(true) + } + + override fun run(indicator: ProgressIndicator) = + try { + val appender = { changeLists: List -> + runInEdt(ModalityState.stateForComponent(browser)) { + if (project.isDisposed) return@runInEdt + + browser.append(changeLists) + } + } + val bufferedAppender = BufferedListConsumer(30, appender, -1) + + provider.loadCommittedChanges(settings, repositoryLocation, maxCount, object : AsynchConsumer { + override fun consume(changeList: CommittedChangeList) { + if (isDisposed) indicator.cancel() + + ProgressManager.checkCanceled() + bufferedAppender.consumeOne(changeList) + } + + override fun finished() = bufferedAppender.flush() + }) + } + catch (e: VcsException) { + LOG.info(e) + error = e + } + + override fun onSuccess() { + error?.let { + showErrorDialog(myProject, "Error refreshing view: ${it.messages.joinToString("\n")}", "Committed Changes") + } + } + + override fun onFinished() { + isLoading = false + browser.setLoading(false) } } - - @Override - public void refreshChanges() { - myBrowser.reset(); - - isLoading = true; - myBrowser.setLoading(true); - ProgressManager.getInstance().run(new Task.Backgroundable(myProject, "Loading changes", true) { - - @Override - public void run(@NotNull final ProgressIndicator indicator) { - try { - Consumer> appender = list -> - runOrInvokeLaterAboveProgress(() -> myBrowser.append(list), ModalityState.stateForComponent(myBrowser), myProject); - final BufferedListConsumer bufferedListConsumer = new BufferedListConsumer<>(30, appender, -1); - - myProvider.loadCommittedChanges(mySettings, myRepositoryLocation, myMaxCount, new AsynchConsumer() { - @Override - public void finished() { - bufferedListConsumer.flush(); - } - - @Override - public void consume(CommittedChangeList committedChangeList) { - if (myDisposed) { - indicator.cancel(); - } - ProgressManager.checkCanceled(); - bufferedListConsumer.consumeOne(committedChangeList); - } - }); - } - catch (final VcsException e) { - LOG.info(e); - runOrInvokeLaterAboveProgress( - () -> Messages - .showErrorDialog(myProject, "Error refreshing view: " + StringUtil.join(e.getMessages(), "\n"), "Committed Changes"), - null, - myProject - ); - } - finally { - isLoading = false; - myBrowser.setLoading(false); - } - } - }); - } - - - @Nullable - @Override - public Object getData(@NotNull String dataId) { - if (REMOTE_HISTORY_CHANGED_LISTENER.is(dataId)) return (Consumer)s -> refreshChanges(); - if (REMOTE_HISTORY_LOCATION.is(dataId)) return myRepositoryLocation; - return super.getData(dataId); - } - - @Override - public void dispose() { - myDisposed = true; - } } \ No newline at end of file