vcs: use new ChangesBrowser in commit dialog

* do not show checkboxes in alien commit dialog, as they are ignored anyway
This commit is contained in:
Aleksey Pivovarov
2017-10-03 18:13:41 +03:00
committed by Aleksey Pivovarov
parent d489bfccc6
commit 30ef642a5c
7 changed files with 292 additions and 554 deletions
@@ -28,8 +28,9 @@ import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserBase;
import com.intellij.openapi.vcs.changes.ui.ChangesListView;
import com.intellij.openapi.vcs.changes.ui.OldChangesBrowserBase;
import com.intellij.openapi.vcs.changes.ui.CommitDialogChangesBrowser;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
@@ -59,13 +60,13 @@ public class ScheduleForAdditionAction extends AnAction implements DumbAware {
Project project = e.getRequiredData(CommonDataKeys.PROJECT);
List<VirtualFile> unversionedFiles = getUnversionedFiles(e, project).collect(Collectors.toList());
addUnversioned(project, unversionedFiles, this::isStatusForAddition, e.getData(OldChangesBrowserBase.DATA_KEY));
addUnversioned(project, unversionedFiles, this::isStatusForAddition, e.getData(ChangesBrowserBase.DATA_KEY));
}
public static boolean addUnversioned(@NotNull Project project,
@NotNull List<VirtualFile> files,
@NotNull Condition<FileStatus> unversionedFileCondition,
@Nullable OldChangesBrowserBase browser) {
@Nullable ChangesBrowserBase browser) {
boolean result = true;
if (!files.isEmpty()) {
@@ -73,13 +74,20 @@ public class ScheduleForAdditionAction extends AnAction implements DumbAware {
@SuppressWarnings("unchecked")
Consumer<List<Change>> consumer = browser == null ? null : changes -> {
browser.rebuildList();
browser.getViewer().excludeChanges((List)files);
if (browser instanceof CommitDialogChangesBrowser) {
((CommitDialogChangesBrowser)browser).updateDisplayedChangeLists();
}
browser.getViewer().includeChanges((List)changes);
};
ChangeListManagerImpl manager = ChangeListManagerImpl.getInstanceImpl(project);
LocalChangeList targetChangeList =
browser == null ? manager.getDefaultChangeList() : (LocalChangeList)browser.getSelectedChangeList();
LocalChangeList targetChangeList;
if (browser instanceof CommitDialogChangesBrowser) {
targetChangeList = ((CommitDialogChangesBrowser)browser).getSelectedChangeList();
}
else {
targetChangeList = manager.getDefaultChangeList();
}
List<VcsException> exceptions = manager.addUnversionedFiles(targetChangeList, files, unversionedFileCondition, consumer);
result = exceptions.isEmpty();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -16,49 +16,107 @@
package com.intellij.openapi.vcs.changes.ui;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeList;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.changes.RemoteRevisionsCache;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.DefaultTreeModel;
import java.util.Collections;
import java.util.List;
public class AlienChangeListBrowser extends ChangesBrowser {
private final List<Change> myChanges;
public class AlienChangeListBrowser extends CommitDialogChangesBrowser {
@NotNull private final LocalChangeList myChangeList;
@NotNull private final List<Change> myChanges;
public AlienChangeListBrowser(final Project project, final List<? extends ChangeList> changeLists, final List<Change> changes,
final ChangeList initialListSelection, final boolean capableOfExcludingChanges,
final boolean highlightProblems) {
super(project, changeLists, changes, initialListSelection, capableOfExcludingChanges, highlightProblems, null, MyUseCase.LOCAL_CHANGES, null);
public AlienChangeListBrowser(@NotNull Project project,
@NotNull LocalChangeList changelist,
@NotNull List<Change> changes) {
super(project, true, true);
myChangeList = changelist;
myChanges = changes;
rebuildList();
init();
}
@Override
public void rebuildList() {
// dont change lists
myViewer.setChangesToDisplay(myChanges == null ? Collections.emptyList() : myChanges);
}
protected void setInitialSelection(final List<? extends ChangeList> changeLists, final List<Change> changes, final ChangeList initialListSelection) {
if (! changeLists.isEmpty()) {
mySelectedChangeList = changeLists.get(0);
}
}
@Override
protected void buildToolBar(DefaultActionGroup toolBarGroup) {
super.buildToolBar(toolBarGroup);
toolBarGroup.add(ActionManager.getInstance().getAction("AlienCommitChangesDialog.AdditionalActions"));
}
@Override
@NotNull
public List<Change> getCurrentIncludedChanges() {
return ContainerUtil.newArrayList(myChanges);
@Override
protected List<AnAction> createToolbarActions() {
return ContainerUtil.append(
super.createToolbarActions(),
ActionManager.getInstance().getAction("AlienCommitChangesDialog.AdditionalActions")
);
}
@NotNull
@Override
protected DefaultTreeModel buildTreeModel(boolean showFlatten) {
RemoteStatusChangeNodeDecorator decorator = RemoteRevisionsCache.getInstance(myProject).getChangesNodeDecorator();
return TreeModelBuilder.buildFromChanges(myProject, showFlatten, myChanges, decorator);
}
@NotNull
@Override
public LocalChangeList getSelectedChangeList() {
return myChangeList;
}
@NotNull
@Override
public List<Change> getDisplayedChanges() {
return myChanges;
}
@NotNull
@Override
public List<Change> getSelectedChanges() {
return VcsTreeModelData.selected(myViewer).userObjects(Change.class);
}
@NotNull
@Override
public List<Change> getIncludedChanges() {
return myChanges;
}
@NotNull
@Override
public List<VirtualFile> getDisplayedUnversionedFiles() {
return Collections.emptyList();
}
@NotNull
@Override
public List<VirtualFile> getSelectedUnversionedFiles() {
return Collections.emptyList();
}
@NotNull
@Override
public List<VirtualFile> getIncludedUnversionedFiles() {
return Collections.emptyList();
}
@Override
public void updateDisplayedChangeLists() {
}
@Nullable
@Override
public Object getData(String dataId) {
if (VcsDataKeys.CHANGE_LISTS.is(dataId)) {
return new ChangeList[]{myChangeList};
}
return super.getData(dataId);
}
}
@@ -19,9 +19,7 @@ import com.intellij.diff.util.DiffPlaces;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataSink;
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.extensions.Extensions;
@@ -53,6 +51,7 @@ import com.intellij.util.ui.AbstractLayoutManager;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.JBDimension;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.components.BorderLayoutPanel;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -70,7 +69,6 @@ import static com.intellij.openapi.vcs.VcsBundle.message;
import static com.intellij.util.ArrayUtil.isEmpty;
import static com.intellij.util.ArrayUtil.toObjectArray;
import static com.intellij.util.ObjectUtils.notNull;
import static com.intellij.util.containers.ContainerUtil.createMaybeSingletonList;
import static com.intellij.util.containers.ContainerUtil.isEmpty;
import static com.intellij.util.containers.ContainerUtil.map;
import static com.intellij.util.containers.ContainerUtil.map2SetNotNull;
@@ -80,7 +78,7 @@ import static com.intellij.util.containers.ContainerUtil.newHashMap;
import static com.intellij.util.containers.ContainerUtil.newHashSet;
import static java.util.Collections.*;
public class CommitChangeListDialog extends DialogWrapper implements CheckinProjectPanel, TypeSafeDataProvider {
public class CommitChangeListDialog extends DialogWrapper implements CheckinProjectPanel, DataProvider {
private static final String HELP_ID = "reference.dialogs.vcs.commit";
private static final String TITLE = message("commit.dialog.title");
@@ -110,7 +108,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
@NotNull private final CommitOptionsPanel myCommitOptions;
@NotNull private final CommitContext myCommitContext;
@NotNull private final ChangeInfoCalculator myChangesInfoCalculator;
@NotNull private final OldChangesBrowserBase<?> myBrowser;
@NotNull private final CommitDialogChangesBrowser myBrowser;
@NotNull private final MyChangeProcessor myDiffDetails;
@NotNull private final CommitMessage myCommitMessageArea;
@NotNull private final CommitLegendPanel myLegend;
@@ -290,36 +288,46 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
myCommitMessageArea = new CommitMessage(project, true, true, myShowVcsCommit);
if (myIsAlien) {
myCommitMessageArea.setChangeLists(newArrayList(changeLists));
myBrowser = new AlienChangeListBrowser(project, changeLists, changes, initialSelection, true, true);
} else {
myCommitMessageArea.setChangeLists(createMaybeSingletonList(initialSelection));
//noinspection unchecked
MultipleChangeListBrowser browser =
new MultipleChangeListBrowser(project, changeLists, (List)changes, initialSelection, () -> updateWarning(),
() -> myHandlers.forEach(CheckinHandler::includedChangesChanged), myShowVcsCommit);
browser.addSelectedListChangeListener(new SelectedListChangeListener() {
@Override
public void selectedListChanged() {
myCommitMessageArea.setChangeLists(createMaybeSingletonList(browser.getSelectedChangeList()));
updateOnListSelection();
}
});
myBrowser = browser;
myBrowser.setAlwayExpandList(false);
}
myBrowser.getViewer().addSelectionListener(() -> SwingUtilities.invokeLater(() -> changeDetails()));
myBrowser.setDiffBottomComponent(new DiffCommitMessageEditor(myProject, myCommitMessageArea));
assert changeLists.size() == 1;
LocalChangeList changeList = changeLists.get(0);
mySplitter = new Splitter(true);
mySplitter.setHonorComponentsMinimumSize(true);
mySplitter.setFirstComponent(myBrowser);
mySplitter.setSecondComponent(myCommitMessageArea);
mySplitter.setProportion(PropertiesComponent.getInstance().getFloat(SPLITTER_PROPORTION_OPTION, SPLITTER_PROPORTION_OPTION_DEFAULT));
myBrowser = new AlienChangeListBrowser(project, changeList, changes);
myCommitMessageArea.setChangeList(changeList);
}
else {
MultipleLocalChangeListsBrowser browser = new MultipleLocalChangeListsBrowser(project, true, true, myShowVcsCommit);
myBrowser = browser;
if (initialSelection != null) browser.setSelectedChangeList(initialSelection);
myCommitMessageArea.setChangeList(browser.getSelectedChangeList());
DiffCommitMessageEditor commitMessageEditor = new DiffCommitMessageEditor(myProject, myCommitMessageArea);
browser.setBottomDiffComponent(commitMessageEditor);
browser.setInclusionChangedListener(() -> myHandlers.forEach(CheckinHandler::includedChangesChanged));
browser.setSelectedListChangeListener(() -> {
myCommitMessageArea.setChangeList(browser.getSelectedChangeList());
updateOnListSelection();
updateWarning();
});
browser.getViewer().addSelectionListener(() -> SwingUtilities.invokeLater(() -> changeDetails()));
browser.getViewer().setKeepTreeState(true);
}
myBrowser.getViewer().setIncludedChanges(changes);
myChangesInfoCalculator = new ChangeInfoCalculator();
myLegend = new CommitLegendPanel(myChangesInfoCalculator);
myBrowser.getBottomPanel().add(JBUI.Panels.simplePanel().addToRight(myLegend.getComponent()), BorderLayout.SOUTH);
BorderLayoutPanel legendPanel = JBUI.Panels.simplePanel().addToRight(myLegend.getComponent());
BorderLayoutPanel topPanel = JBUI.Panels.simplePanel().addToCenter(myBrowser).addToBottom(legendPanel);
mySplitter = new Splitter(true);
mySplitter.setHonorComponentsMinimumSize(true);
mySplitter.setFirstComponent(topPanel);
mySplitter.setSecondComponent(myCommitMessageArea);
mySplitter.setProportion(PropertiesComponent.getInstance().getFloat(SPLITTER_PROPORTION_OPTION, SPLITTER_PROPORTION_OPTION_DEFAULT));
if (!myVcsConfiguration.CLEAR_INITIAL_COMMIT_MESSAGE) {
setComment(initialSelection, comment);
@@ -860,7 +868,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
public Collection<VirtualFile> getRoots() {
ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
return map2SetNotNull(myBrowser.getCurrentDisplayedChanges(), change -> vcsManager.getVcsRootFor(ChangesUtil.getFilePath(change)));
return map2SetNotNull(myBrowser.getDisplayedChanges(), change -> vcsManager.getVcsRootFor(ChangesUtil.getFilePath(change)));
}
@NotNull
@@ -920,7 +928,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
@Override
public void refresh() {
ChangeListManager.getInstance(myProject).invokeAfterUpdate(() -> {
myBrowser.rebuildList();
myBrowser.updateDisplayedChangeLists();
myCommitOptions.refresh();
}, InvokeAfterUpdateMode.SILENT, "commit dialog", ModalityState.current());
}
@@ -955,14 +963,15 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
private void updateLegend() {
if (myDisposed || myUpdateDisabled) return;
myChangesInfoCalculator.update(myBrowser.getCurrentDisplayedChanges(), getIncludedChanges(), myBrowser.getUnversionedFilesCount(),
myChangesInfoCalculator.update(myBrowser.getDisplayedChanges(), getIncludedChanges(),
myBrowser.getDisplayedUnversionedFiles().size(),
myBrowser.getIncludedUnversionedFiles().size());
myLegend.update();
}
@NotNull
private List<Change> getIncludedChanges() {
return myBrowser.getCurrentIncludedChanges();
return myBrowser.getIncludedChanges();
}
@Override
@@ -976,14 +985,13 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
return myCommitMessageArea.getEditorField();
}
@Nullable
@Override
public void calcData(DataKey key, DataSink sink) {
if (key == Refreshable.PANEL_KEY) {
sink.put(Refreshable.PANEL_KEY, this);
}
else {
myBrowser.calcData(key, sink);
public Object getData(String dataId) {
if (Refreshable.PANEL_KEY.is(dataId)) {
return this;
}
return myBrowser.getData(dataId);
}
@NotNull
@@ -992,13 +1000,8 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
}
private void ensureDataIsActual(@NotNull Runnable runnable) {
if (myBrowser.isDataIsDirty()) {
ChangeListManager.getInstance(myProject).invokeAfterUpdate(runnable, InvokeAfterUpdateMode.SYNCHRONOUS_CANCELLABLE,
"Refreshing changelists...", ModalityState.current());
}
else {
runnable.run();
}
ChangeListManager.getInstance(myProject).invokeAfterUpdate(runnable, InvokeAfterUpdateMode.SYNCHRONOUS_CANCELLABLE,
"Refreshing changelists...", ModalityState.current());
}
private class CommitExecutorAction extends AbstractAction {
@@ -1055,13 +1058,13 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
@NotNull
@Override
protected List<Change> getAllChanges() {
return myBrowser.getAllChanges();
return myBrowser.getDisplayedChanges();
}
@Override
protected void selectChange(@NotNull Change change) {
//noinspection unchecked
myBrowser.select((List)singletonList(change));
myBrowser.selectEntries((List)singletonList(change));
}
@Override
@@ -0,0 +1,63 @@
/*
* 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.openapi.vcs.changes.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public abstract class CommitDialogChangesBrowser extends ChangesBrowserBase implements Disposable {
public CommitDialogChangesBrowser(@NotNull Project project,
boolean showCheckboxes,
boolean highlightProblems) {
super(project, showCheckboxes, highlightProblems);
}
@Override
public void dispose() {
}
@NotNull
public abstract LocalChangeList getSelectedChangeList();
@NotNull
public abstract List<Change> getDisplayedChanges();
@NotNull
public abstract List<Change> getSelectedChanges();
@NotNull
public abstract List<Change> getIncludedChanges();
@NotNull
public abstract List<VirtualFile> getDisplayedUnversionedFiles();
@NotNull
public abstract List<VirtualFile> getSelectedUnversionedFiles();
@NotNull
public abstract List<VirtualFile> getIncludedUnversionedFiles();
public abstract void updateDisplayedChangeLists();
}
@@ -1,457 +0,0 @@
/*
* 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.openapi.vcs.changes.ui;
import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.AnActionListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.actions.MoveChangesToAnotherListAction;
import com.intellij.openapi.vcs.changes.actions.RollbackDialogAction;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.ColoredListCellRendererWrapper;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.EventDispatcher;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.*;
import java.util.List;
import static com.intellij.openapi.util.text.StringUtil.capitalize;
import static com.intellij.openapi.util.text.StringUtil.shortenTextWithEllipsis;
import static java.util.stream.Collectors.toList;
public class MultipleChangeListBrowser extends OldChangesBrowserBase<Object> {
@NotNull private final ChangeListChooser myChangeListChooser;
@NotNull final ChangeListListener myChangeListListener = new MyChangeListListener();
@NotNull private final EventDispatcher<SelectedListChangeListener> myDispatcher =
EventDispatcher.create(SelectedListChangeListener.class);
@Nullable private final Runnable myRebuildListListener;
@NotNull private final VcsConfiguration myVcsConfiguration;
private final boolean myUnversionedFilesEnabled;
private boolean myInRebuildList;
private AnAction myMoveActionWithCustomShortcut;
// todo terrible constructor
public MultipleChangeListBrowser(@NotNull Project project,
@NotNull List<? extends ChangeList> changeLists,
@NotNull List<Object> changes,
@Nullable ChangeList initialListSelection,
@Nullable Runnable rebuildListListener,
@Nullable Runnable inclusionListener,
boolean unversionedFilesEnabled) {
super(project, changes, true, true, inclusionListener, ChangesBrowser.MyUseCase.LOCAL_CHANGES, null, Object.class);
myRebuildListListener = rebuildListListener;
myVcsConfiguration = ObjectUtils.assertNotNull(VcsConfiguration.getInstance(myProject));
myUnversionedFilesEnabled = unversionedFilesEnabled;
init();
setInitialSelection(changeLists, changes, initialListSelection);
myChangeListChooser = new ChangeListChooser();
myHeaderPanel.add(myChangeListChooser, BorderLayout.EAST);
ChangeListManager.getInstance(myProject).addChangeListListener(myChangeListListener);
setupRebuildListForActions();
rebuildList();
}
private void setupRebuildListForActions() {
ActionManager actionManager = ActionManager.getInstance();
final AnAction moveAction = actionManager.getAction(IdeActions.MOVE_TO_ANOTHER_CHANGE_LIST);
final AnAction deleteAction = actionManager.getAction("ChangesView.DeleteUnversioned.From.Dialog");
actionManager.addAnActionListener(new AnActionListener.Adapter() {
@Override
public void afterActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
if (moveAction.equals(action) || myMoveActionWithCustomShortcut != null && myMoveActionWithCustomShortcut.equals(action)) {
rebuildList();
}
else if (deleteAction.equals(action)) {
UnversionedViewDialog.refreshChanges(myProject, MultipleChangeListBrowser.this);
}
}
}, this);
}
private boolean isShowUnversioned() {
return myUnversionedFilesEnabled && myVcsConfiguration.SHOW_UNVERSIONED_FILES_WHILE_COMMIT;
}
private void setShowUnversioned(boolean value) {
myVcsConfiguration.SHOW_UNVERSIONED_FILES_WHILE_COMMIT = value;
rebuildList();
}
@Override
protected void setInitialSelection(@NotNull List<? extends ChangeList> changeLists,
@NotNull List<Object> changes,
@Nullable ChangeList initialListSelection) {
mySelectedChangeList = initialListSelection;
for (ChangeList list : changeLists) {
if (list instanceof LocalChangeList) {
if (initialListSelection == null && ContainerUtil.intersects(list.getChanges(), changes)) {
mySelectedChangeList = list;
}
}
}
if (mySelectedChangeList == null) {
mySelectedChangeList = ObjectUtils.chooseNotNull(findDefaultList(changeLists), ContainerUtil.getFirstItem(changeLists));
}
}
@Override
public void dispose() {
ChangeListManager.getInstance(myProject).removeChangeListListener(myChangeListListener);
}
public void addSelectedListChangeListener(@NotNull SelectedListChangeListener listener) {
myDispatcher.addListener(listener);
}
private void setSelectedList(@Nullable ChangeList list) {
mySelectedChangeList = list;
rebuildList();
myDispatcher.getMulticaster().selectedListChanged();
}
@Override
public void rebuildList() {
if (myInRebuildList) return;
try {
myInRebuildList = true;
updateListsInChooser();
super.rebuildList();
if (myRebuildListListener != null) {
myRebuildListListener.run();
}
} finally {
myInRebuildList = false;
}
}
@Override
@NotNull
public List<Change> getCurrentIncludedChanges() {
Collection<Object> includedObjects = myViewer.getIncludedChanges();
return mySelectedChangeList.getChanges().stream().filter(includedObjects::contains).collect(toList());
}
@NotNull
@Override
protected DefaultTreeModel buildTreeModel(@NotNull List<Object> objects,
@Nullable ChangeNodeDecorator changeNodeDecorator,
boolean showFlatten) {
ChangeListManagerImpl manager = ChangeListManagerImpl.getInstanceImpl(myProject);
TreeModelBuilder builder = new TreeModelBuilder(myProject, showFlatten);
List<VirtualFile> unversionedFiles = manager.getUnversionedFiles();
builder.setChanges(findChanges(objects), changeNodeDecorator);
if (isShowUnversioned()) {
builder.setUnversioned(unversionedFiles);
}
if (myUnversionedFilesEnabled) {
if (!isShowUnversioned() && !unversionedFiles.isEmpty()) {
myViewer.getEmptyText()
.setText("Unversioned files available. ")
.appendText("Show", SimpleTextAttributes.LINK_ATTRIBUTES, e -> setShowUnversioned(true));
}
else {
myViewer.getEmptyText().setText(capitalize(DiffBundle.message("diff.count.differences.status.text", 0)));
}
}
return builder.build();
}
@NotNull
@Override
protected List<Object> getSelectedObjects(@NotNull ChangesBrowserNode<?> node) {
List<Object> result = ContainerUtil.newArrayList();
result.addAll(node.getAllChangesUnder());
if (isShowUnversioned()) {
if (isUnderUnversioned(node)) {
result.addAll(node.getAllFilesUnder());
}
else if (node.isRoot()) {
ChangesBrowserUnversionedFilesNode unversionedFilesNode = findUnversionedFilesNode();
if (unversionedFilesNode != null) result.addAll(unversionedFilesNode.getAllFilesUnder());
}
}
return result;
}
@Nullable
@Override
protected Object getLeadSelectedObject(@NotNull ChangesBrowserNode<?> node) {
Object result = null;
Object userObject = node.getUserObject();
if (userObject instanceof Change || isShowUnversioned() && isUnderUnversioned(node) && userObject instanceof VirtualFile) {
result = userObject;
}
return result;
}
@NotNull
@Override
public List<Object> getCurrentDisplayedObjects() {
//noinspection unchecked
return (List)getCurrentDisplayedChanges();
}
@NotNull
@Override
public List<VirtualFile> getIncludedUnversionedFiles() {
return isShowUnversioned()
? ContainerUtil.findAll(myViewer.getIncludedChanges(), VirtualFile.class)
: Collections.emptyList();
}
@Override
public int getUnversionedFilesCount() {
int result = 0;
if (isShowUnversioned()) {
ChangesBrowserUnversionedFilesNode node = findUnversionedFilesNode();
if (node != null) {
result = node.getFileCount();
}
}
return result;
}
@Nullable
private ChangesBrowserUnversionedFilesNode findUnversionedFilesNode() {
//noinspection unchecked
Enumeration<ChangesBrowserNode> nodes = myViewer.getRoot().children();
return ContainerUtil.findInstance(ContainerUtil.iterate(nodes), ChangesBrowserUnversionedFilesNode.class);
}
@NotNull
@Override
public List<Change> getSelectedChanges() {
Set<Change> changes = ContainerUtil.newLinkedHashSet();
TreePath[] paths = myViewer.getSelectionPaths();
if (paths != null) {
for (TreePath path : paths) {
ChangesBrowserNode<?> node = (ChangesBrowserNode)path.getLastPathComponent();
changes.addAll(node.getAllChangesUnder());
}
}
return ContainerUtil.newArrayList(changes);
}
@NotNull
@Override
public List<Change> getAllChanges() {
return myViewer.getRoot().getAllChangesUnder();
}
@Override
protected void buildToolBar(@NotNull DefaultActionGroup toolBarGroup) {
super.buildToolBar(toolBarGroup);
toolBarGroup.add(new AnAction("Refresh Changes", null, AllIcons.Actions.Refresh) {
@Override
public void actionPerformed(AnActionEvent e) {
rebuildList();
}
});
if (myUnversionedFilesEnabled) {
toolBarGroup.add(new ShowHideUnversionedFilesAction());
toolBarGroup.add(UnversionedViewDialog.getUnversionedActionGroup());
}
else {
toolBarGroup.add(ActionManager.getInstance().getAction(IdeActions.MOVE_TO_ANOTHER_CHANGE_LIST));
}
UnversionedViewDialog.registerUnversionedActionsShortcuts(DataManager.getInstance().getDataContext(this), myViewer);
// We do not add "Delete" key shortcut for deleting unversioned files as this shortcut is already used to uncheck
// checkboxes in the tree.
myMoveActionWithCustomShortcut =
EmptyAction.registerWithShortcutSet(IdeActions.MOVE_TO_ANOTHER_CHANGE_LIST, CommonShortcuts.getMove(), myViewer);
RollbackDialogAction rollback = new RollbackDialogAction();
rollback.registerCustomShortcutSet(this, null);
toolBarGroup.add(rollback);
EditSourceForDialogAction editSourceAction = new EditSourceForDialogAction(this);
editSourceAction.registerCustomShortcutSet(CommonShortcuts.getEditSource(), this);
toolBarGroup.add(editSourceAction);
toolBarGroup.add(ActionManager.getInstance().getAction("Vcs.CheckinProjectToolbar"));
}
@Override
protected void afterDiffRefresh() {
rebuildList();
setDataIsDirty(false);
ApplicationManager.getApplication().invokeLater(
() -> IdeFocusManager.findInstance().requestFocus(myViewer.getPreferredFocusedComponent(), true));
}
@Override
protected List<AnAction> createDiffActions() {
List<AnAction> actions = super.createDiffActions();
actions.add(new MoveAction());
return actions;
}
private void updateListsInChooser() {
Runnable runnable = () -> myChangeListChooser.updateLists(ChangeListManager.getInstance(myProject).getChangeListsCopy());
if (SwingUtilities.isEventDispatchThread()) {
runnable.run();
}
else {
ApplicationManager.getApplication().invokeLater(runnable, ModalityState.stateForComponent(this));
}
}
@Nullable
private static ChangeList findDefaultList(@NotNull List<? extends ChangeList> lists) {
return ContainerUtil.find(lists, (Condition<ChangeList>)list -> list instanceof LocalChangeList && ((LocalChangeList)list).isDefault());
}
private class ChangeListChooser extends JPanel {
private final static int MAX_LEN = 35;
@NotNull private final ComboBox myChooser;
public ChangeListChooser() {
super(new BorderLayout(4, 2));
myChooser = new ComboBox();
//noinspection unchecked
myChooser.setRenderer(new ColoredListCellRendererWrapper<LocalChangeList>() {
@Override
protected void doCustomize(JList list, LocalChangeList value, int index, boolean selected, boolean hasFocus) {
if (value != null) {
String name = shortenTextWithEllipsis(value.getName().trim(), MAX_LEN, 0);
append(name, value.isDefault() ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
});
myChooser.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final LocalChangeList changeList = (LocalChangeList)myChooser.getSelectedItem();
setSelectedList(changeList);
myChooser.setToolTipText(changeList == null ? "" : (changeList.getName()));
}
}
});
myChooser.setEditable(false);
add(myChooser, BorderLayout.CENTER);
JLabel label = new JLabel(VcsBundle.message("commit.dialog.changelist.label"));
label.setLabelFor(myChooser);
add(label, BorderLayout.WEST);
}
public void updateLists(@NotNull List<? extends ChangeList> lists) {
//noinspection unchecked
myChooser.setModel(new DefaultComboBoxModel(lists.toArray()));
myChooser.setEnabled(lists.size() > 1);
if (lists.contains(mySelectedChangeList)) {
myChooser.setSelectedItem(mySelectedChangeList);
} else {
if (myChooser.getItemCount() > 0) {
myChooser.setSelectedIndex(0);
}
}
mySelectedChangeList = (ChangeList) myChooser.getSelectedItem();
}
}
private class MyChangeListListener extends ChangeListAdapter {
public void changeListAdded(ChangeList list) {
updateListsInChooser();
}
}
private class ShowHideUnversionedFilesAction extends ToggleAction {
private ShowHideUnversionedFilesAction() {
super("Show Unversioned Files", null, AllIcons.Vcs.ShowUnversionedFiles);
}
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);
e.getPresentation().setEnabledAndVisible(e.isFromActionToolbar());
}
@Override
public boolean isSelected(@NotNull AnActionEvent e) {
return myVcsConfiguration.SHOW_UNVERSIONED_FILES_WHILE_COMMIT;
}
@Override
public void setSelected(@NotNull AnActionEvent e, boolean state) {
setShowUnversioned(state);
}
}
private class MoveAction extends MoveChangesToAnotherListAction {
@Override
protected boolean isEnabled(@NotNull AnActionEvent e) {
Change change = e.getData(VcsDataKeys.CURRENT_CHANGE);
if (change == null) return false;
return super.isEnabled(e);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Change change = e.getRequiredData(VcsDataKeys.CURRENT_CHANGE);
askAndMove(myProject, Collections.singletonList(change), Collections.emptyList());
}
}
}
@@ -15,6 +15,8 @@
*/
package com.intellij.openapi.vcs.changes.ui;
import com.intellij.diff.chains.DiffRequestChain;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
import com.intellij.ide.DeleteProvider;
@@ -57,8 +59,9 @@ import java.util.List;
import static com.intellij.openapi.util.text.StringUtil.shortenTextWithEllipsis;
import static com.intellij.openapi.vcs.changes.ui.ChangesListView.UNVERSIONED_FILES_DATA_KEY;
public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implements Disposable {
public class MultipleLocalChangeListsBrowser extends CommitDialogChangesBrowser implements Disposable {
private final boolean myEnableUnversioned;
@Nullable private JComponent myBottomDiffComponent;
@NotNull private final ChangeListChooser myChangeListChooser;
@NotNull private final DeleteProvider myDeleteProvider = new VirtualFileDeleteProvider();
@@ -69,6 +72,8 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
@NotNull private LocalChangeList myChangeList;
@Nullable private Runnable mySelectedListChangeListener;
public MultipleLocalChangeListsBrowser(@NotNull Project project,
boolean showCheckboxes,
boolean highlightProblems,
@@ -80,17 +85,12 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
myChangeListChooser = new ChangeListChooser();
installChangeListListener();
init();
updateDisplayedChangeLists();
setSelectedChangeList(myChangeList);
}
@Override
public void dispose() {
}
private void installChangeListListener() {
ChangeListAdapter changeListListener = new MyChangeListListener();
ChangeListManager.getInstance(myProject).addChangeListListener(changeListListener);
@@ -148,6 +148,20 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
);
}
@Override
protected void updateDiffContext(@NotNull DiffRequestChain chain) {
super.updateDiffContext(chain);
chain.putUserData(DiffUserDataKeysEx.BOTTOM_PANEL, myBottomDiffComponent);
}
public void setBottomDiffComponent(@NotNull JComponent value) {
myBottomDiffComponent = value;
}
public void setSelectedListChangeListener(@Nullable Runnable runnable) {
mySelectedListChangeListener = runnable;
}
private boolean isShowUnversioned() {
return myEnableUnversioned && VcsConfiguration.getInstance(myProject).SHOW_UNVERSIONED_FILES_WHILE_COMMIT;
@@ -159,6 +173,7 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
}
@NotNull
@Override
public LocalChangeList getSelectedChangeList() {
return myChangeList;
}
@@ -167,6 +182,7 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
myChangeList = list;
myChangeListChooser.setToolTipText(list.getName());
updateDisplayedChanges();
if (mySelectedListChangeListener != null) mySelectedListChangeListener.run();
}
public void updateDisplayedChangeLists() {
@@ -232,6 +248,45 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
}
@NotNull
@Override
public List<Change> getDisplayedChanges() {
return myChanges;
}
@NotNull
@Override
public List<Change> getSelectedChanges() {
return VcsTreeModelData.selected(myViewer).userObjects(Change.class);
}
@NotNull
@Override
public List<Change> getIncludedChanges() {
return VcsTreeModelData.included(myViewer).userObjects(Change.class);
}
@NotNull
@Override
public List<VirtualFile> getDisplayedUnversionedFiles() {
return myUnversioned;
}
@NotNull
@Override
public List<VirtualFile> getSelectedUnversionedFiles() {
if (!isShowUnversioned()) return Collections.emptyList();
return VcsTreeModelData.selected(myViewer).userObjects(VirtualFile.class);
}
@NotNull
@Override
public List<VirtualFile> getIncludedUnversionedFiles() {
if (!isShowUnversioned()) return Collections.emptyList();
return VcsTreeModelData.included(myViewer).userObjects(VirtualFile.class);
}
private class ChangeListChooser extends JPanel {
private final static int MAX_NAME_LEN = 35;
@NotNull private final ComboBox<LocalChangeList> myChooser = new ComboBox<>();
@@ -248,6 +303,7 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
});
myChooser.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
LocalChangeList changeList = (LocalChangeList)myChooser.getSelectedItem();
@@ -313,12 +369,14 @@ public class MultipleLocalChangeListsBrowser extends ChangesBrowserBase implemen
super(VcsBundle.message("commit.dialog.include.action.name"));
}
@Override
public boolean isSelected(AnActionEvent e) {
Change change = e.getData(VcsDataKeys.CURRENT_CHANGE);
if (change == null) return false;
return myViewer.isIncluded(change);
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
Change change = e.getData(VcsDataKeys.CURRENT_CHANGE);
if (change == null) return;
@@ -51,6 +51,7 @@ import org.jetbrains.annotations.*;
import javax.swing.*;
import java.awt.*;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -61,7 +62,6 @@ import static com.intellij.util.containers.ContainerUtil.addIfNotNull;
import static com.intellij.util.containers.ContainerUtil.newHashSet;
import static com.intellij.util.ui.JBUI.Panels.simplePanel;
import static com.intellij.vcs.commit.CommitMessageInspectionProfile.getBodyRightMargin;
import static java.util.Collections.emptyList;
import static javax.swing.BorderFactory.createEmptyBorder;
public class CommitMessage extends JPanel implements Disposable, DataProvider, CommitMessageI {
@@ -69,7 +69,7 @@ public class CommitMessage extends JPanel implements Disposable, DataProvider, C
@NotNull private final EditorTextField myEditorField;
@Nullable private final TitledSeparator mySeparator;
@NotNull private List<ChangeList> myChangeLists = emptyList(); // guarded with WriteLock
@NotNull private List<ChangeList> myChangeLists = Collections.emptyList(); // guarded with WriteLock
public CommitMessage(@NotNull Project project) {
this(project, true, true, true);
@@ -210,6 +210,11 @@ public class CommitMessage extends JPanel implements Disposable, DataProvider, C
public void dispose() {
}
@CalledInAwt
public void setChangeList(@NotNull ChangeList value) {
setChangeLists(Collections.singletonList(value));
}
@CalledInAwt
public void setChangeLists(@NotNull List<ChangeList> value) {
WriteAction.run(() -> myChangeLists = value);