vcs: Refactor "CommittedChangesPanel" and inheritors

GitOrigin-RevId: b65cabf3f1d8fa3cadb061633bc06649efe7c0cf
This commit is contained in:
Konstantin Kolosovsky
2019-12-21 19:41:55 +00:00
committed by intellij-monorepo-bot
parent 7ff08ff35b
commit 449465ed96
4 changed files with 194 additions and 268 deletions
@@ -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
}
@@ -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<CommittedChangeList> 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<CommittedChangeList> ->
browser.emptyText.text = message("committed.changes.empty.message")
browser.setItems(changeLists, CommittedChangesBrowserUseCase.COMMITTED)
}
val errorHandler = { errors: List<VcsException> ->
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<CommittedChangeList>()
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<? extends CommittedChangeList> 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);
})
}
}
@@ -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();
}
}
@@ -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<RepositoryLocationCommittedChangesPanel<*>>()
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<S : ChangeBrowserSettings>(
project: Project,
val provider: CommittedChangesProvider<*, S>,
val repositoryLocation: RepositoryLocation,
extraActions: DefaultActionGroup
) : CommittedChangesPanel(project) {
public class RepositoryLocationCommittedChangesPanel<S extends ChangeBrowserSettings> extends CommittedChangesPanel {
private static final Logger LOG = Logger.getInstance(RepositoryLocationCommittedChangesPanel.class);
@Volatile
private var isDisposed = false
@NotNull private final CommittedChangesProvider<?, S> 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<?, S> 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<String> { 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<CommittedChangeList> ->
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<CommittedChangeList> {
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<List<CommittedChangeList>> appender = list ->
runOrInvokeLaterAboveProgress(() -> myBrowser.append(list), ModalityState.stateForComponent(myBrowser), myProject);
final BufferedListConsumer<CommittedChangeList> bufferedListConsumer = new BufferedListConsumer<>(30, appender, -1);
myProvider.loadCommittedChanges(mySettings, myRepositoryLocation, myMaxCount, new AsynchConsumer<CommittedChangeList>() {
@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<String>)s -> refreshChanges();
if (REMOTE_HISTORY_LOCATION.is(dataId)) return myRepositoryLocation;
return super.getData(dataId);
}
@Override
public void dispose() {
myDisposed = true;
}
}