mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
support operations in DirDiff
This commit is contained in:
@@ -218,4 +218,38 @@ public abstract class DiffElement<T> implements Disposable {
|
||||
public DataProvider getDataProvider(Project project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines is it possible to perform such operations as copy or delete through Diff Panel
|
||||
*
|
||||
* @return <code>true</code> if copy, delete, etc operations are allowed,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean isOperationsEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies element to the container.
|
||||
*
|
||||
* @param container file directory or other container
|
||||
* @param relativePath
|
||||
* @return <code>true</code> if coping was completed successfully,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean copyTo(DiffElement<T> container, String relativePath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes element
|
||||
* @return <code>true</code> if deletion was completed successfully,
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean delete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.fileEditor.FileEditorProvider;
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -33,6 +34,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -175,4 +177,61 @@ public class VirtualFileDiffElement extends DiffElement<VirtualFile> {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOperationsEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyTo(DiffElement<VirtualFile> container, String relativePath) {
|
||||
try {
|
||||
final File src = new File(myFile.getPath());
|
||||
final File trg = new File(container.getValue().getPath() + relativePath + src.getName());
|
||||
FileUtil.copy(src, trg);
|
||||
//final VirtualFile targetRoot = container.getValue();
|
||||
//if (targetRoot != null && targetRoot.isDirectory()) {
|
||||
// VirtualFile target = getSeparator().equals(relativePath) ? targetRoot : targetRoot.findFileByRelativePath(relativePath);
|
||||
// final String path;
|
||||
// if (target == null) {
|
||||
// path = (targetRoot.getPath() + relativePath).replace('/', File.separatorChar);
|
||||
// new File(path).mkdirs();
|
||||
// target = targetRoot.findFileByRelativePath(removeSeparators(relativePath));
|
||||
// }
|
||||
//
|
||||
// if (target != null && target.isDirectory()) {
|
||||
// myFile.copy(this, target, myFile.getName());
|
||||
// }
|
||||
// else {
|
||||
// assert false : "Can't find " + container.getPath() + relativePath;
|
||||
// }
|
||||
//
|
||||
//}
|
||||
}
|
||||
catch (IOException e) {//
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String removeSeparators(String path) {
|
||||
final int start = path.startsWith(getSeparator()) ? getSeparator().length() : 0;
|
||||
final int end = path.endsWith(getSeparator()) ? path.length() - getSeparator().length() : path.length();
|
||||
return path.substring(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
try {
|
||||
myFile.delete(this);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
myFile.refresh(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ public class DTree {
|
||||
isContainer = container;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<DTree> getChildren() {
|
||||
init();
|
||||
if (myChildrenList == null) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import static com.intellij.openapi.diff.impl.dir.DirDiffOperation.*;
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class DirDiffElement {
|
||||
private final DTree myParent;
|
||||
private final DType myType;
|
||||
private final DiffElement mySource;
|
||||
private final long mySourceLength;
|
||||
@@ -37,7 +38,8 @@ public class DirDiffElement {
|
||||
private DirDiffOperation myOperation;
|
||||
private DirDiffOperation myDefaultOperation;
|
||||
|
||||
private DirDiffElement(@Nullable DiffElement source, @Nullable DiffElement target, DType type, String name) {
|
||||
private DirDiffElement(DTree parent, @Nullable DiffElement source, @Nullable DiffElement target, DType type, String name) {
|
||||
myParent = parent;
|
||||
myType = type;
|
||||
mySource = source;
|
||||
mySourceLength = source == null || source.isContainer() ? -1 : source.getSize();
|
||||
@@ -75,28 +77,28 @@ public class DirDiffElement {
|
||||
return timeStamp < 0 ? "" : DateFormatUtil.formatDateTime(timeStamp);
|
||||
}
|
||||
|
||||
public static DirDiffElement createChange(@NotNull DiffElement source, @NotNull DiffElement target) {
|
||||
return new DirDiffElement(source, target, DType.CHANGED, source.getName());
|
||||
public static DirDiffElement createChange(DTree parent, @NotNull DiffElement source, @NotNull DiffElement target) {
|
||||
return new DirDiffElement(parent, source, target, DType.CHANGED, source.getName());
|
||||
}
|
||||
|
||||
public static DirDiffElement createError(@Nullable DiffElement source, @Nullable DiffElement target) {
|
||||
return new DirDiffElement(source, target, DType.ERROR, source == null ? target.getName() : source.getName());
|
||||
public static DirDiffElement createError(DTree parent, @Nullable DiffElement source, @Nullable DiffElement target) {
|
||||
return new DirDiffElement(parent, source, target, DType.ERROR, source == null ? target.getName() : source.getName());
|
||||
}
|
||||
|
||||
public static DirDiffElement createSourceOnly(@NotNull DiffElement source) {
|
||||
return new DirDiffElement(source, null, DType.SOURCE, null);
|
||||
public static DirDiffElement createSourceOnly(DTree parent, @NotNull DiffElement source) {
|
||||
return new DirDiffElement(parent, source, null, DType.SOURCE, null);
|
||||
}
|
||||
|
||||
public static DirDiffElement createTargetOnly(@NotNull DiffElement target) {
|
||||
return new DirDiffElement(null, target, DType.TARGET, null);
|
||||
public static DirDiffElement createTargetOnly(DTree parent, @NotNull DiffElement target) {
|
||||
return new DirDiffElement(parent, null, target, DType.TARGET, null);
|
||||
}
|
||||
|
||||
public static DirDiffElement createDirElement(DiffElement src, DiffElement trg, String name) {
|
||||
return new DirDiffElement(src, trg, DType.SEPARATOR, name);
|
||||
public static DirDiffElement createDirElement(DTree parent, DiffElement src, DiffElement trg, String name) {
|
||||
return new DirDiffElement(parent, src, trg, DType.SEPARATOR, name);
|
||||
}
|
||||
|
||||
public static DirDiffElement createEqual(@NotNull DiffElement source, @NotNull DiffElement target) {
|
||||
return new DirDiffElement(source, target, DType.EQUAL, source.getName());
|
||||
public static DirDiffElement createEqual(DTree parent, @NotNull DiffElement source, @NotNull DiffElement target) {
|
||||
return new DirDiffElement(parent, source, target, DType.EQUAL, source.getName());
|
||||
}
|
||||
|
||||
public DType getType() {
|
||||
@@ -167,4 +169,8 @@ public class DirDiffElement {
|
||||
public Icon getIcon() {
|
||||
return mySource != null ? mySource.getIcon() : myTarget.getIcon();
|
||||
}
|
||||
|
||||
public DTree getParentNode() {
|
||||
return myParent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,25 +109,27 @@ public class DirDiffPanel implements Disposable {
|
||||
myDiffWindow.setTitle(myModel.getTitle());
|
||||
}
|
||||
});
|
||||
new AnAction("Change diff operation") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
changeOperationForSelectedRow();
|
||||
}
|
||||
}.registerCustomShortcutSet(CustomShortcutSet.fromString("SPACE"), myTable);
|
||||
myTable.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (myTable.getRowCount() > 0 && e.getClickCount() > 1) {
|
||||
final int row = myTable.rowAtPoint(e.getPoint());
|
||||
final int col = myTable.columnAtPoint(e.getPoint());
|
||||
if (model.isOperationsEnabled()) {
|
||||
new AnAction("Change diff operation") {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
changeOperationForSelectedRow();
|
||||
}
|
||||
}.registerCustomShortcutSet(CustomShortcutSet.fromString("SPACE"), myTable);
|
||||
myTable.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (myTable.getRowCount() > 0 && e.getClickCount() > 1) {
|
||||
final int row = myTable.rowAtPoint(e.getPoint());
|
||||
final int col = myTable.columnAtPoint(e.getPoint());
|
||||
|
||||
if (row != -1 && col == ((myTable.getColumnCount() - 1) / 2)) {
|
||||
changeOperationForSelectedRow();
|
||||
if (row != -1 && col == ((myTable.getColumnCount() - 1) / 2)) {
|
||||
changeOperationForSelectedRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
myTable.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.ide.diff.DiffElement;
|
||||
import com.intellij.ide.diff.DirDiffModel;
|
||||
import com.intellij.ide.diff.DirDiffSettings;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -133,6 +134,14 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
getSettings().setFilter(myPanel.getFilter());
|
||||
}
|
||||
|
||||
public boolean isOperationsEnabled() {
|
||||
return mySrc.isOperationsEnabled() && myTrg.isOperationsEnabled();
|
||||
}
|
||||
|
||||
public List<DirDiffElement> getElements() {
|
||||
return myElements;
|
||||
}
|
||||
|
||||
private static String prepareText(String text) {
|
||||
final int LEN = EMPTY_STRING.length();
|
||||
String right;
|
||||
@@ -165,15 +174,19 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
}
|
||||
|
||||
public void reloadModel() {
|
||||
//System.out.println("Start reloading");
|
||||
myUpdating.set(true);
|
||||
final JBLoadingPanel loadingPanel = getLoadingPanel();
|
||||
loadingPanel.startLoading();
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
//System.out.println("start updating on pooled thread");
|
||||
try {
|
||||
updater = new Updater(loadingPanel, 100);
|
||||
updater.start();
|
||||
myTree = new DTree(null, "", true);
|
||||
mySrc.refresh();
|
||||
myTrg.refresh();
|
||||
scan(mySrc, myTree, true);
|
||||
scan(myTrg, myTree, false);
|
||||
|
||||
@@ -184,6 +197,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
}
|
||||
catch (Exception e) {//
|
||||
}
|
||||
//System.out.println("end updating on pooled thread");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -193,6 +207,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
}
|
||||
|
||||
public void applySettings() {
|
||||
//System.out.println(StringUtil.getThrowableText(new Throwable()));
|
||||
if (! myUpdating.get()) myUpdating.set(true);
|
||||
final JBLoadingPanel loadingPanel = getLoadingPanel();
|
||||
if (!loadingPanel.isLoading()) {
|
||||
@@ -205,6 +220,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
final Application app = ApplicationManager.getApplication();
|
||||
app.executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
//System.out.println("start updating tree");
|
||||
myTree.updateVisibility(mySettings);
|
||||
final ArrayList<DirDiffElement> elements = new ArrayList<DirDiffElement>();
|
||||
fillElements(myTree, elements);
|
||||
@@ -227,6 +243,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
} else {
|
||||
app.invokeLater(uiThread);
|
||||
}
|
||||
//System.out.println("stop updating tree");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -240,24 +257,24 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
if (!child.isContainer()) {
|
||||
if (child.isVisible()) {
|
||||
if (!separatorAdded) {
|
||||
elements.add(DirDiffElement.createDirElement(tree.getSource(), tree.getTarget(), tree.getPath()));
|
||||
elements.add(DirDiffElement.createDirElement(tree, tree.getSource(), tree.getTarget(), tree.getPath()));
|
||||
separatorAdded = true;
|
||||
}
|
||||
switch (child.getType()) {
|
||||
case SOURCE:
|
||||
elements.add(DirDiffElement.createSourceOnly(child.getSource()));
|
||||
elements.add(DirDiffElement.createSourceOnly(tree, child.getSource()));
|
||||
break;
|
||||
case TARGET:
|
||||
elements.add(DirDiffElement.createTargetOnly(child.getTarget()));
|
||||
elements.add(DirDiffElement.createTargetOnly(tree, child.getTarget()));
|
||||
break;
|
||||
case CHANGED:
|
||||
elements.add(DirDiffElement.createChange(child.getSource(), child.getTarget()));
|
||||
elements.add(DirDiffElement.createChange(tree, child.getSource(), child.getTarget()));
|
||||
break;
|
||||
case EQUAL:
|
||||
elements.add(DirDiffElement.createEqual(child.getSource(), child.getTarget()));
|
||||
elements.add(DirDiffElement.createEqual(tree, child.getSource(), child.getTarget()));
|
||||
break;
|
||||
case ERROR:
|
||||
elements.add(DirDiffElement.createError(child.getSource(), child.getTarget()));
|
||||
elements.add(DirDiffElement.createError(tree, child.getSource(), child.getTarget()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -354,6 +371,17 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public List<DirDiffElement> getSelectedElements() {
|
||||
final int[] rows = myTable.getSelectedRows();
|
||||
final ArrayList<DirDiffElement> elements = new ArrayList<DirDiffElement>();
|
||||
for (int row : rows) {
|
||||
final DirDiffElement element = getElementAt(row);
|
||||
if (element == null || element.isSeparator()) continue;
|
||||
elements.add(element);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
@@ -427,6 +455,54 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode
|
||||
return mySettings;
|
||||
}
|
||||
|
||||
public void performCopyTo(DirDiffElement element) {
|
||||
final DiffElement source = element.getSource();
|
||||
if (source != null) {
|
||||
final String path = element.getParentNode().getPath();
|
||||
|
||||
final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass());
|
||||
try {
|
||||
source.copyTo(myTrg, path);
|
||||
} finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void performCopyFrom(DirDiffElement element) {
|
||||
final DiffElement target = element.getTarget();
|
||||
if (target != null) {
|
||||
final String path = element.getParentNode().getPath();
|
||||
final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass());
|
||||
try {
|
||||
target.copyTo(mySrc, path);
|
||||
} finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void performDelete(DirDiffElement element) {
|
||||
final DiffElement source = element.getSource();
|
||||
final DiffElement target = element.getTarget();
|
||||
final int index = myElements.indexOf(element);
|
||||
if (index != -1) {
|
||||
myElements.remove(index);
|
||||
fireTableRowsDeleted(index, index);
|
||||
}
|
||||
final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass());
|
||||
try {
|
||||
if (source != null) {
|
||||
source.delete();
|
||||
}
|
||||
if (target != null) {
|
||||
target.delete();
|
||||
}
|
||||
} finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
|
||||
class Updater extends Thread {
|
||||
private final JBLoadingPanel myLoadingPanel;
|
||||
private final int mySleep;
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class DirDiffAction extends ToggleAction implements DirDiffIcons
|
||||
@Override
|
||||
public final void setSelected(AnActionEvent e, boolean state) {
|
||||
updateState(state);
|
||||
if (this.getClass() == RefreshDirDiffAction.class) {
|
||||
if (isFullReload()) {
|
||||
getModel().reloadModel();
|
||||
} else {
|
||||
if (state) {
|
||||
@@ -54,6 +54,10 @@ public abstract class DirDiffAction extends ToggleAction implements DirDiffIcons
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isFullReload() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
super.update(e);
|
||||
|
||||
+3
-1
@@ -43,7 +43,9 @@ public class DirDiffToolbarActions extends ActionGroup {
|
||||
new EnableRight(model),
|
||||
Separator.getInstance(),
|
||||
new ChangeCompareModeGroup(model),
|
||||
Separator.getInstance()));
|
||||
Separator.getInstance(),
|
||||
new SynchronizeDiff(model, false),
|
||||
new SynchronizeDiff(model, true)));
|
||||
|
||||
for (AnAction action : model.getSettings().getExtraActions()) {
|
||||
actions.add(action);
|
||||
|
||||
+5
@@ -43,4 +43,9 @@ public class RefreshDirDiffAction extends DirDiffAction {
|
||||
public ShortcutSet getShortcut() {
|
||||
return CustomShortcutSet.fromString("F5");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isFullReload() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.diff.impl.dir.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CustomShortcutSet;
|
||||
import com.intellij.openapi.actionSystem.ShortcutSet;
|
||||
import com.intellij.openapi.diff.impl.dir.DirDiffElement;
|
||||
import com.intellij.openapi.diff.impl.dir.DirDiffOperation;
|
||||
import com.intellij.openapi.diff.impl.dir.DirDiffTableModel;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class SynchronizeDiff extends DirDiffAction {
|
||||
private boolean mySelectedOnly;
|
||||
|
||||
public SynchronizeDiff(DirDiffTableModel model, boolean selectedOnly) {
|
||||
super(model,
|
||||
selectedOnly ? "Synchronize Selected" : "Synchronize All",
|
||||
IconLoader.getIcon(selectedOnly ? "/actions/resume.png" : "/actions/refreshUsages.png"));
|
||||
mySelectedOnly = selectedOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateState(boolean state) {
|
||||
final List<DirDiffElement> elements = mySelectedOnly ? getModel().getSelectedElements() : getModel().getElements();
|
||||
for (DirDiffElement element : elements) {
|
||||
final DirDiffOperation operation = element.getOperation();
|
||||
if (operation == null) continue;
|
||||
switch (operation) {
|
||||
case COPY_TO:
|
||||
getModel().performCopyTo(element);
|
||||
break;
|
||||
case COPY_FROM:
|
||||
getModel().performCopyFrom(element);
|
||||
break;
|
||||
case MERGE:
|
||||
break;
|
||||
case EQUAL:
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
case DELETE:
|
||||
getModel().performDelete(element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortcutSet getShortcut() {
|
||||
return CustomShortcutSet.fromString(mySelectedOnly ? "ENTER" : SystemInfo.isMac ? "meta ENTER" : "control ENTER");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isFullReload() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user