mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
vcs: Refactored "ChangesTreeList" (and inheritors) - used tree component with flat model (corresponding model with no hierarchy is provided by "buildTreeModel()" implementations) instead of separate list component for displaying data in flat mode
This commit is contained in:
+2
-2
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.history.integration.ui.views;
|
||||
|
||||
import com.intellij.diff.DiffDialogHints;
|
||||
import com.intellij.history.core.LocalHistoryFacade;
|
||||
import com.intellij.history.core.revisions.Difference;
|
||||
import com.intellij.history.integration.IdeaGateway;
|
||||
@@ -25,7 +26,6 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.diff.DiffDialogHints;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.actions.diff.ShowDiffAction;
|
||||
import com.intellij.openapi.vcs.changes.actions.diff.ShowDiffContext;
|
||||
@@ -141,7 +141,7 @@ public class DirectoryHistoryDialog extends HistoryDialog<DirectoryHistoryDialog
|
||||
return new ChangesTreeList<Change>(myProject, Collections.<Change>emptyList(), false, false, null, null) {
|
||||
@Override
|
||||
protected DefaultTreeModel buildTreeModel(List<Change> cc, ChangeNodeDecorator changeNodeDecorator) {
|
||||
return new TreeModelBuilder(myProject, false).buildModel(cc, changeNodeDecorator);
|
||||
return new TreeModelBuilder(myProject, isShowFlatten()).buildModel(cc, changeNodeDecorator);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ public class MoveChangesDialog extends DialogWrapper {
|
||||
|
||||
@Override
|
||||
protected DefaultTreeModel buildTreeModel(List<Change> changes, ChangeNodeDecorator changeNodeDecorator) {
|
||||
TreeModelBuilder builder = new TreeModelBuilder(project, false);
|
||||
TreeModelBuilder builder = new TreeModelBuilder(project, isShowFlatten());
|
||||
return builder.buildModel(new ArrayList<ChangeList>(changeLists));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -507,7 +507,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
|
||||
@Override
|
||||
protected DefaultTreeModel buildTreeModel(List<AbstractFilePatchInProgress.PatchChange> changes,
|
||||
ChangeNodeDecorator changeNodeDecorator) {
|
||||
TreeModelBuilder builder = new TreeModelBuilder(myProject, false);
|
||||
TreeModelBuilder builder = new TreeModelBuilder(myProject, isShowFlatten());
|
||||
return builder.buildModel(ObjectsConvertor.convert(changes,
|
||||
new Convertor<AbstractFilePatchInProgress.PatchChange, Change>() {
|
||||
public Change convert(AbstractFilePatchInProgress.PatchChange o) {
|
||||
|
||||
@@ -90,7 +90,7 @@ public class ChangesBrowser extends JPanel implements TypeSafeDataProvider {
|
||||
|
||||
myViewer = new ChangesTreeList<Change>(myProject, changes, capableOfExcludingChanges, highlightProblems, inclusionListener, decorator) {
|
||||
protected DefaultTreeModel buildTreeModel(final List<Change> changes, ChangeNodeDecorator changeNodeDecorator) {
|
||||
TreeModelBuilder builder = new TreeModelBuilder(myProject, false);
|
||||
TreeModelBuilder builder = new TreeModelBuilder(myProject, isShowFlatten());
|
||||
return builder.buildModel(changes, changeNodeDecorator);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,10 @@ import com.intellij.ide.util.treeView.TreeState;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diff.DiffBundle;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.EmptyRunnable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -36,24 +34,19 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangesUtil;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.ui.treeStructure.actions.CollapseAllAction;
|
||||
import com.intellij.ui.treeStructure.actions.ExpandAllAction;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import com.intellij.util.ui.tree.WideSelectionTreeUI;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -61,13 +54,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
@@ -77,9 +67,7 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataProvider {
|
||||
private final Tree myTree;
|
||||
private final JBList myList;
|
||||
private final JScrollPane myTreeScrollPane;
|
||||
private final JScrollPane myListScrollPane;
|
||||
protected final Project myProject;
|
||||
private final boolean myShowCheckboxes;
|
||||
private final boolean myHighlightProblems;
|
||||
@@ -89,10 +77,10 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
@NotNull private Runnable myDoubleClickHandler = EmptyRunnable.getInstance();
|
||||
private boolean myAlwaysExpandList;
|
||||
|
||||
@NonNls private static final String TREE_CARD = "Tree";
|
||||
@NonNls private static final String LIST_CARD = "List";
|
||||
@NotNull private final TreeCellRenderer myNodeRenderer;
|
||||
@NotNull private final TreeCellRenderer myShowFlattenNodeRenderer;
|
||||
|
||||
@NonNls private static final String ROOT = "root";
|
||||
private final CardLayout myCards;
|
||||
|
||||
@NonNls private final static String FLATTEN_OPTION_KEY = "ChangesBrowser.SHOW_FLATTEN";
|
||||
|
||||
@@ -100,7 +88,6 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
@Nullable private ChangeNodeDecorator myChangeDecorator;
|
||||
private Runnable myGenericSelectionListener;
|
||||
@NotNull private final CopyProvider myTreeCopyProvider;
|
||||
@NotNull private final ChangesBrowserNodeListCopyProvider myListCopyProvider;
|
||||
|
||||
public ChangesTreeList(@NotNull final Project project,
|
||||
@NotNull Collection<T> initiallyIncluded,
|
||||
@@ -115,10 +102,10 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
myChangeDecorator = decorator;
|
||||
myIncludedChanges = new HashSet<T>(initiallyIncluded);
|
||||
myAlwaysExpandList = true;
|
||||
myNodeRenderer = new MyTreeCellRenderer(new ChangesBrowserNodeRenderer(myProject, false, myHighlightProblems));
|
||||
myShowFlattenNodeRenderer = new MyTreeCellRenderer(new ChangesBrowserNodeRenderer(myProject, true, myHighlightProblems));
|
||||
|
||||
myCards = new CardLayout();
|
||||
|
||||
setLayout(myCards);
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
final int checkboxWidth = new JCheckBox().getPreferredSize().width;
|
||||
myTree = new MyTree(project, checkboxWidth);
|
||||
@@ -126,7 +113,6 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
myTree.setRootVisible(false);
|
||||
myTree.setShowsRootHandles(true);
|
||||
myTree.setOpaque(false);
|
||||
myTree.setCellRenderer(new MyTreeCellRenderer());
|
||||
new TreeSpeedSearch(myTree, new Convertor<TreePath, String>() {
|
||||
@Override
|
||||
public String convert(TreePath o) {
|
||||
@@ -135,23 +121,7 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
});
|
||||
|
||||
myList = new JBList(new DefaultListModel());
|
||||
myList.setVisibleRowCount(10);
|
||||
|
||||
add(myListScrollPane = ScrollPaneFactory.createScrollPane(myList), LIST_CARD);
|
||||
add(myTreeScrollPane = ScrollPaneFactory.createScrollPane(myTree), TREE_CARD);
|
||||
|
||||
new ListSpeedSearch(myList) {
|
||||
@Override
|
||||
protected String getElementText(Object element) {
|
||||
if (element instanceof Change) {
|
||||
return ChangesUtil.getFilePath((Change)element).getName();
|
||||
}
|
||||
return super.getElementText(element);
|
||||
}
|
||||
};
|
||||
|
||||
myList.setCellRenderer(new MyListCellRenderer());
|
||||
add(myTreeScrollPane = ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER);
|
||||
|
||||
new MyToggleSelectionAction().registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)), this);
|
||||
if (myShowCheckboxes) {
|
||||
@@ -198,29 +168,6 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
});
|
||||
|
||||
new ClickListener() {
|
||||
@Override
|
||||
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
|
||||
if (!myList.isEnabled()) return false;
|
||||
final int idx = myList.locationToIndex(e.getPoint());
|
||||
if (idx >= 0) {
|
||||
if (myShowCheckboxes) {
|
||||
final Rectangle baseRect = myList.getCellBounds(idx, idx);
|
||||
baseRect.setSize(checkboxWidth, baseRect.height);
|
||||
if (baseRect.contains(e.getPoint())) {
|
||||
toggleSelection();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (clickCount == 2) {
|
||||
myDoubleClickHandler.run();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}.installOn(myList);
|
||||
|
||||
new DoubleClickListener() {
|
||||
@Override
|
||||
protected boolean onDoubleClick(MouseEvent e) {
|
||||
@@ -249,23 +196,14 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
setEmptyText(emptyText);
|
||||
|
||||
myTreeCopyProvider = new ChangesBrowserNodeCopyProvider(myTree);
|
||||
myListCopyProvider = new ChangesBrowserNodeListCopyProvider(myProject, myList);
|
||||
}
|
||||
|
||||
public void setEmptyText(@NotNull String emptyText) {
|
||||
myTree.getEmptyText().setText(emptyText);
|
||||
myList.getEmptyText().setText(emptyText);
|
||||
}
|
||||
|
||||
// generic, both for tree and list
|
||||
public void addSelectionListener(final Runnable runnable) {
|
||||
myGenericSelectionListener = runnable;
|
||||
myList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
myGenericSelectionListener.run();
|
||||
}
|
||||
});
|
||||
myTree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
@@ -283,12 +221,11 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
|
||||
public void installPopupHandler(ActionGroup group) {
|
||||
PopupHandler.installUnknownPopupHandler(myList, group, ActionManager.getInstance());
|
||||
PopupHandler.installUnknownPopupHandler(myTree, group, ActionManager.getInstance());
|
||||
}
|
||||
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myShowFlatten ? myList : myTree;
|
||||
return myTree;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -301,34 +238,21 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
|
||||
public void setScrollPaneBorder(Border border) {
|
||||
myListScrollPane.setBorder(border);
|
||||
myTreeScrollPane.setBorder(border);
|
||||
}
|
||||
|
||||
public void setShowFlatten(final boolean showFlatten) {
|
||||
final List<T> wasSelected = getSelectedChanges();
|
||||
myShowFlatten = showFlatten;
|
||||
myCards.show(this, myShowFlatten ? LIST_CARD : TREE_CARD);
|
||||
setChangesToDisplay(getChanges());
|
||||
myTree.setCellRenderer(myShowFlatten ? myShowFlattenNodeRenderer : myNodeRenderer);
|
||||
select(wasSelected);
|
||||
if (myList.hasFocus() || myTree.hasFocus()) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
requestFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void requestFocus() {
|
||||
if (myShowFlatten) {
|
||||
myList.requestFocus();
|
||||
}
|
||||
else {
|
||||
myTree.requestFocus();
|
||||
}
|
||||
myTree.requestFocus();
|
||||
}
|
||||
|
||||
public void setChangesToDisplay(final List<T> changes) {
|
||||
@@ -336,48 +260,15 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
|
||||
public void setChangesToDisplay(final List<T> changes, @Nullable final VirtualFile toSelect) {
|
||||
final boolean wasEmpty = myList.isEmpty();
|
||||
final List<T> sortedChanges = new ArrayList<T>(changes);
|
||||
Collections.sort(sortedChanges, new Comparator<T>() {
|
||||
@Override
|
||||
public int compare(final T o1, final T o2) {
|
||||
return TreeModelBuilder.getPathForObject(o1).getName().compareToIgnoreCase(TreeModelBuilder.getPathForObject(o2).getName());
|
||||
}
|
||||
});
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
final Set<Object> wasSelected = new THashSet<Object>(Arrays.asList(myList.getSelectedValues()));
|
||||
//noinspection unchecked
|
||||
myList.setModel(new AbstractListModel() {
|
||||
@Override
|
||||
public int getSize() {
|
||||
return sortedChanges.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(int index) {
|
||||
return sortedChanges.get(index);
|
||||
}
|
||||
});
|
||||
|
||||
final DefaultTreeModel model = buildTreeModel(changes, myChangeDecorator);
|
||||
TreeState state = null;
|
||||
if (! myAlwaysExpandList && ! wasEmpty) {
|
||||
state = TreeState.createOn(myTree, (DefaultMutableTreeNode) myTree.getModel().getRoot());
|
||||
if (!myAlwaysExpandList) {
|
||||
state = TreeState.createOn(myTree, (DefaultMutableTreeNode)myTree.getModel().getRoot());
|
||||
}
|
||||
myTree.setModel(model);
|
||||
if (! myAlwaysExpandList && ! wasEmpty) {
|
||||
if (!myAlwaysExpandList) {
|
||||
//noinspection ConstantConditions
|
||||
state.applyTo(myTree, (DefaultMutableTreeNode) myTree.getModel().getRoot());
|
||||
|
||||
final TIntArrayList indices = new TIntArrayList();
|
||||
for (int i = 0; i < sortedChanges.size(); i++) {
|
||||
T t = sortedChanges.get(i);
|
||||
if (wasSelected.contains(t)) {
|
||||
indices.add(i);
|
||||
}
|
||||
}
|
||||
myList.setSelectedIndices(indices.toNativeArray());
|
||||
state.applyTo(myTree, (DefaultMutableTreeNode)myTree.getModel().getRoot());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -387,19 +278,10 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
if (myProject.isDisposed()) return;
|
||||
TreeUtil.expandAll(myTree);
|
||||
|
||||
int selectedListRow = 0;
|
||||
int selectedTreeRow = -1;
|
||||
|
||||
if (myShowCheckboxes) {
|
||||
if (myIncludedChanges.size() > 0) {
|
||||
for (int i = 0; i < sortedChanges.size(); i++) {
|
||||
T t = sortedChanges.get(i);
|
||||
if (myIncludedChanges.contains(t)) {
|
||||
selectedListRow = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ChangesBrowserNode root = (ChangesBrowserNode)model.getRoot();
|
||||
Enumeration enumeration = root.depthFirstEnumeration();
|
||||
|
||||
@@ -429,17 +311,10 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
if (rowInTree > -1) {
|
||||
selectedTreeRow = rowInTree;
|
||||
}
|
||||
int rowInList = findRowContainingFile(myList.getModel(), toSelect);
|
||||
if (rowInList > -1) {
|
||||
selectedListRow = rowInList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changes.size() > 0) {
|
||||
myList.setSelectedIndex(selectedListRow);
|
||||
myList.ensureIndexIsVisible(selectedListRow);
|
||||
|
||||
if (changes.size() > 0) {
|
||||
if (selectedTreeRow >= 0) {
|
||||
myTree.setSelectionRow(selectedTreeRow);
|
||||
}
|
||||
@@ -454,16 +329,6 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
}
|
||||
|
||||
private static int findRowContainingFile(@NotNull ListModel listModel, @NotNull final VirtualFile toSelect) {
|
||||
for (int i = 0; i < listModel.getSize(); i++) {
|
||||
Object item = listModel.getElementAt(i);
|
||||
if (item instanceof Change && matches((Change)item, toSelect)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int findRowContainingFile(@NotNull TreeNode root, @NotNull final VirtualFile toSelect) {
|
||||
final Ref<Integer> row = Ref.create(-1);
|
||||
TreeUtil.traverse(root, new TreeUtil.Traverse() {
|
||||
@@ -504,57 +369,34 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
|
||||
public List<T> getChanges() {
|
||||
if (myShowFlatten) {
|
||||
ListModel m = myList.getModel();
|
||||
int size = m.getSize();
|
||||
List<T> result = new ArrayList<T>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
//noinspection unchecked
|
||||
result.add((T)m.getElementAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
final LinkedHashSet<T> result = new LinkedHashSet<T>();
|
||||
TreeUtil.traverseDepth((ChangesBrowserNode)myTree.getModel().getRoot(), new TreeUtil.Traverse() {
|
||||
@Override
|
||||
public boolean accept(Object node) {
|
||||
ChangesBrowserNode changeNode = (ChangesBrowserNode)node;
|
||||
if (changeNode.isLeaf()) {
|
||||
//noinspection unchecked
|
||||
result.addAll(changeNode.getAllChangesUnder());
|
||||
}
|
||||
return true;
|
||||
final LinkedHashSet<T> result = new LinkedHashSet<T>();
|
||||
TreeUtil.traverseDepth((ChangesBrowserNode)myTree.getModel().getRoot(), new TreeUtil.Traverse() {
|
||||
@Override
|
||||
public boolean accept(Object node) {
|
||||
ChangesBrowserNode changeNode = (ChangesBrowserNode)node;
|
||||
if (changeNode.isLeaf()) {
|
||||
//noinspection unchecked
|
||||
result.addAll(changeNode.getAllChangesUnder());
|
||||
}
|
||||
});
|
||||
return new ArrayList<T>(result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return new ArrayList<T>(result);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<T> getSelectedChanges() {
|
||||
if (myShowFlatten) {
|
||||
final List<T> changes = new ArrayList<T>();
|
||||
//noinspection deprecation
|
||||
for (Object anO : myList.getSelectedValues()) {
|
||||
//noinspection unchecked
|
||||
changes.add((T)anO);
|
||||
}
|
||||
return changes;
|
||||
final TreePath[] paths = myTree.getSelectionPaths();
|
||||
if (paths == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
final TreePath[] paths = myTree.getSelectionPaths();
|
||||
if (paths == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
LinkedHashSet<T> changes = ContainerUtil.newLinkedHashSet();
|
||||
for (TreePath path : paths) {
|
||||
//noinspection unchecked
|
||||
changes.addAll(getSelectedObjects((ChangesBrowserNode)path.getLastPathComponent()));
|
||||
}
|
||||
return ContainerUtil.newArrayList(changes);
|
||||
LinkedHashSet<T> changes = ContainerUtil.newLinkedHashSet();
|
||||
for (TreePath path : paths) {
|
||||
//noinspection unchecked
|
||||
changes.addAll(getSelectedObjects((ChangesBrowserNode)path.getLastPathComponent()));
|
||||
}
|
||||
return ContainerUtil.newArrayList(changes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,36 +414,19 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
|
||||
@Nullable
|
||||
public T getHighestLeadSelection() {
|
||||
if (myShowFlatten) {
|
||||
final int index = myList.getLeadSelectionIndex();
|
||||
ListModel listModel = myList.getModel();
|
||||
if (index < 0 || index >= listModel.getSize()) return null;
|
||||
//noinspection unchecked
|
||||
return (T)listModel.getElementAt(index);
|
||||
}
|
||||
else {
|
||||
final TreePath path = myTree.getSelectionPath();
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
//noinspection unchecked
|
||||
return getLeadSelectedObject((ChangesBrowserNode<T>)path.getLastPathComponent());
|
||||
final TreePath path = myTree.getSelectionPath();
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
//noinspection unchecked
|
||||
return getLeadSelectedObject((ChangesBrowserNode<T>)path.getLastPathComponent());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T getLeadSelection() {
|
||||
if (myShowFlatten) {
|
||||
final int index = myList.getLeadSelectionIndex();
|
||||
ListModel listModel = myList.getModel();
|
||||
//noinspection unchecked
|
||||
return index < 0 || index >= listModel.getSize() ? null : (T)listModel.getElementAt(index);
|
||||
}
|
||||
else {
|
||||
final TreePath path = myTree.getSelectionPath();
|
||||
//noinspection unchecked
|
||||
return path == null ? null : ContainerUtil.getFirstItem(getSelectedObjects(((ChangesBrowserNode<T>)path.getLastPathComponent())));
|
||||
}
|
||||
final TreePath path = myTree.getSelectionPath();
|
||||
//noinspection unchecked
|
||||
return path == null ? null : ContainerUtil.getFirstItem(getSelectedObjects(((ChangesBrowserNode<T>)path.getLastPathComponent())));
|
||||
}
|
||||
|
||||
private void notifyInclusionListener() {
|
||||
@@ -615,35 +440,30 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
myIncludedChanges.clear();
|
||||
myIncludedChanges.addAll(changes);
|
||||
myTree.repaint();
|
||||
myList.repaint();
|
||||
}
|
||||
|
||||
public void includeChange(final T change) {
|
||||
myIncludedChanges.add(change);
|
||||
notifyInclusionListener();
|
||||
myTree.repaint();
|
||||
myList.repaint();
|
||||
}
|
||||
|
||||
public void includeChanges(final Collection<T> changes) {
|
||||
myIncludedChanges.addAll(changes);
|
||||
notifyInclusionListener();
|
||||
myTree.repaint();
|
||||
myList.repaint();
|
||||
}
|
||||
|
||||
public void excludeChange(final T change) {
|
||||
myIncludedChanges.remove(change);
|
||||
notifyInclusionListener();
|
||||
myTree.repaint();
|
||||
myList.repaint();
|
||||
}
|
||||
|
||||
public void excludeChanges(final Collection<T> changes) {
|
||||
myIncludedChanges.removeAll(changes);
|
||||
notifyInclusionListener();
|
||||
myTree.repaint();
|
||||
myList.repaint();
|
||||
}
|
||||
|
||||
private void toggleChanges(final Collection<T> changes) {
|
||||
@@ -703,7 +523,6 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
}
|
||||
|
||||
public void setSelectionMode(@JdkConstants.ListSelectionMode int mode) {
|
||||
myList.setSelectionMode(mode);
|
||||
myTree.getSelectionModel().setSelectionMode(getTreeSelectionModeFromListSelectionMode(mode));
|
||||
}
|
||||
|
||||
@@ -722,10 +541,10 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
private final JCheckBox myCheckBox;
|
||||
|
||||
|
||||
public MyTreeCellRenderer() {
|
||||
public MyTreeCellRenderer(@NotNull ChangesBrowserNodeRenderer textRenderer) {
|
||||
super(new BorderLayout());
|
||||
myCheckBox = new JCheckBox();
|
||||
myTextRenderer = new ChangesBrowserNodeRenderer(myProject, false, myHighlightProblems);
|
||||
myTextRenderer = textRenderer;
|
||||
|
||||
if (myShowCheckboxes) {
|
||||
add(myCheckBox, BorderLayout.WEST);
|
||||
@@ -790,89 +609,6 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
return CheckboxTree.NodeState.CLEAR;
|
||||
}
|
||||
|
||||
private class MyListCellRenderer extends JPanel implements ListCellRenderer {
|
||||
private final ColoredListCellRenderer myTextRenderer;
|
||||
public final JCheckBox myCheckbox;
|
||||
|
||||
public MyListCellRenderer() {
|
||||
super(new BorderLayout());
|
||||
myCheckbox = new JCheckBox();
|
||||
myTextRenderer = new VirtualFileListCellRenderer(myProject) {
|
||||
@Override
|
||||
protected void putParentPath(Object value, FilePath path, FilePath self) {
|
||||
super.putParentPath(value, path, self);
|
||||
final boolean applyChangeDecorator = (value instanceof Change) && myChangeDecorator != null;
|
||||
if (applyChangeDecorator) {
|
||||
myChangeDecorator.decorate((Change) value, this, isShowFlatten());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putParentPathImpl(Object value, String parentPath, FilePath self) {
|
||||
final boolean applyChangeDecorator = (value instanceof Change) && myChangeDecorator != null;
|
||||
List<Pair<String,ChangeNodeDecorator.Stress>> parts = null;
|
||||
if (applyChangeDecorator) {
|
||||
parts = myChangeDecorator.stressPartsOfFileName((Change)value, parentPath);
|
||||
}
|
||||
if (parts == null) {
|
||||
super.putParentPathImpl(value, parentPath, self);
|
||||
return;
|
||||
}
|
||||
|
||||
for (Pair<String, ChangeNodeDecorator.Stress> part : parts) {
|
||||
append(part.getFirst(), part.getSecond().derive(SimpleTextAttributes.GRAYED_ATTRIBUTES));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list,
|
||||
Object value,
|
||||
int index,
|
||||
boolean selected,
|
||||
boolean hasFocus) {
|
||||
final Component component = super.getListCellRendererComponent(list, value, index, selected, hasFocus);
|
||||
final FileColorManager colorManager = FileColorManager.getInstance(myProject);
|
||||
if (!selected) {
|
||||
if (Registry.is("file.colors.in.commit.dialog") && colorManager.isEnabled() && colorManager.isEnabledForProjectView()) {
|
||||
if (value instanceof Change) {
|
||||
final VirtualFile file = ((Change)value).getVirtualFile();
|
||||
if (file != null) {
|
||||
final Color color = colorManager.getFileColor(file);
|
||||
if (color != null) {
|
||||
component.setBackground(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return component;
|
||||
}
|
||||
};
|
||||
|
||||
myCheckbox.setBackground(null);
|
||||
setBackground(null);
|
||||
|
||||
if (myShowCheckboxes) {
|
||||
add(myCheckbox, BorderLayout.WEST);
|
||||
}
|
||||
add(myTextRenderer, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
myTextRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (myShowCheckboxes) {
|
||||
//noinspection SuspiciousMethodCalls
|
||||
myCheckbox.setSelected(myIncludedChanges.contains(value));
|
||||
myCheckbox.setEnabled(list.isEnabled());
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
return myTextRenderer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyToggleSelectionAction extends AnAction implements DumbAware {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
@@ -916,30 +652,6 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
});
|
||||
myTree.setSelectionPaths(treeSelection.toArray(new TreePath[treeSelection.size()]));
|
||||
if (treeSelection.size() == 1) myTree.scrollPathToVisible(treeSelection.get(0));
|
||||
|
||||
// list
|
||||
final ListModel model = myList.getModel();
|
||||
final int size = model.getSize();
|
||||
final List<Integer> listSelection = new ArrayList<Integer>(changes.size());
|
||||
for (int i = 0; i < size; i++) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final T el = (T) model.getElementAt(i);
|
||||
if (changes.contains(el)) {
|
||||
listSelection.add(i);
|
||||
}
|
||||
}
|
||||
myList.setSelectedIndices(int2int(listSelection));
|
||||
if (listSelection.size() == 1) myList.ensureIndexIsVisible(listSelection.get(0));
|
||||
}
|
||||
|
||||
private static int[] int2int(List<Integer> treeSelection) {
|
||||
final int[] toPass = new int[treeSelection.size()];
|
||||
int i = 0;
|
||||
for (Integer integer : treeSelection) {
|
||||
toPass[i] = integer;
|
||||
++ i;
|
||||
}
|
||||
return toPass;
|
||||
}
|
||||
|
||||
public void setAlwaysExpandList(boolean alwaysExpandList) {
|
||||
@@ -948,13 +660,12 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
|
||||
public void setPaintBusy(final boolean value) {
|
||||
myTree.setPaintBusy(value);
|
||||
myList.setPaintBusy(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calcData(DataKey key, DataSink sink) {
|
||||
if (PlatformDataKeys.COPY_PROVIDER == key) {
|
||||
sink.put(PlatformDataKeys.COPY_PROVIDER, myShowFlatten ? myListCopyProvider : myTreeCopyProvider);
|
||||
sink.put(PlatformDataKeys.COPY_PROVIDER, myTreeCopyProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1033,36 +744,4 @@ public abstract class ChangesTreeList<T> extends JPanel implements TypeSafeDataP
|
||||
ChangesTreeList.this.calcData(key, sink);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ChangesBrowserNodeListCopyProvider implements CopyProvider {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final JList myList;
|
||||
|
||||
ChangesBrowserNodeListCopyProvider(@NotNull Project project, @NotNull JList list) {
|
||||
myProject = project;
|
||||
myList = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performCopy(@NotNull DataContext dataContext) {
|
||||
CopyPasteManager.getInstance().setContents(new StringSelection(StringUtil.join(myList.getSelectedValues(),
|
||||
new Function<Object, String>() {
|
||||
@Override
|
||||
public String fun(Object object) {
|
||||
return ChangesBrowserNode.create(myProject, object).getTextPresentation();
|
||||
}
|
||||
}, "\n")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCopyEnabled(@NotNull DataContext dataContext) {
|
||||
return !myList.isSelectionEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCopyVisible(@NotNull DataContext dataContext) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class FilePathChangesTreeList extends ChangesTreeList<FilePath> {
|
||||
}
|
||||
|
||||
protected DefaultTreeModel buildTreeModel(final List<FilePath> changes, ChangeNodeDecorator changeNodeDecorator) {
|
||||
return new TreeModelBuilder(myProject, false).buildModelFromFilePaths(changes);
|
||||
return new TreeModelBuilder(myProject, isShowFlatten()).buildModelFromFilePaths(changes);
|
||||
}
|
||||
|
||||
protected List<FilePath> getSelectedObjects(final ChangesBrowserNode<FilePath> node) {
|
||||
|
||||
@@ -116,7 +116,7 @@ public class SelectFilesDialog extends AbstractSelectFilesDialog<VirtualFile> {
|
||||
}
|
||||
|
||||
protected DefaultTreeModel buildTreeModel(final List<VirtualFile> changes, ChangeNodeDecorator changeNodeDecorator) {
|
||||
return new TreeModelBuilder(myProject, false).buildModelFromFiles(changes);
|
||||
return new TreeModelBuilder(myProject, isShowFlatten()).buildModelFromFiles(changes);
|
||||
}
|
||||
|
||||
protected List<VirtualFile> getSelectedObjects(final ChangesBrowserNode node) {
|
||||
|
||||
Reference in New Issue
Block a user