diff --git a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java index a449772ea9da..9b67b5603a78 100644 --- a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java +++ b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java @@ -150,6 +150,7 @@ public class NullityInferrer { final PsiModifierListOwner element = pointer.getElement(); if (element != null) { if (shouldIgnore(element)) continue; + if (element instanceof PsiField && ((PsiField)element).hasInitializer() && element.hasModifierProperty(PsiModifier.FINAL)) continue; new AddAnnotationFix(manager.getDefaultNotNull(), element, manager.getDefaultNullable()).invoke(project, null, element.getContainingFile()); } diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java b/java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java index a262cbebf9da..90741ae88c95 100644 --- a/java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java +++ b/java/java-tests/testData/codeInsight/nullityinferrer/afterFieldsAssignment.java @@ -32,6 +32,12 @@ class Test { @Nullable final String myFoo10; + final String myFoo11 = ""; + @NotNull + final String myFoo12; + @Nullable + final String myFoo13 = null; + /** * {@link #myFoo6} */ @@ -42,6 +48,7 @@ class Test { myFoo8 = paramNullable; myFoo9 = simpleParam; myFoo10 = foo10(false); + myFoo12 = ""; } @Nullable diff --git a/java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java b/java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java index d08d088af2f2..a7772aff997b 100644 --- a/java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java +++ b/java/java-tests/testData/codeInsight/nullityinferrer/beforeFieldsAssignment.java @@ -23,6 +23,10 @@ class Test { final String myFoo9; final String myFoo10; + final String myFoo11 = ""; + final String myFoo12; + final String myFoo13 = null; + /** * {@link #myFoo6} */ @@ -33,6 +37,7 @@ class Test { myFoo8 = paramNullable; myFoo9 = simpleParam; myFoo10 = foo10(false); + myFoo12 = ""; } String foo10(boolean flag) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/CommonInspectionToolWrapper.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/CommonInspectionToolWrapper.java new file mode 100644 index 000000000000..e2ed38048553 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/CommonInspectionToolWrapper.java @@ -0,0 +1,105 @@ +/* + * Copyright 2000-2012 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.codeInspection.ex; + +import com.intellij.analysis.AnalysisScope; +import com.intellij.codeInspection.GlobalInspectionContext; +import com.intellij.codeInspection.InspectionEP; +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.reference.RefEntity; +import com.intellij.codeInspection.ui.InspectionNode; +import com.intellij.codeInspection.ui.InspectionTreeNode; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Set; + +public class CommonInspectionToolWrapper extends InspectionToolWrapper { + public CommonInspectionToolWrapper(InspectionEP ep) { + super(ep); + } + + CommonInspectionToolWrapper(InspectionTool tool) { + super(tool); + } + + CommonInspectionToolWrapper(InspectionEP ep, InspectionTool tool) { + super(ep, tool); + } + + @Override + public CommonInspectionToolWrapper createCopy(InspectionToolWrapper from) { + return new CommonInspectionToolWrapper(from.myEP, from.myTool); + } + + @Override + public void runInspection(@NotNull AnalysisScope scope, @NotNull InspectionManager manager) { + getTool().runInspection(scope, manager); + } + + @Override + public void initialize(@NotNull GlobalInspectionContextImpl context) { + getTool().initialize(context); + } + + @NotNull + @Override + public JobDescriptor[] getJobDescriptors(GlobalInspectionContext globalInspectionContext) { + return getTool().getJobDescriptors(globalInspectionContext); + } + + @Override + public boolean isGraphNeeded() { + return getTool().isGraphNeeded(); + } + + @Override + public void updateContent() { + getTool().updateContent(); + } + + @Override + public boolean hasReportedProblems() { + return getTool().hasReportedProblems(); + } + + @Override + public Map> getContent() { + return getTool().getContent(); + } + + @Override + public GlobalInspectionContextImpl getContext() { + return getTool().getContext(); + } + + @Override + public HTMLComposerImpl getComposer() { + return getTool().getComposer(); + } + + @Override + public QuickFixAction[] getQuickFixes(RefEntity[] refElements) { + return getTool().getQuickFixes(refElements); + } + + @Override + public InspectionNode createToolNode(InspectionRVContentProvider provider, + InspectionTreeNode parentNode, + boolean showStructure) { + return getTool().createToolNode(provider, parentNode, showStructure); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index 34de456f8594..c578b5a0461e 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -357,7 +357,14 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G for (ScopeToolState state : tools.getTools()) { final NamedScope namedScope = state.getScope(element.getProject()); if (namedScope == null || namedScope.getValue().contains(element.getContainingFile(), getCurrentProfile().getProfileManager().getScopesManager())) { - return state.isEnabled() && state.getTool() == tool; + if (state.isEnabled()) { + final InspectionProfileEntry entry = state.getTool(); + if (entry instanceof InspectionToolWrapper && ((InspectionToolWrapper)entry).getTool() == tool) return true; + if (entry == tool) { + return true; + } + } + return false; } } } @@ -484,7 +491,7 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G final InspectionTool tool = (InspectionTool)state.getTool(); try { if (tool.isGraphNeeded()) { - ((RefManagerImpl)tool.getRefManager()).findAllDeclarations(); + ((RefManagerImpl)getRefManager()).findAllDeclarations(); } tool.runInspection(scope, manager); if (tool.queryExternalUsagesRequests(manager)) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java index f24e1e336539..bc3f13ba3643 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java @@ -86,7 +86,7 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider if (tool.isOldProblemsIncluded()) { final Map oldProblems = - tool instanceof DescriptorProviderInspection ? ((DescriptorProviderInspection)tool) + tool instanceof DescriptorProviderInspection && !(tool instanceof CommonInspectionToolWrapper)? ((DescriptorProviderInspection)tool) .getOldProblemElements() : null; computeContainer = new Function>() { public UserObjectContainer fun(final RefEntity refElement) { @@ -111,7 +111,7 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider final RefElementContainer refElementDescriptor = ((RefElementContainer)container); final RefEntity refElement = refElementDescriptor.getUserObject(); if (context.getUIOptions().SHOW_ONLY_DIFF && tool.getElementStatus(refElement) == FileStatus.NOT_CHANGED) return; - if (tool instanceof DescriptorProviderInspection) { + if (tool instanceof DescriptorProviderInspection && !(tool instanceof CommonInspectionToolWrapper)) { final DescriptorProviderInspection descriptorProviderInspection = (DescriptorProviderInspection)tool; final CommonProblemDescriptor[] problems = refElementDescriptor.getProblemDescriptors(); if (problems != null) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java index 3cf54d5b3cee..4fb225bc54db 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java @@ -18,7 +18,6 @@ package com.intellij.codeInspection.ex; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import com.intellij.analysis.AnalysisScope; import com.intellij.codeInspection.*; import com.intellij.ide.ui.search.SearchableOptionsRegistrar; import com.intellij.notification.Notification; @@ -315,39 +314,4 @@ public class InspectionToolRegistrar { } }); } - - private static class CommonInspectionToolWrapper extends InspectionToolWrapper { - public CommonInspectionToolWrapper(InspectionEP ep) { - super(ep); - } - - private CommonInspectionToolWrapper(InspectionTool tool) { - super(tool); - } - - private CommonInspectionToolWrapper(InspectionEP ep, InspectionTool tool) { - super(ep, tool); - } - - @Override - public CommonInspectionToolWrapper createCopy(InspectionToolWrapper from) { - return new CommonInspectionToolWrapper(from.myEP, from.myTool); - } - - @Override - public void runInspection(@NotNull AnalysisScope scope, @NotNull InspectionManager manager) { - getTool().runInspection(scope, manager); - } - - @Override - public void initialize(@NotNull GlobalInspectionContextImpl context) { - getTool().initialize(context); - } - - @NotNull - @Override - public JobDescriptor[] getJobDescriptors(GlobalInspectionContext globalInspectionContext) { - return getTool().getJobDescriptors(globalInspectionContext); - } - } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java index d0915011fe17..456ca3a62f1e 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java @@ -77,7 +77,8 @@ public class QuickFixAction extends AnAction { } final InspectionTree tree = view.getTree(); - if (!view.isSingleToolInSelection() || tree.getSelectedTool() != myTool) { + final InspectionTool tool = tree.getSelectedTool(); + if (!view.isSingleToolInSelection() || (tool instanceof InspectionToolWrapper && ((InspectionToolWrapper)tool).getTool() != myTool)) { e.getPresentation().setVisible(false); e.getPresentation().setEnabled(false); return; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java index 94df12c95c73..8c2d5d2dc232 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java @@ -22,10 +22,7 @@ package com.intellij.codeInspection.offlineViewer; import com.intellij.codeInspection.CommonProblemDescriptor; import com.intellij.codeInspection.QuickFix; -import com.intellij.codeInspection.ex.DescriptorProviderInspection; -import com.intellij.codeInspection.ex.InspectionRVContentProvider; -import com.intellij.codeInspection.ex.InspectionTool; -import com.intellij.codeInspection.ex.QuickFixAction; +import com.intellij.codeInspection.ex.*; import com.intellij.codeInspection.offline.OfflineProblemDescriptor; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefEntity; @@ -96,7 +93,7 @@ public class OfflineInspectionRVContentProvider extends InspectionRVContentProvi final RefEntity[] selectedRefElements = selectedElements.toArray(new RefEntity[selectedElements.size()]); - if (tool instanceof DescriptorProviderInspection) { + if (tool instanceof DescriptorProviderInspection && !(tool instanceof CommonInspectionToolWrapper)) { return ((DescriptorProviderInspection)tool).extractActiveFixes(selectedRefElements, actions); } @@ -171,7 +168,7 @@ public class OfflineInspectionRVContentProvider extends InspectionRVContentProvi final InspectionPackageNode packageNode, final boolean canPackageRepeat) { final RefElementNode elemNode = addNodeToParent(container, tool, packageNode); - if (tool instanceof DescriptorProviderInspection) { + if (tool instanceof DescriptorProviderInspection && !(tool instanceof CommonInspectionToolWrapper)) { elemNode.add(new OfflineProblemDescriptorNode(((OfflineProblemDescriptorContainer)container).getUserObject(), (DescriptorProviderInspection)tool)); } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java index ad47d61bd1c6..9515d2bd03fb 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java @@ -116,7 +116,7 @@ class Browser extends JPanel { private void showPageFromHistory(RefEntity newEntity) { InspectionTool tool = getTool(newEntity); try { - if (tool instanceof DescriptorProviderInspection) { + if (tool instanceof DescriptorProviderInspection && !(tool instanceof CommonInspectionToolWrapper)) { showEmpty(); } else { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java index 46096eda2a18..dafe722fef70 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java @@ -25,6 +25,7 @@ package com.intellij.codeInspection.ui; import com.intellij.codeInspection.CommonProblemDescriptor; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ex.CommonInspectionToolWrapper; import com.intellij.codeInspection.ex.DescriptorProviderInspection; import com.intellij.codeInspection.ex.InspectionTool; import com.intellij.codeInspection.reference.RefElement; @@ -163,7 +164,7 @@ public class InspectionTree extends Tree { public CommonProblemDescriptor[] getSelectedDescriptors() { final InspectionTool tool = getSelectedTool(); - if (getSelectionCount() == 0 || !(tool instanceof DescriptorProviderInspection)) return EMPTY_DESCRIPTORS; + if (getSelectionCount() == 0 || !(tool instanceof DescriptorProviderInspection && !(tool instanceof CommonInspectionToolWrapper))) return EMPTY_DESCRIPTORS; final TreePath[] paths = getSelectionPaths(); final LinkedHashSet descriptors = new LinkedHashSet(); for (TreePath path : paths) { diff --git a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java index 17a0bc2235ff..fa779821df8f 100644 --- a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java @@ -66,7 +66,7 @@ public class DeferredIconImpl implements DeferredIcon { } public void paintIcon(final Component c, final Graphics g, final int x, final int y) { - if (!(myDelegateIcon instanceof DeferredIconImpl)) { + if (!(myDelegateIcon instanceof DeferredIconImpl && ((DeferredIconImpl)myDelegateIcon).myDelegateIcon instanceof DeferredIconImpl)) { myDelegateIcon.paintIcon(c, g, x, y); //SOE protection } diff --git a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java index f0d0f878410f..4c931ec305f7 100644 --- a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java @@ -64,6 +64,7 @@ public class UISettings implements PersistentStateComponent, Exporta public boolean SHOW_TOOL_WINDOW_NUMBERS = true; public boolean HIDE_TOOL_STRIPES = false; public boolean SHOW_MEMORY_INDICATOR = true; + public boolean ALLOW_MERGE_BUTTONS = true; public boolean SHOW_MAIN_TOOLBAR = true; public boolean SHOW_STATUS_BAR = true; public boolean SHOW_NAVIGATION_BAR = true; diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/PlatformDataKeys.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/PlatformDataKeys.java index 4bf1a444bd39..e348b266da6e 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/PlatformDataKeys.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/PlatformDataKeys.java @@ -59,6 +59,7 @@ public class PlatformDataKeys { */ public static final DataKey IS_MODAL_CONTEXT = DataKey.create("isModalContext"); public static final DataKey DIFF_VIEWER = DataKey.create("diffViewer"); + public static final DataKey COMPOSITE_DIFF_VIEWER = DataKey.create("compositeDiffViewer"); /** * Returns help id (String) diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java index 0f78e7a4e38a..c250d4bc1be7 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequest.java @@ -19,6 +19,7 @@ import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,14 +40,21 @@ public abstract class DiffRequest { private final HashSet myHints = new HashSet(); private final Map myGenericData; private Runnable myOnOkRunnable; + private final List> myAdditional; protected DiffRequest(Project project) { myProject = project; myGenericData = new HashMap(2); + myAdditional = new ArrayList>(0); } public void setToolbarAddons(@NotNull ToolbarAddons toolbarAddons) { myToolbarAddons = toolbarAddons; + if (haveMultipleLayers()) { + for (Pair pair : myAdditional) { + pair.getSecond().setToolbarAddons(toolbarAddons); + } + } } public String getGroupKey() { return myGroupKey; } @@ -63,6 +71,24 @@ public abstract class DiffRequest { @NotNull public abstract DiffContent[] getContents(); + public DiffViewerType getType() { + if (haveMultipleLayers()) return DiffViewerType.multiLayer; + if (getContentTitles().length == 3) return DiffViewerType.merge; + return DiffViewerType.contents; + } + + public boolean haveMultipleLayers() { + return ! getOtherLayers().isEmpty(); + } + + public void addOtherLayer(final String name, DiffRequest request) { + myAdditional.add(new Pair(name, request)); + } + + public List> getOtherLayers() { + return myAdditional; + } + /** * @return contents names. Should have same length as {@link #getContents()} */ @@ -73,6 +99,10 @@ public abstract class DiffRequest { */ public abstract String getWindowTitle(); + public void setWindowTitle(final String value) { + // + } + /** * Work in progress. Don't rely on this functionality
*/ @@ -90,6 +120,11 @@ public abstract class DiffRequest { public void passForDataContext(final DataKey key, final Object value) { myGenericData.put(key.getName(), value); + if (haveMultipleLayers()) { + for (Pair pair : myAdditional) { + pair.getSecond().passForDataContext(key, value); + } + } } public Map getGenericData() { @@ -102,6 +137,11 @@ public abstract class DiffRequest { */ public void addHint(Object hint) { myHints.add(hint); + if (haveMultipleLayers()) { + for (Pair pair : myAdditional) { + pair.getSecond().addHint(hint); + } + } } /** @@ -110,6 +150,11 @@ public abstract class DiffRequest { */ public void removeHint(Object hint) { myHints.remove(hint); + if (haveMultipleLayers()) { + for (Pair pair : myAdditional) { + pair.getSecond().removeHint(hint); + } + } } /** diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java index 534c801b2ad9..07c9d101dd7a 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffTool.java @@ -15,8 +15,13 @@ */ package com.intellij.openapi.diff; +import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.DataKey; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; public interface DiffTool { @@ -55,4 +60,7 @@ public interface DiffTool { * @return true if this tool can comare given contents */ boolean canShow(DiffRequest request); + + @Nullable + DiffViewer createComponent(final String title, final DiffRequest request, Window window, Disposable parentDisposable); } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffViewer.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffViewer.java index 89c7afa4a373..ad2aba33e60c 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DiffViewer.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffViewer.java @@ -28,4 +28,6 @@ public interface DiffViewer { JComponent getPreferredFocusedComponent(); int getContentsNumber(); + + DiffViewerType getType(); } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffViewerType.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffViewerType.java new file mode 100644 index 000000000000..26c25b61ec64 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffViewerType.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2012 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; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/15/12 + * Time: 11:25 AM + */ +public enum DiffViewerType { + contents, + merge, + binary, + external_files, + external_folders, + multiLayer, + unknown +} diff --git a/platform/platform-api/src/com/intellij/openapi/diff/SimpleDiffRequest.java b/platform/platform-api/src/com/intellij/openapi/diff/SimpleDiffRequest.java index 2f82543a52a8..fa87be32dbd2 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/SimpleDiffRequest.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/SimpleDiffRequest.java @@ -49,7 +49,6 @@ public class SimpleDiffRequest extends DiffRequest { myContentTitles[1] = title2; } - public void setWindowTitle(String windowTitle) { myWindowTitle = windowTitle; } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index 516b458c90ad..4ba8817c83a0 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -16,6 +16,7 @@ package com.intellij.openapi.ui; import com.intellij.CommonBundle; +import com.intellij.ide.ui.UISettings; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.Disposable; import com.intellij.openapi.MnemonicHelper; @@ -498,7 +499,22 @@ public abstract class DialogWrapper { return false; } - private JPanel createButtons(Action[] actions, List buttons) { + private JPanel createButtons(Action[] actions, List buttons) { + if (!UISettings.getInstance().ALLOW_MERGE_BUTTONS) { + final List actionList = new ArrayList(); + for (Action action : actions) { + actionList.add(action); + if (action instanceof OptionAction) { + final Action[] options = ((OptionAction)action).getOptions(); + actionList.addAll(Arrays.asList(options)); + } + + } + if (actionList.size() != actions.length) { + actions = actionList.toArray(actionList.toArray(new Action[actionList.size()])); + } + } + JPanel buttonsPanel = new JPanel(new GridLayout(1, actions.length, SystemInfo.isMacOSLeopard ? 0 : 5, 0)); for (final Action action : actions) { JButton button = createJButtonForAction(action); @@ -537,7 +553,7 @@ public abstract class DialogWrapper { */ protected JButton createJButtonForAction(Action action) { JButton button; - if (action instanceof OptionAction) { + if (action instanceof OptionAction && UISettings.getInstance().ALLOW_MERGE_BUTTONS) { final Action[] options = ((OptionAction)action).getOptions(); button = new JBOptionButton(action, options); final JBOptionButton eachOptionsButton = (JBOptionButton)button; diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java index af38bcf58550..bbfc3827dead 100644 --- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java +++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java @@ -60,7 +60,7 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI { public void paintNow(int frame, int totalFrames, int cycle) { myAnimationColorShift = 40; if (frame > delayFrames) { - myAnimationColorShift *= 1 - (frame - delayFrames) / (totalFrames - delayFrames); + myAnimationColorShift *= 1 - ((double)(frame - delayFrames)) / ((double)(totalFrames - delayFrames)); } if (scrollbar != null) { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java index 72f3a1ebb430..9b0d4537914b 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java @@ -138,6 +138,8 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab settings.SHOW_ICONS_IN_MENUS = myComponent.myCbDisplayIconsInMenu.isSelected(); update |= settings.SHOW_MEMORY_INDICATOR != myComponent.myShowMemoryIndicatorCheckBox.isSelected(); settings.SHOW_MEMORY_INDICATOR = myComponent.myShowMemoryIndicatorCheckBox.isSelected(); + update |= settings.ALLOW_MERGE_BUTTONS != myComponent.myAllowMergeButtons.isSelected(); + settings.ALLOW_MERGE_BUTTONS = myComponent.myAllowMergeButtons.isSelected(); update |= settings.CYCLE_SCROLLING != myComponent.myCycleScrollingCheckBox.isSelected(); settings.CYCLE_SCROLLING = myComponent.myCycleScrollingCheckBox.isSelected(); if (settings.OVERRIDE_NONIDEA_LAF_FONTS != myComponent.myOverrideLAFFonts.isSelected()) { @@ -200,6 +202,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab myComponent.myShowToolStripesCheckBox.setSelected(!settings.HIDE_TOOL_STRIPES); myComponent.myCbDisplayIconsInMenu.setSelected(settings.SHOW_ICONS_IN_MENUS); myComponent.myShowMemoryIndicatorCheckBox.setSelected(settings.SHOW_MEMORY_INDICATOR); + myComponent.myAllowMergeButtons.setSelected(settings.ALLOW_MERGE_BUTTONS); myComponent.myCycleScrollingCheckBox.setSelected(settings.CYCLE_SCROLLING); myComponent.myHideIconsInQuickNavigation.setSelected(settings.SHOW_ICONS_IN_QUICK_NAVIGATION); @@ -238,6 +241,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab isModified |= myComponent.myShowToolStripesCheckBox.isSelected() == settings.HIDE_TOOL_STRIPES; isModified |= myComponent.myCbDisplayIconsInMenu.isSelected() != settings.SHOW_ICONS_IN_MENUS; isModified |= myComponent.myShowMemoryIndicatorCheckBox.isSelected() != settings.SHOW_MEMORY_INDICATOR; + isModified |= myComponent.myAllowMergeButtons.isSelected() != settings.ALLOW_MERGE_BUTTONS; isModified |= myComponent.myCycleScrollingCheckBox.isSelected() != settings.CYCLE_SCROLLING; isModified |= myComponent.myOverrideLAFFonts.isSelected() != settings.OVERRIDE_NONIDEA_LAF_FONTS; @@ -315,6 +319,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab private JCheckBox myCbDisplayIconsInMenu; private JCheckBox myDisableMnemonics; private JBCheckBox myHideNavigationPopupsCheckBox; + private JCheckBox myAllowMergeButtons; public MyComponent() { ActionListener updater = new ActionListener() { diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form index ecad82e26ff7..cdb3caab141c 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form @@ -305,6 +305,15 @@ + + + + + + + + + diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java new file mode 100644 index 000000000000..31232ef27eeb --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java @@ -0,0 +1,115 @@ +/* + * Copyright 2000-2012 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; + +import com.intellij.execution.ui.RunnerLayoutUi; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.diff.DiffViewer; +import com.intellij.openapi.diff.DiffViewerType; +import com.intellij.openapi.diff.impl.external.DiscloseMultiRequest; +import com.intellij.openapi.diff.impl.external.MultiLevelDiffTool; +import com.intellij.openapi.project.Project; +import com.intellij.ui.content.Content; +import org.jetbrains.annotations.NonNls; + +import javax.swing.*; +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/13/12 + * Time: 1:59 PM + */ +public class CompositeDiffPanel implements DiffViewer { + private final static int ourBadHackMagicContentsNumber = 101; + private final RunnerLayoutUi myUi; + private final DiscloseMultiRequest myRequest; + private final Window myWindow; + private final Disposable myParentDisposable; + private final Map myMap; + + public CompositeDiffPanel(Project project, final DiscloseMultiRequest request, final Window window, final Disposable parentDisposable) { + myRequest = request; + myWindow = window; + myParentDisposable = parentDisposable; + myUi = RunnerLayoutUi.Factory.getInstance(project).create("Diff", "Diff", "Diff", project); + myUi.getComponent().setBorder(null); + myUi.getOptions().setMinimizeActionEnabled(false); + //myUi.getOptions().setTopToolbar() + myMap = new HashMap(); + } + + @Override + public void setDiffRequest(DiffRequest request) { + final Map requestMap = myRequest.discloseRequest(request); + final HashMap copy = new HashMap(myMap); + + for (Map.Entry entry : requestMap.entrySet()) { + final String key = entry.getKey(); + final DiffRequest diffRequest = entry.getValue(); + final DiffViewer viewer = copy.remove(key); + if (viewer != null) { + viewer.setDiffRequest(diffRequest); + } else { + final DiffViewer newViewer = myRequest.viewerForRequest(myWindow, myParentDisposable, key, diffRequest); + myMap.put(key, newViewer); + final Content content = myUi.createContent(key, newViewer.getComponent(), key, null, newViewer.getPreferredFocusedComponent()); + content.setCloseable(false); + content.setPinned(true); + content.setDisposer(myParentDisposable); + myUi.addContent(content); + } + } + final Content[] contents = myUi.getContentManager().getContents(); + for (String s : copy.keySet()) { + myMap.remove(s); + for (Content content : contents) { + if (s.equals(content.getTabName())) { + myUi.getContentManager().removeContent(content, false); + break; + } + } + } + } + + @Override + public JComponent getComponent() { + return myUi.getComponent(); + } + + @Override + public JComponent getPreferredFocusedComponent() { + final Content[] contents = myUi.getContents(); + if (contents == null || contents.length == 0) return null; + return contents[0].getPreferredFocusableComponent(); + } + + @Override + public int getContentsNumber() { + return ourBadHackMagicContentsNumber; + } + + @Override + public DiffViewerType getType() { + return DiffViewerType.multiLayer; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 33a3cbee1f2e..5d3782d26df1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -17,10 +17,7 @@ package com.intellij.openapi.diff.impl; import com.intellij.ide.actions.EditSourceAction; import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.CommonShortcuts; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -183,6 +180,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid } public void reset() { + //myUi.getContentManager().removeAllContents(false); myPanel.setPreferredHeightGetter(null); } @@ -373,6 +371,11 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid return 2; } + @Override + public DiffViewerType getType() { + return DiffViewerType.contents; + } + public ComparisonPolicy getComparisonPolicy() { return myData.getComparisonPolicy(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java index 186953b1c835..10f92e976815 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffUtil.java @@ -18,6 +18,7 @@ package com.intellij.openapi.diff.impl; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.diff.DiffContent; import com.intellij.openapi.diff.DiffContentUtil; +import com.intellij.openapi.diff.DiffViewer; import com.intellij.openapi.diff.LineTokenizer; import com.intellij.openapi.diff.ex.DiffFragment; import com.intellij.openapi.diff.impl.external.DiffManagerImpl; @@ -40,8 +41,7 @@ public class DiffUtil { private DiffUtil() { } - public static void initDiffFrame(FrameWrapper frameWrapper, final DiffPanelImpl diffPanel, final JComponent mainComponent) { - Project project = diffPanel.getProject(); + public static void initDiffFrame(Project project, FrameWrapper frameWrapper, final DiffViewer diffPanel, final JComponent mainComponent) { frameWrapper.setComponent(mainComponent); frameWrapper.setProject(project); frameWrapper.setImage(ImageLoader.loadFromResource("/diff/Diff.png")); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java index ad2735f1cb89..ec9c2e2b5787 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BaseExternalTool.java @@ -18,16 +18,15 @@ package com.intellij.openapi.diff.impl.external; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.util.ExecutionErrorDialog; -import com.intellij.openapi.diff.DiffBundle; -import com.intellij.openapi.diff.DiffContent; -import com.intellij.openapi.diff.DiffRequest; -import com.intellij.openapi.diff.DiffTool; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.diff.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.config.AbstractProperty; import com.intellij.util.config.BooleanProperty; import com.intellij.util.config.StringProperty; import org.jetbrains.annotations.Nullable; +import java.awt.*; import java.io.File; import java.io.IOException; @@ -52,6 +51,11 @@ abstract class BaseExternalTool implements DiffTool { return true; } + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + return null; + } + protected abstract ContentExternalizer externalize(DiffRequest request, int index); private String getToolPath() { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BinaryDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BinaryDiffTool.java index c45084caa971..fccd186516cf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BinaryDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/BinaryDiffTool.java @@ -16,6 +16,7 @@ package com.intellij.openapi.diff.impl.external; import com.intellij.ide.diff.DiffElement; +import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.*; import com.intellij.openapi.fileEditor.FileEditorProvider; @@ -28,6 +29,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import java.awt.*; import java.io.IOException; import java.util.Arrays; @@ -42,16 +44,16 @@ public class BinaryDiffTool implements DiffTool { public void show(final DiffRequest data) { final DiffContent current = data.getContents()[0]; final DiffContent upToDate = data.getContents()[1]; + final Project project = data.getProject(); if ((current instanceof FileContent && upToDate instanceof FileContent) || (current.getContentType() instanceof UIBasedFileType && upToDate.getContentType() instanceof UIBasedFileType)) { final VirtualFile src = current.getFile(); final VirtualFile trg = upToDate.getFile(); if (src != null && trg != null) { - final FileEditorProvider[] srcProvider = FileEditorProviderManager.getInstance().getProviders(project, src); - final FileEditorProvider[] trgProvider = FileEditorProviderManager.getInstance().getProviders(project, trg); - if (srcProvider.length > 0 && trgProvider.length > 0) { - new DialogWrapper(project) { + final PanelCreator creator = new PanelCreator(data); + if (creator.isCanCreatePanel()) { + new DialogWrapper(data.getProject()) { public DiffPanel myPanel; { setModal(false); @@ -72,12 +74,7 @@ public class BinaryDiffTool implements DiffTool { @Override protected JComponent createCenterPanel() { - myPanel = DiffManager.getInstance().createDiffPanel(getWindow(), project,getDisposable()); - myPanel.setDiffRequest(data); - myPanel.setTitle1(src.getPath()); - myPanel.setTitle2(trg.getPath()); - myPanel.enableToolbar(false); - myPanel.removeStatusBar(); + myPanel = creator.create(getWindow(), getDisposable()); return myPanel.getComponent(); } }.show(); @@ -86,7 +83,7 @@ public class BinaryDiffTool implements DiffTool { final DirDiffManager diffManager = DirDiffManager.getInstance(project); final DiffElement before = diffManager.createDiffElement(src); final DiffElement after = diffManager.createDiffElement(trg); - + if (before != null && after != null && diffManager.canShow(after, before)) { diffManager.showDiff(before, after); return; @@ -108,6 +105,49 @@ public class BinaryDiffTool implements DiffTool { } } + private static class PanelCreator { + private boolean myCanCreatePanel; + private final DiffRequest myData; + private VirtualFile mySrc; + private VirtualFile myTrg; + + private PanelCreator(final DiffRequest data) { + myData = data; + final DiffContent current = data.getContents()[0]; + final DiffContent upToDate = data.getContents()[1]; + final Project project = data.getProject(); + if ((current instanceof FileContent && upToDate instanceof FileContent) + || (current.getContentType() instanceof UIBasedFileType && upToDate.getContentType() instanceof UIBasedFileType)) { + mySrc = current.getFile(); + myTrg = upToDate.getFile(); + if (mySrc != null && myTrg != null) { + final FileEditorProvider[] srcProvider = FileEditorProviderManager.getInstance().getProviders(project, mySrc); + final FileEditorProvider[] trgProvider = FileEditorProviderManager.getInstance().getProviders(project, myTrg); + if (srcProvider.length > 0 && trgProvider.length > 0) { + myCanCreatePanel = true; + } + } + } + } + + public boolean isCanCreatePanel() { + return myCanCreatePanel; + } + + public DiffPanel create(final Window window, final Disposable disposable) { + if (! myCanCreatePanel) return null; + + final Project project = myData.getProject(); + final DiffPanel panel = DiffManager.getInstance().createDiffPanel(window, project, disposable); + panel.setDiffRequest(myData); + panel.setTitle1(mySrc.getPath()); + panel.setTitle2(myTrg.getPath()); + panel.enableToolbar(false); + panel.removeStatusBar(); + return panel; + } + } + public boolean canShow(final DiffRequest data) { final DiffContent[] contents = data.getContents(); if (contents.length != 2) { @@ -122,6 +162,13 @@ public class BinaryDiffTool implements DiffTool { return true; } + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + final PanelCreator creator = new PanelCreator(request); + if (! creator.isCanCreatePanel()) return null; + return creator.create(window, parentDisposable); + } + public static boolean canShow(@NotNull Project project, VirtualFile file) { if (file == null) return false; if (FileEditorProviderManager.getInstance().getProviders(project, file).length > 0) return true; diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java index 01f3a2353f84..6278a3d8df57 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java @@ -15,15 +15,15 @@ */ package com.intellij.openapi.diff.impl.external; +import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.DiffContent; -import com.intellij.openapi.diff.DiffRequest; -import com.intellij.openapi.diff.DiffTool; +import com.intellij.openapi.diff.*; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.UIBasedFileType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.awt.*; import java.util.ArrayList; import java.util.List; @@ -47,6 +47,12 @@ class CompositeDiffTool implements DiffTool { return chooseTool(data) != null; } + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + // should not be called for it + throw new IllegalStateException(); + } + @Nullable private DiffTool chooseTool(DiffRequest data) { final DiffContent[] contents = data.getContents(); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java index b38c32c6c211..50831f60defc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java @@ -87,13 +87,31 @@ public class DiffManagerImpl extends DiffManager implements JDOMExternalizable { public DiffTool getIdeaDiffTool() { return INTERNAL_DIFF; } public DiffTool getDiffTool() { - DiffTool[] standardTools = { - ExtCompareFolders.INSTANCE, - ExtCompareFiles.INSTANCE, - INTERNAL_DIFF, - new MergeTool(), - BinaryDiffTool.INSTANCE - }; + DiffTool[] standardTools; + // there is inner check in multiple tool for external viewers as well + if (! ENABLE_FILES.value(myProperties) || ! ENABLE_FOLDERS.value(myProperties)) { + DiffTool[] embeddableTools = { + INTERNAL_DIFF, + new MergeTool(), + BinaryDiffTool.INSTANCE + }; + standardTools = new DiffTool[]{ + ExtCompareFolders.INSTANCE, + ExtCompareFiles.INSTANCE, + new MultiLevelDiffTool(Arrays.asList(embeddableTools)), + INTERNAL_DIFF, + new MergeTool(), + BinaryDiffTool.INSTANCE + }; + } else { + standardTools = new DiffTool[]{ + ExtCompareFolders.INSTANCE, + ExtCompareFiles.INSTANCE, + INTERNAL_DIFF, + new MergeTool(), + BinaryDiffTool.INSTANCE + }; + } ArrayList allTools = new ArrayList(myAdditionTools); allTools.addAll(Arrays.asList(standardTools)); return new CompositeDiffTool(allTools); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiscloseMultiRequest.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiscloseMultiRequest.java new file mode 100644 index 000000000000..18c9adec2647 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiscloseMultiRequest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2012 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.external; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.diff.DiffViewer; +import com.intellij.openapi.util.Pair; + +import java.awt.*; +import java.util.List; +import java.util.Map; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/13/12 + * Time: 6:58 PM + */ +public interface DiscloseMultiRequest { + Map discloseRequest(DiffRequest request); + DiffViewer viewerForRequest(Window window, Disposable parentDisposable, final String name, DiffRequest current); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java index 6db22efea7ff..d08f609b6457 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java @@ -92,7 +92,7 @@ class FrameDiffTool implements DiffTool { diffPanel.setPatchAppliedApproximately(); } frameWrapper.setTitle(request.getWindowTitle()); - DiffUtil.initDiffFrame(frameWrapper, diffPanel, diffPanel.getComponent()); + DiffUtil.initDiffFrame(diffPanel.getProject(), frameWrapper, diffPanel, diffPanel.getComponent()); new AnAction() { public void actionPerformed(final AnActionEvent e) { @@ -143,11 +143,11 @@ class FrameDiffTool implements DiffTool { return diffPanel; } - private static void showDiffDialog(DialogBuilder builder, Collection hints) { + static void showDiffDialog(DialogBuilder builder, Collection hints) { builder.showModal(!hints.contains(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG)); } - private static boolean shouldOpenDialog(Collection hints) { + static boolean shouldOpenDialog(Collection hints) { if (hints.contains(DiffTool.HINT_SHOW_MODAL_DIALOG)) return true; if (hints.contains(DiffTool.HINT_SHOW_NOT_MODAL_DIALOG)) return true; if (hints.contains(DiffTool.HINT_SHOW_FRAME)) return false; @@ -205,4 +205,9 @@ class FrameDiffTool implements DiffTool { } return true; } + + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + return createDiffPanelIfShouldShow(request, window, parentDisposable); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/MultiLevelDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/MultiLevelDiffTool.java new file mode 100644 index 000000000000..ca544b7bc6b9 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/MultiLevelDiffTool.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2012 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.external; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.diff.DiffContent; +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.diff.DiffTool; +import com.intellij.openapi.diff.DiffViewer; +import com.intellij.openapi.diff.impl.CompositeDiffPanel; +import com.intellij.openapi.diff.impl.DiffUtil; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.ui.DialogBuilder; +import com.intellij.openapi.ui.FrameWrapper; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.config.AbstractProperty; +import com.intellij.util.containers.hash.HashMap; + +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/13/12 + * Time: 3:17 PM + */ +public class MultiLevelDiffTool implements DiffTool, DiscloseMultiRequest { + public final static String ourDefaultTab = "Contents"; + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.external.MultiLevelDiffTool"); + private final List myTools; + + public MultiLevelDiffTool(final List tools) { + myTools = tools; + } + + @Override + public void show(DiffRequest request) { + Collection hints = request.getHints(); + boolean shouldOpenDialog = FrameDiffTool.shouldOpenDialog(hints); + if (shouldOpenDialog) { + final DialogBuilder builder = new DialogBuilder(request.getProject()); + final CompositeDiffPanel diffPanel = createPanel(request, builder.getWindow(), builder); + if (diffPanel == null) { + Disposer.dispose(builder); + return; + } + // todo ? + builder.removeAllActions(); + builder.setCenterPanel(diffPanel.getComponent()); + builder.setPreferedFocusComponent(diffPanel.getPreferredFocusedComponent()); + builder.setTitle(request.getWindowTitle()); + builder.setDimensionServiceKey(request.getGroupKey()); + + new AnAction() { + public void actionPerformed(final AnActionEvent e) { + builder.getDialogWrapper().close(0); + } + }.registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts("CloseContent")), + diffPanel.getComponent()); + diffPanel.setDiffRequest(request); + FrameDiffTool.showDiffDialog(builder, hints); + } else { + final FrameWrapper frameWrapper = new FrameWrapper(request.getProject(), request.getGroupKey()); + final CompositeDiffPanel diffPanel = createPanel(request, frameWrapper.getFrame(), frameWrapper); + if (diffPanel == null) { + Disposer.dispose(frameWrapper); + return; + } + frameWrapper.setTitle(request.getWindowTitle()); + diffPanel.setDiffRequest(request); + DiffUtil.initDiffFrame(request.getProject(), frameWrapper, diffPanel, diffPanel.getComponent()); + + new AnAction() { + public void actionPerformed(final AnActionEvent e) { + frameWrapper.getFrame().dispose(); + } + }.registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts("CloseContent")), + diffPanel.getComponent()); + + frameWrapper.show(); + } + } + + private CompositeDiffPanel createPanel(DiffRequest request, final Window window, final Disposable parentDisposable) { + final CompositeDiffPanel panel = new CompositeDiffPanel(request.getProject(), this, window, parentDisposable); + request.getGenericData().put(PlatformDataKeys.COMPOSITE_DIFF_VIEWER.getName(), panel); + final List> layers = request.getOtherLayers(); + if (layers != null) { + for (Pair layer : layers) { + layer.getSecond().getGenericData().put(PlatformDataKeys.COMPOSITE_DIFF_VIEWER.getName(), panel); + } + } + return panel; + } + + public DiffViewer viewerForRequest(Window window, + Disposable parentDisposable, + final String name, DiffRequest current) { + DiffViewer viewer = null; + for (DiffTool tool : myTools) { + if (tool.canShow(current)) { + viewer = tool.createComponent(name, current, window, parentDisposable); + break; + } + } + return viewer; + } + + public Map discloseRequest(DiffRequest request) { + final Map pairs = new TreeMap(new Comparator() { + @Override + public int compare(String o1, String o2) { + if (ourDefaultTab.equals(o1)) return -1; + if (ourDefaultTab.equals(o2)) return 1; + return Comparing.compare(o1, o2); + } + }); + final List> layers = request.getOtherLayers(); + for (Pair layer : layers) { + pairs.put(layer.getFirst(), layer.getSecond()); + } + pairs.put(ourDefaultTab, request); + return pairs; + } + + @Override + public boolean canShow(DiffRequest request) { + boolean isFile = false; + DiffContent[] contents = request.getContents(); + for (int i = 0; i < contents.length; i++) { + DiffContent content = contents[i]; + VirtualFile file = content.getFile(); + if (file != null && file.isInLocalFileSystem() && ! file.isDirectory()) { + isFile = true; + break; + } + } + AbstractProperty.AbstractPropertyContainer config = DiffManagerImpl.getInstanceEx().getProperties(); + if (isFile && DiffManagerImpl.ENABLE_FILES.value(config)) return false; + if (! isFile && DiffManagerImpl.ENABLE_FOLDERS.value(config)) return false; + return request.haveMultipleLayers(); + } + + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + // should not be called for it + throw new IllegalStateException(); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java index f7a85dc1e0e7..adeadb75847f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java @@ -41,7 +41,6 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorMarkupModel; -import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypes; @@ -297,6 +296,11 @@ public class MergePanel2 implements DiffViewer { return 3; } + @Override + public DiffViewerType getType() { + return DiffViewerType.merge; + } + private boolean hasAllEditors() { for (int i = 0; i < EDITORS_COUNT; i++) { if (getEditor(i) == null) return false; @@ -304,10 +308,6 @@ public class MergePanel2 implements DiffViewer { return true; } - public DialogBuilder getBuilder() { - return myBuilder; - } - public MergeRequestImpl getMergeRequest() { return (MergeRequestImpl)(myData instanceof MergeRequestImpl ? myData : null); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeTool.java index 0f2327d73a66..6502ba5386d8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeTool.java @@ -22,6 +22,8 @@ import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; +import java.awt.*; + public class MergeTool implements DiffTool { public void show(DiffRequest data) { if (data instanceof MergeRequestImpl) { @@ -69,4 +71,9 @@ public class MergeTool implements DiffTool { } return true; } + + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + return createMergeComponent(request, null, parentDisposable); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java index 6c2ae03f2575..21d1fb3d46a3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java @@ -449,7 +449,7 @@ public class ScrollingModelImpl implements ScrollingModelEx { myAnimator = new Animator("Animated scroller", myStepCount, SCROLL_DURATION, false, true) { @Override public void paintNow(int frame, int totalFrames, int cycle) { - double time = (frame + 1) / (double)totalFrames; + double time = ((double)(frame + 1)) / (double)totalFrames; double fraction = timeToFraction(time); final int hOffset = (int)(myStartHOffset + (myEndHOffset - myStartHOffset) * fraction + 0.5); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/external/DiffManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/external/DiffManagerTest.java index 525bcac7b374..64b444b702f4 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/external/DiffManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/external/DiffManagerTest.java @@ -15,15 +15,14 @@ */ package com.intellij.openapi.diff.impl.external; -import com.intellij.openapi.diff.BinaryContent; -import com.intellij.openapi.diff.DiffContent; -import com.intellij.openapi.diff.DiffRequest; -import com.intellij.openapi.diff.DiffTool; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.diff.*; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.util.ArrayUtil; import junit.framework.TestCase; import org.jetbrains.annotations.NotNull; +import java.awt.*; import java.util.ArrayList; public class DiffManagerTest extends TestCase { @@ -53,6 +52,11 @@ public class DiffManagerTest extends TestCase { return canShowImpl(request); } + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + return null; + } + private static boolean canShowImpl(DiffRequest request) { return request.getContents().length == 4; } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/Change.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/Change.java index e383de3f7164..ff52469a6783 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/Change.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/Change.java @@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FileStatus; @@ -30,6 +31,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.File; +import java.util.HashMap; +import java.util.Map; /** * @author max @@ -53,6 +56,9 @@ public class Change { protected boolean myRenameOrMoveCached = false; private boolean myIsReplaced; private Type myType; + private final Map myOtherLayers; + // if null, vcs's is used. intended: for property conflict case + private Getter myMergeProvider; public Change(final ContentRevision beforeRevision, final ContentRevision afterRevision) { this(beforeRevision, afterRevision, convertStatus(beforeRevision, afterRevision)); @@ -64,6 +70,7 @@ public class Change { myAfterRevision = afterRevision; myFileStatus = fileStatus == null ? convertStatus(beforeRevision, afterRevision) : fileStatus; myHash = -1; + myOtherLayers = new HashMap(0); } private static FileStatus convertStatus(ContentRevision beforeRevision, ContentRevision afterRevision) { @@ -72,6 +79,26 @@ public class Change { return FileStatus.MODIFIED; } + public Getter getMergeProvider() { + return myMergeProvider; + } + + public void setMergeProvider(Getter mergeProvider) { + myMergeProvider = mergeProvider; + } + + public void addAdditionalLayerElement(final String name, final Change change) { + myOtherLayers.put(name, change); + } + + public Map getOtherLayers() { + return myOtherLayers; + } + + public boolean hasOtherLayers() { + return ! myOtherLayers.isEmpty(); + } + public Type getType() { if (myType == null) { if (myBeforeRevision == null) { diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ExternallyRenamedChange.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ExternallyRenamedChange.java index e6143f1ff891..03a9567faf67 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ExternallyRenamedChange.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ExternallyRenamedChange.java @@ -87,4 +87,8 @@ public class ExternallyRenamedChange extends Change { public void setCopied(final boolean copied) { myCopied = copied; } + + public String getOriginUrl() { + return myOriginUrl; + } } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/MergeTexts.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/MergeTexts.java new file mode 100644 index 000000000000..18423d8ad490 --- /dev/null +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/MergeTexts.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2012 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; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/14/12 + * Time: 4:31 PM + */ +public class MergeTexts { + private final String myLeft; + private final String myRight; + private final String myBase; + + public MergeTexts(String left, String right, String base) { + myLeft = left; + myRight = right; + myBase = base; + } + + public String getLeft() { + return myLeft; + } + + public String getRight() { + return myRight; + } + + public String getBase() { + return myBase; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java index 2035e149da97..d7210246e5ba 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/FilePathImpl.java @@ -131,6 +131,10 @@ public class FilePathImpl implements FilePath { } } + public void setIsDirectory(boolean isDirectory) { + myIsDirectory = isDirectory; + } + public boolean isDirectory() { if (myVirtualFile == null) { return myIsDirectory; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SimpleContentRevision.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SimpleContentRevision.java index 65190216b85d..0f417a68954c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SimpleContentRevision.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SimpleContentRevision.java @@ -22,7 +22,7 @@ public class SimpleContentRevision implements ContentRevision { } @Nullable - public String getContent() throws VcsException { + public String getContent() { return myContent; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java index ddf8e002b5c9..f598d61ca0f5 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsManager.java @@ -104,6 +104,11 @@ public class VcsChangeDetailsManager { myQueue = queue; } + @Override + public String getName() { + return "Contents Diff"; + } + @Override public boolean canComment(Change change) { FilePath path = ChangesUtil.getFilePath(change); @@ -213,6 +218,11 @@ public class VcsChangeDetailsManager { myQueue = queue; } + @Override + public String getName() { + return "Contents Diff"; + } + @Override public boolean canComment(Change change) { return FragmentedDiffRequestFromChange.canCreateRequest(change); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsProvider.java index e006fa2bfe08..75da00932629 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsProvider.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsChangeDetailsProvider.java @@ -16,6 +16,7 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.Disposable; +import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.CalledInAwt; import com.intellij.openapi.vcs.CalledInBackground; @@ -28,6 +29,10 @@ import javax.swing.*; * Time: 2:49 PM */ public interface VcsChangeDetailsProvider { + ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.vcschangedetails"); + + String getName(); + @CalledInAwt boolean canComment(final Change change); @CalledInAwt diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java index c8bb85324281..6831b52c7bac 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java @@ -42,12 +42,18 @@ import java.util.List; public class ChangeDiffRequestPresentable implements DiffRequestPresentable { private final Project myProject; private final Change myChange; + // I don't like that much + private boolean myIgnoreDirectoryFlag; public ChangeDiffRequestPresentable(final Project project, final Change change) { myChange = change; myProject = project; } + public void setIgnoreDirectoryFlag(boolean ignoreDirectoryFlag) { + myIgnoreDirectoryFlag = ignoreDirectoryFlag; + } + public MyResult step(DiffChainContext context) { final SimpleDiffRequest request = new SimpleDiffRequest(myProject, null); if (! canShowChange(context)) { @@ -157,6 +163,11 @@ public class ChangeDiffRequestPresentable implements DiffRequestPresentable { final ContentRevision bRev = myChange.getBeforeRevision(); final ContentRevision aRev = myChange.getAfterRevision(); + if (myIgnoreDirectoryFlag) { + if (! checkContentsAvailable(bRev, aRev)) return false; + return true; + } + if ((bRev != null && (bRev.getFile().getFileType().isBinary() || bRev.getFile().isDirectory())) || (aRev != null && (aRev.getFile().getFileType().isBinary() || aRev.getFile().isDirectory()))) { if (bRev != null && bRev.getFile().getFileType() == FileTypes.UNKNOWN && !bRev.getFile().isDirectory()) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeForDiffConvertor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeForDiffConvertor.java new file mode 100644 index 000000000000..8cb62c17f356 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeForDiffConvertor.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2012 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.actions; + +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Getter; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.openapi.vcs.changes.patch.ApplyPatchForBaseRevisionTexts; +import com.intellij.openapi.vcs.changes.patch.MergedDiffRequestPresentable; +import com.intellij.openapi.vcs.merge.MergeProvider; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.Convertor; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/14/12 + * Time: 3:07 PM + */ +public class ChangeForDiffConvertor implements Convertor { + private final Project myProject; + private final boolean myRecursive; + + public ChangeForDiffConvertor(Project project, final boolean recursive) { + myProject = project; + myRecursive = recursive; + } + + @Override + public DiffRequestPresentable convert(Change o) { + return convert(o, false); + } + + public DiffRequestPresentable convert(final Change ch, final boolean forceText) { + if (ch.hasOtherLayers() && myRecursive) { + return new MultipleDiffRequestPresentable(myProject, ch); + } + if (ChangesUtil.isTextConflictingChange(ch)) { + final AbstractVcs vcs = ChangesUtil.getVcsForChange(ch, myProject); + final MergeProvider mergeProvider = vcs.getMergeProvider(); + if (mergeProvider == null) return null; + final FilePath path = ChangesUtil.getFilePath(ch); + VirtualFile vf = path.getVirtualFile(); + if (vf == null) { + path.hardRefresh(); + vf = path.getVirtualFile(); + } + if (vf == null) return null; + + return new ConflictedDiffRequestPresentable(myProject, vf, ch); + } else { + final ChangeDiffRequestPresentable presentable = new ChangeDiffRequestPresentable(myProject, ch); + if (forceText) { + presentable.setIgnoreDirectoryFlag(true); + } + return presentable; + } + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java new file mode 100644 index 000000000000..ce19d4c0aeb8 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java @@ -0,0 +1,129 @@ +/* + * Copyright 2000-2012 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.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.diff.DiffRequestFactory; +import com.intellij.openapi.diff.MergeRequest; +import com.intellij.openapi.diff.SimpleDiffRequest; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Getter; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.VcsBundle; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.openapi.vcs.changes.MergeTexts; +import com.intellij.openapi.vcs.merge.MergeData; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.openapi.vfs.VirtualFile; + +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/14/12 + * Time: 4:09 PM + */ +public class ConflictedDiffRequestPresentable implements DiffRequestPresentable { + private final static Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.actions.ConflictedDiffRequestPresentable"); + private final Project myProject; + private final VirtualFile myFile; + private final Change myChange; + + public ConflictedDiffRequestPresentable(final Project project, VirtualFile file, final Change change) { + myProject = project; + myFile = file; + myChange = change; + } + + @Override + public MyResult step(DiffChainContext context) { + if (myChange.getAfterRevision() == null) return createErrorResult(); + final Getter mergeProvider = myChange.getMergeProvider(); + if (mergeProvider != null) { + // guaranteed text + final MergeTexts texts = mergeProvider.get(); + if (texts == null) { + return createErrorResult(); + } + final MergeRequest request = DiffRequestFactory.getInstance() + .create3WayDiffRequest(texts.getLeft(), texts.getRight(), texts.getBase(), myProject, null, null); + request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl())); + // todo titles? + request.setVersionTitles(new String[] {myChange.getAfterRevision().getRevisionNumber().asString(), + "Base Version", "Last Revision"}); + return new MyResult(request, DiffPresentationReturnValue.useRequest); + + } else { + if (myFile.getFileType().isBinary()) { + final boolean nowItIsText = ChangeDiffRequestPresentable.checkAssociate(myProject, new FilePathImpl(myFile), context); + if (! nowItIsText) { + return createErrorResult(); + } + } + final AbstractVcs vcs = ChangesUtil.getVcsForChange(myChange, myProject); + if (vcs == null || vcs.getMergeProvider() == null) { + return createErrorResult(); + } + try { + final MergeData mergeData = vcs.getMergeProvider().loadRevisions(myFile); + if (mergeData == null) { + return createErrorResult(); + } + final Charset charset = myFile.getCharset(); + final MergeRequest request = DiffRequestFactory.getInstance() + .create3WayDiffRequest(CharsetToolkit.bytesToString(mergeData.CURRENT, charset), + CharsetToolkit.bytesToString(mergeData.LAST, charset), + CharsetToolkit.bytesToString(mergeData.ORIGINAL, charset), myProject, null, null); + request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl())); + // todo titles? + request.setVersionTitles(new String[] {myChange.getAfterRevision().getRevisionNumber().asString(), + "Base Version", mergeData.LAST_REVISION_NUMBER.asString()}); + return new MyResult(request, DiffPresentationReturnValue.useRequest); + } + catch (VcsException e) { + LOG.info(e); + return createErrorResult(); + } + } + } + + private MyResult createErrorResult() { + final SimpleDiffRequest request = new SimpleDiffRequest(myProject, null); + return new MyResult(request, DiffPresentationReturnValue.removeFromList); + } + + @Override + public void haveStuff() throws VcsException { + } + + @Override + public List createActions(ShowDiffAction.DiffExtendUIFactory uiFactory) { + return Collections.emptyList(); + } + + @Override + public String getPathPresentation() { + return myFile.getPath(); + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/MultipleDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/MultipleDiffRequestPresentable.java new file mode 100644 index 000000000000..b4eaf504604d --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/MultipleDiffRequestPresentable.java @@ -0,0 +1,107 @@ +/* + * Copyright 2000-2012 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.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.diff.DiffRequest; +import com.intellij.openapi.diff.SimpleDiffRequest; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.psi.impl.source.tree.ChangeUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/14/12 + * Time: 3:48 PM + */ +public class MultipleDiffRequestPresentable implements DiffRequestPresentable { + private final Project myProject; + private final Change myChange; + + public MultipleDiffRequestPresentable(Project project, Change change) { + myProject = project; + myChange = change; + } + + @Override + public MyResult step(DiffChainContext context) { + final ChangeForDiffConvertor convertor = new ChangeForDiffConvertor(myProject, false); + final List> list = new ArrayList>(); + final DiffRequestPresentable requestPresentable = convertor.convert(myChange, false); + if (requestPresentable != null) { + list.add(new Pair("", requestPresentable)); + } + final Map layers = myChange.getOtherLayers(); + for (Map.Entry entry : layers.entrySet()) { + final String key = entry.getKey(); + final Change value = entry.getValue(); + final DiffRequestPresentable additional = convertor.convert(value, true); + if (additional != null) { + list.add(new Pair(key, additional)); + } + } + + if (list.isEmpty()) return new MyResult(new SimpleDiffRequest(myProject, ""), DiffPresentationReturnValue.removeFromList); + + DiffRequest request = null; + for (Pair pair : list) { + final MyResult step = pair.getSecond().step(context); + if (step == null) continue; + final DiffPresentationReturnValue returnValue = step.getReturnValue(); + if (DiffPresentationReturnValue.quit.equals(returnValue)) { + return new MyResult(new SimpleDiffRequest(myProject, ""), DiffPresentationReturnValue.quit); + } else if (! DiffPresentationReturnValue.removeFromList.equals(returnValue)) { + // use contents + if (request == null) { + request = step.getRequest(); + if (! StringUtil.isEmptyOrSpaces(pair.getFirst())) { + request.setWindowTitle(pair.getFirst() + " " + request.getWindowTitle()); + } + } else { + request.addOtherLayer(pair.getFirst(), step.getRequest()); + } + } + } + if (request == null) { + return new MyResult(new SimpleDiffRequest(myProject, ""), DiffPresentationReturnValue.removeFromList); + } + return new MyResult(request, DiffPresentationReturnValue.useRequest); + } + + @Override + public void haveStuff() throws VcsException { + } + + @Override + public List createActions(ShowDiffAction.DiffExtendUIFactory uiFactory) { + return Collections.emptyList(); + } + + @Override + public String getPathPresentation() { + return ChangesUtil.getFilePath(myChange).getPath(); + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java index 54452bd820ea..3124718db898 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java @@ -61,7 +61,7 @@ public class ShowDiffAction extends AnAction implements DumbAware { protected static boolean canShowDiff(Change[] changes) { if (changes == null || changes.length == 0) return false; - return !ChangesUtil.getFilePath(changes [0]).isDirectory(); + return !ChangesUtil.getFilePath(changes [0]).isDirectory() || changes[0].hasOtherLayers(); } public void actionPerformed(final AnActionEvent e) { @@ -192,13 +192,8 @@ public class ShowDiffAction extends AnAction implements DumbAware { if (newIndex < 0) { newIndex = 0; } - - showDiffImpl(project, ObjectsConvertor.convert(changeList, - new Convertor() { - public ChangeDiffRequestPresentable convert(Change o) { - return new ChangeDiffRequestPresentable(project, o); - } - }), newIndex, context); + + showDiffImpl(project, ObjectsConvertor.convert(changeList, new ChangeForDiffConvertor(project, true), ObjectsConvertor.NOT_NULL), newIndex, context); } public static void showDiffForChange(final Change[] changes, int index, final Project project, @NotNull ShowDiffUIContext context) { @@ -277,6 +272,7 @@ public class ShowDiffAction extends AnAction implements DumbAware { } public static boolean isBinaryChange(Change change) { + if (change.hasOtherLayers()) return false; // +- final ContentRevision bRev = change.getBeforeRevision(); final ContentRevision aRev = change.getAfterRevision(); @@ -319,7 +315,7 @@ public class ShowDiffAction extends AnAction implements DumbAware { }*/ final FilePath path = ChangesUtil.getFilePath(change); if (path.isDirectory()) { - return true; + return ! change.hasOtherLayers(); } final FileType type = path.getFileType(); if ((! FileTypes.UNKNOWN.equals(type)) && (type.isBinary())) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowNextChangeAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowNextChangeAction.java index ef2554df89c0..5cd6508d12bb 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowNextChangeAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowNextChangeAction.java @@ -50,15 +50,20 @@ public class ShowNextChangeAction extends AnAction implements DumbAware { return; } - final DiffViewer diffViewer = e.getData(PlatformDataKeys.DIFF_VIEWER); + DiffViewer diffViewer = e.getData(PlatformDataKeys.COMPOSITE_DIFF_VIEWER); + if (diffViewer == null) { + diffViewer = e.getData(PlatformDataKeys.DIFF_VIEWER); + } if (diffViewer == null) return; final DiffRequest request = chain.moveForward(); if (request != null) { - if (diffViewer.getContentsNumber() == request.getContents().length) { + if (diffViewer.getType().equals(request.getType())) { diffViewer.setDiffRequest(request); } else { final Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); - window.setVisible(false); + if (window != null) { + window.setVisible(false); + } DiffManager.getInstance().getDiffTool().show(request); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowPrevChangeAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowPrevChangeAction.java index 618182fb37f6..de1969dddc46 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowPrevChangeAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowPrevChangeAction.java @@ -26,7 +26,9 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.ChangeRequestChain; +import com.intellij.util.ui.UIUtil; +import javax.swing.*; import java.awt.*; /** @@ -49,16 +51,27 @@ public class ShowPrevChangeAction extends AnAction implements DumbAware { return; } - final DiffViewer diffViewer = e.getData(PlatformDataKeys.DIFF_VIEWER); + DiffViewer diffViewer = e.getData(PlatformDataKeys.COMPOSITE_DIFF_VIEWER); + if (diffViewer == null) { + diffViewer = e.getData(PlatformDataKeys.DIFF_VIEWER); + } if (diffViewer == null) return; final DiffRequest request = chain.moveBack(); if (request != null) { - if (diffViewer.getContentsNumber() == request.getContents().length) { + if (diffViewer.getType().equals(request.getType())) { diffViewer.setDiffRequest(request); } else { final Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); - window.setVisible(false); + if (window != null) { + window.setVisible(false); + } else { + JComponent current = (JComponent)diffViewer; + final Window windowAncestor = SwingUtilities.getWindowAncestor(current); + if (windowAncestor != null) { + windowAncestor.setVisible(false); + } + } DiffManager.getInstance().getDiffTool().show(request); } } diff --git a/plugins/git4idea/src/git4idea/util/UntrackedFilesNotifier.java b/plugins/git4idea/src/git4idea/util/UntrackedFilesNotifier.java index 1ddab094a1fd..d153f60a3e26 100644 --- a/plugins/git4idea/src/git4idea/util/UntrackedFilesNotifier.java +++ b/plugins/git4idea/src/git4idea/util/UntrackedFilesNotifier.java @@ -51,7 +51,8 @@ public class UntrackedFilesNotifier { NotificationManager.getInstance(project).notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, notificationTitle, notificationDesc, NotificationType.ERROR, new NotificationListener() { @Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { - SelectFilesDialog dlg = new SelectFilesDialog(project, new ArrayList(untrackedFiles), dialogDesc, null, false, false) { + SelectFilesDialog dlg = new SelectFilesDialog(project, new ArrayList(untrackedFiles), + StringUtil.stripHtml(dialogDesc, true), null, false, false) { @Override protected Action[] createActions() { return new Action[]{getOKAction()}; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.form b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.form index 9c35f9e3c165..1c47880ce856 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.form +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.form @@ -148,7 +148,7 @@ - + @@ -164,8 +164,7 @@ - - + diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java index f9eb6e511e53..e78e2d495aee 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java @@ -88,7 +88,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { private JScrollPane myArchetypeDescriptionScrollPane; private JTextArea myArchetypeDescriptionField; - private AtomicBoolean myLoadingCancelled = new AtomicBoolean(); + private Object myCurrentUpdaterMarker; private final AsyncProcessIcon myLoadingIcon = new AsyncProcessIcon.Big(getClass() + ".loading"); public MavenModuleWizardStep(@Nullable Project project, MavenModuleBuilder builder) { @@ -104,11 +104,18 @@ public class MavenModuleWizardStep extends ModuleWizardStep { myArchetypesTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode())); myArchetypesScrollPane = ScrollPaneFactory.createScrollPane(myArchetypesTree); - myLoadingIcon.setVisible(false); + myArchetypesPanel.add(myArchetypesScrollPane, "archetypes"); + + JPanel loadingPanel = new JPanel(new GridBagLayout()); + JPanel bp = new JPanel(new BorderLayout(10, 10)); + bp.add(new JLabel("Loading archetype list..."), BorderLayout.NORTH); + bp.add(myLoadingIcon, BorderLayout.CENTER); + + loadingPanel.add(bp, new GridBagConstraints()); + + myArchetypesPanel.add(ScrollPaneFactory.createScrollPane(loadingPanel), "loading"); + ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes"); - myArchetypesPanel.setLayout(new MyLayout()); - myArchetypesPanel.add(myArchetypesScrollPane); - myArchetypesPanel.add(myLoadingIcon); mySelectAggregator.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -133,7 +140,6 @@ public class MavenModuleWizardStep extends ModuleWizardStep { myInheritVersionCheckBox.addActionListener(updatingListener); myUseArchetypeCheckBox.addActionListener(updatingListener); - myArchetypesTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); myAddArchetypeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -189,7 +195,6 @@ public class MavenModuleWizardStep extends ModuleWizardStep { @Override public void onStepLeaving() { - myLoadingCancelled.set(true); saveSettings(); } @@ -228,7 +233,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { return getSavedValue(key, String.valueOf(defaultValue)).equals(String.valueOf(true)); } - private String getSavedValue(String key, String defaultValue) { + private static String getSavedValue(String key, String defaultValue) { String value = PropertiesComponent.getInstance().getValue(key); return value == null ? defaultValue : value; } @@ -237,7 +242,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { saveValue(key, String.valueOf(value)); } - private void saveValue(String key, String value) { + private static void saveValue(String key, String value) { PropertiesComponent props = PropertiesComponent.getInstance(); props.setValue(key, value); } @@ -272,26 +277,24 @@ public class MavenModuleWizardStep extends ModuleWizardStep { } private void updateArchetypesList(final MavenArchetype selected) { - myLoadingCancelled.set(true); - myLoadingCancelled = new AtomicBoolean(); - final AtomicBoolean currentStatus = myLoadingCancelled; - myLoadingIcon.setVisible(true); + ApplicationManager.getApplication().assertIsDispatchThread(); + myLoadingIcon.setBackground(myArchetypesTree.getBackground()); + ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "loading"); + + final Object currentUpdaterMarker = new Object(); + myCurrentUpdaterMarker = currentUpdaterMarker; + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { - try { - Thread.sleep(3000); - } - catch (InterruptedException e) { - throw new RuntimeException(e); - } final Set archetypes = MavenIndicesManager.getInstance().getArchetypes(); SwingUtilities.invokeLater(new Runnable() { public void run() { - if (currentStatus.get()) return; - myLoadingIcon.setVisible(false); + if (currentUpdaterMarker != myCurrentUpdaterMarker) return; // Other updater has been run. + + ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes"); TreeNode root = groupAndSortArchetypes(archetypes); TreeModel model = new DefaultTreeModel(root); @@ -325,7 +328,8 @@ public class MavenModuleWizardStep extends ModuleWizardStep { myMainPanel.revalidate(); } - private TreePath findNodePath(MavenArchetype object, TreeModel model, Object parent) { + @Nullable + private static TreePath findNodePath(MavenArchetype object, TreeModel model, Object parent) { for (int i = 0; i < model.getChildCount(parent); i++) { DefaultMutableTreeNode each = (DefaultMutableTreeNode)model.getChild(parent, i); if (each.getUserObject().equals(object)) return new TreePath(each.getPath()); @@ -336,7 +340,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { return null; } - private TreeNode groupAndSortArchetypes(Set archetypes) { + private static TreeNode groupAndSortArchetypes(Set archetypes) { List list = new ArrayList(archetypes); Collections.sort(list, new Comparator() { @@ -458,7 +462,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { return WIZARD_ICON; } - private class MyRenderer extends ColoredTreeCellRenderer { + private static class MyRenderer extends ColoredTreeCellRenderer { public void customizeCellRenderer(JTree tree, Object value, boolean selected, @@ -486,19 +490,5 @@ public class MavenModuleWizardStep extends ModuleWizardStep { public String getHelpId() { return "reference.dialogs.new.project.fromScratch.maven"; } - - private class MyLayout extends AbstractLayoutManager { - public Dimension preferredLayoutSize(Container parent) { - return myArchetypesScrollPane.getPreferredSize(); - } - - public void layoutContainer(Container parent) { - int w = parent.getWidth(); - int h = parent.getHeight(); - myArchetypesScrollPane.setBounds(new Rectangle(0, 0, w, h)); - Dimension is = myLoadingIcon.getPreferredSize(); - myLoadingIcon.setBounds(new Rectangle((w - is.width) / 2, (h - is.height) / 2, is.width, is.height)); - } - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProvider.java index 7833fe34c000..3c825a998174 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProvider.java @@ -58,6 +58,7 @@ import java.util.*; public class SvnChangeProvider implements ChangeProvider { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnChangeProvider"); public static final String ourDefaultListName = VcsBundle.message("changes.default.changlist.name"); + public static final String PROPERTY_LAYER = "Property"; private final SvnVcs17 myVcs; private final VcsContextFactory myFactory; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProviderContext.java index d58ce242e1f7..31ef208e05ef 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProviderContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnChangeProviderContext.java @@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn17.actions.AbstractShowPropertiesDiffAction; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNLock; @@ -314,27 +315,64 @@ class SvnChangeProviderContext implements StatusReceiver { // seems here we can only have a tree conflict; which can be marked on either path (?) // .. ok try to merge states Change createMovedChange(final ContentRevision before, final ContentRevision after, final SVNStatus copiedStatus, - final SVNStatus deletedStatus) { - return new ConflictedSvnChange(before, after, ConflictState.mergeState(getState(copiedStatus), getState(deletedStatus)), - ((copiedStatus != null) && (copiedStatus.getTreeConflict() != null)) ? after.getFile() : before.getFile()); + final SVNStatus deletedStatus) throws SVNException { + // todo no convertion needed for the contents status? + return patchWithPropertyChange(new ConflictedSvnChange(before, after, ConflictState.mergeState(getState(copiedStatus), getState(deletedStatus)), + ((copiedStatus != null) && (copiedStatus.getTreeConflict() != null)) ? after.getFile() : before.getFile()), copiedStatus, deletedStatus); } - private Change createChange(final ContentRevision before, final ContentRevision after, final FileStatus fStatus, final SVNStatus svnStatus) { - return new ConflictedSvnChange(before, after, fStatus, getState(svnStatus), after == null ? before.getFile() : after.getFile()); + private Change createChange(final ContentRevision before, final ContentRevision after, final FileStatus fStatus, final SVNStatus svnStatus) + throws SVNException { + return patchWithPropertyChange(new ConflictedSvnChange(before, after, correctContentsStatus(fStatus, svnStatus), + getState(svnStatus), after == null ? before.getFile() : after.getFile()), svnStatus, null); + } + + private FileStatus correctContentsStatus(final FileStatus fs, final SVNStatus svnStatus) throws SVNException { + return fs; + //return SvnStatusConvertor.convertContentsStatus(svnStatus); } private LocallyDeletedChange createLocallyDeletedChange(@NotNull FilePath filePath, final SVNStatus status) { return new SvnLocallyDeletedChange(filePath, getState(status)); } + private Change patchWithPropertyChange(final Change change, final SVNStatus svnStatus, final SVNStatus deletedStatus) throws SVNException { + final SVNStatusType propertiesStatus = svnStatus.getPropertiesStatus(); + if (SVNStatusType.STATUS_CONFLICTED.equals(propertiesStatus) || SVNStatusType.CHANGED.equals(propertiesStatus) || + SVNStatusType.STATUS_ADDED.equals(propertiesStatus) || SVNStatusType.STATUS_DELETED.equals(propertiesStatus) || + SVNStatusType.STATUS_MODIFIED.equals(propertiesStatus) || SVNStatusType.STATUS_REPLACED.equals(propertiesStatus) || + SVNStatusType.MERGED.equals(propertiesStatus)) { + + final FilePath path = ChangesUtil.getFilePath(change); + final File ioFile = path.getIOFile(); + final SVNWCClient wcClient = myVcs.createWCClient(); + final File beforeFile = deletedStatus != null ? deletedStatus.getFile() : ioFile; + final String beforeList = SVNStatusType.STATUS_ADDED.equals(propertiesStatus) && deletedStatus == null ? null : + AbstractShowPropertiesDiffAction.getPropertyList(beforeFile, SVNRevision.BASE, wcClient); + final String afterList = SVNStatusType.STATUS_DELETED.equals(propertiesStatus) ? null : + AbstractShowPropertiesDiffAction.getPropertyList(ioFile, SVNRevision.WORKING, wcClient); + + final String beforeRevisionNu = change.getBeforeRevision() == null ? null : change.getBeforeRevision().getRevisionNumber().asString(); + final String afterRevisionNu = change.getAfterRevision() == null ? null : change.getAfterRevision().getRevisionNumber().asString(); + + final Change propertyChange = new Change(beforeList == null ? null : new SimpleContentRevision(beforeList, path, beforeRevisionNu), + afterList == null ? null : new SimpleContentRevision(afterList, path, afterRevisionNu), + deletedStatus != null ? FileStatus.MODIFIED : SvnStatusConvertor.convertPropertyStatus(propertiesStatus)); + change.addAdditionalLayerElement(SvnChangeProvider.PROPERTY_LAYER, propertyChange); + } + return change; + } + private ConflictState getState(@Nullable final SVNStatus svnStatus) { if (svnStatus == null) { return ConflictState.none; } + final SVNStatusType propertiesStatus = svnStatus.getPropertiesStatus(); + final boolean treeConflict = svnStatus.getTreeConflict() != null; final boolean textConflict = SVNStatusType.STATUS_CONFLICTED == svnStatus.getContentsStatus(); - final boolean propertyConflict = SVNStatusType.STATUS_CONFLICTED == svnStatus.getPropertiesStatus(); + final boolean propertyConflict = SVNStatusType.STATUS_CONFLICTED == propertiesStatus; if (treeConflict) { reportTreeConflict(svnStatus); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnStatusConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnStatusConvertor.java index 222abce7ae16..6430f0731413 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnStatusConvertor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/SvnStatusConvertor.java @@ -25,6 +25,10 @@ public class SvnStatusConvertor { } public static FileStatus convertStatus(final SVNStatus status) throws SVNException { + return convertStatus(status, true); + } + + public static FileStatus convertStatus(final SVNStatus status, final boolean noticeProperties) throws SVNException { if (status == null) { return FileStatus.UNKNOWN; } @@ -53,9 +57,9 @@ public class SvnStatusConvertor { return SvnFileStatus.REPLACED; } else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED || - status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { + noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED && - status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { + noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { return FileStatus.MERGED_WITH_BOTH_CONFLICTS; } else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED) { return FileStatus.MERGED_WITH_CONFLICTS; @@ -63,7 +67,7 @@ public class SvnStatusConvertor { return FileStatus.MERGED_WITH_PROPERTY_CONFLICTS; } else if (status.getContentsStatus() == SVNStatusType.STATUS_MODIFIED || - status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) { + noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) { return FileStatus.MODIFIED; } else if (status.isSwitched()) { @@ -74,4 +78,49 @@ public class SvnStatusConvertor { } return FileStatus.NOT_CHANGED; } + + public static FileStatus convertPropertyStatus(final SVNStatusType status) throws SVNException { + return convertSingleStatus(status, FileStatus.MERGED_WITH_PROPERTY_CONFLICTS); + } + + public static FileStatus convertContentsStatus(final SVNStatus status) throws SVNException { + return convertStatus(status, false); + } + + private static FileStatus convertSingleStatus(final SVNStatusType status, final FileStatus defaultConflictStatus) throws SVNException { + if (status == null) { + return FileStatus.UNKNOWN; + } + if (SVNStatusType.STATUS_UNVERSIONED.equals(status)) { + return FileStatus.UNKNOWN; + } + else if (SVNStatusType.STATUS_MISSING.equals(status)) { + return FileStatus.DELETED_FROM_FS; + } + else if (SVNStatusType.STATUS_EXTERNAL.equals(status)) { + return SvnFileStatus.EXTERNAL; + } + else if (SVNStatusType.STATUS_OBSTRUCTED.equals(status)) { + return SvnFileStatus.OBSTRUCTED; + } + else if (SVNStatusType.STATUS_IGNORED.equals(status)) { + return FileStatus.IGNORED; + } + else if (SVNStatusType.STATUS_ADDED.equals(status)) { + return FileStatus.ADDED; + } + else if (SVNStatusType.STATUS_DELETED.equals(status)) { + return FileStatus.DELETED; + } + else if (SVNStatusType.STATUS_REPLACED.equals(status)) { + return SvnFileStatus.REPLACED; + } + else if (status == SVNStatusType.STATUS_CONFLICTED) { + return defaultConflictStatus; + } + else if (status == SVNStatusType.STATUS_MODIFIED) { + return FileStatus.MODIFIED; + } + return FileStatus.NOT_CHANGED; + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java index 0bca0eab303e..8c91cb2a524e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java @@ -55,7 +55,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -abstract class AbstractShowPropertiesDiffAction extends AnAction implements DumbAware { +public abstract class AbstractShowPropertiesDiffAction extends AnAction implements DumbAware { protected AbstractShowPropertiesDiffAction(String name) { super(name); } @@ -215,7 +215,7 @@ abstract class AbstractShowPropertiesDiffAction extends AnAction implements Dumb private final static String ourPropertiesDelimiter = "\n"; - private String getPropertyList(final ContentRevision contentRevision, final SVNRevision revision, final SVNWCClient client) throws SVNException { + private static String getPropertyList(final ContentRevision contentRevision, final SVNRevision revision, final SVNWCClient client) throws SVNException { if (contentRevision == null) { return ""; } @@ -224,13 +224,34 @@ abstract class AbstractShowPropertiesDiffAction extends AnAction implements Dumb final List lines = new ArrayList(); final File ioFile = contentRevision.getFile().getIOFile(); + final ISVNPropertyHandler propertyHandler = createHandler(revision, lines); + + if (contentRevision instanceof SvnRepositoryContentRevision) { + final SvnRepositoryContentRevision svnRevision = (SvnRepositoryContentRevision) contentRevision; + client.doGetProperty(SVNURL.parseURIEncoded(svnRevision.getFullPath()), null, revision, revision, SVNDepth.EMPTY, propertyHandler); + } else { + client.doGetProperty(ioFile, null, revision, revision, SVNDepth.EMPTY, propertyHandler, null); + } + + Collections.sort(lines, new Comparator() { + public int compare(final SVNPropertyData o1, final SVNPropertyData o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + for (SVNPropertyData line : lines) { + addPropertyPresentation(line, sb); + } + return sb.toString(); + } + + private static ISVNPropertyHandler createHandler(SVNRevision revision, final List lines) { final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); if (indicator != null) { indicator.checkCanceled(); indicator.setText(SvnBundle.message("show.properties.diff.progress.text.revision.information", revision.toString())); } - final ISVNPropertyHandler propertyHandler = new ISVNPropertyHandler() { + return new ISVNPropertyHandler() { public void handleProperty(final File path, final SVNPropertyData property) throws SVNException { if (indicator != null) { indicator.checkCanceled(); @@ -251,13 +272,15 @@ abstract class AbstractShowPropertiesDiffAction extends AnAction implements Dumb // revision properties here } }; + } - if (contentRevision instanceof SvnRepositoryContentRevision) { - final SvnRepositoryContentRevision svnRevision = (SvnRepositoryContentRevision) contentRevision; - client.doGetProperty(SVNURL.parseURIEncoded(svnRevision.getFullPath()), null, revision, revision, SVNDepth.EMPTY, propertyHandler); - } else { - client.doGetProperty(ioFile, null, revision, revision, SVNDepth.EMPTY, propertyHandler, null); - } + public static String getPropertyList(final SVNURL url, final SVNRevision revision, final SVNWCClient client) throws SVNException { + final StringBuilder sb = new StringBuilder(); + final List lines = new ArrayList(); + + final ISVNPropertyHandler propertyHandler = createHandler(revision, lines); + + client.doGetProperty(url, null, revision, revision, SVNDepth.EMPTY, propertyHandler); Collections.sort(lines, new Comparator() { public int compare(final SVNPropertyData o1, final SVNPropertyData o2) { @@ -271,7 +294,27 @@ abstract class AbstractShowPropertiesDiffAction extends AnAction implements Dumb return sb.toString(); } - private void addPropertyPresentation(final SVNPropertyData property, final StringBuilder sb) { + public static String getPropertyList(final File ioFile, final SVNRevision revision, final SVNWCClient client) throws SVNException { + final StringBuilder sb = new StringBuilder(); + final List lines = new ArrayList(); + + final ISVNPropertyHandler propertyHandler = createHandler(revision, lines); + + client.doGetProperty(ioFile, null, revision, revision, SVNDepth.EMPTY, propertyHandler, null); + + Collections.sort(lines, new Comparator() { + public int compare(final SVNPropertyData o1, final SVNPropertyData o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + for (SVNPropertyData line : lines) { + addPropertyPresentation(line, sb); + } + + return sb.toString(); + } + + private static void addPropertyPresentation(final SVNPropertyData property, final StringBuilder sb) { if (sb.length() != 0) { sb.append(ourPropertiesDelimiter); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/dialogs/PropertiesComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/dialogs/PropertiesComponent.java index 83acfaffbd42..057ed18452fc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/dialogs/PropertiesComponent.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/dialogs/PropertiesComponent.java @@ -28,10 +28,7 @@ import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.table.JBTable; import com.intellij.util.containers.HashMap; import org.jetbrains.idea.svn17.SvnVcs17; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNProperty; -import org.tmatesoft.svn.core.SVNPropertyValue; -import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -119,18 +116,18 @@ public class PropertiesComponent extends JPanel { myFile = file; myVcs = vcs; try { - vcs.createWCClient().doGetProperty(file, null, SVNRevision.UNDEFINED, SVNRevision.WORKING, false, new ISVNPropertyHandler() { + vcs.createWCClient().doGetProperty(file, null, SVNRevision.UNDEFINED, SVNRevision.WORKING, SVNDepth.EMPTY, new ISVNPropertyHandler() { public void handleProperty(File path, SVNPropertyData property) throws SVNException { final SVNPropertyValue value = property.getValue(); if (value != null) { - props.put(property.getName(), value.getString()); + props.put(property.getName(), SVNPropertyValue.getPropertyAsString(property.getValue())); } } public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException { } public void handleProperty(long revision, SVNPropertyData property) throws SVNException { } - }); + }, null); } catch (SVNException e) { props.clear(); } @@ -333,7 +330,7 @@ public class PropertiesComponent extends JPanel { recursive = dialog.isRecursive(); SVNWCClient wcClient = myVcs.createWCClient(); try { - wcClient.doSetProperty(myFile, name, SVNPropertyValue.create(value), false, recursive, null); + wcClient.doSetProperty(myFile, name, SVNPropertyValue.create(value), false, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, null, null); } catch (SVNException err) { // show error message diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java index e4cd8edf7a92..3a12a1efa815 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java @@ -23,13 +23,12 @@ package org.jetbrains.idea.svn17.history; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FilePathImpl; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.changes.ExternallyRenamedChange; +import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ConstantFunction; @@ -37,11 +36,13 @@ import com.intellij.util.NotNullFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn17.*; +import org.jetbrains.idea.svn17.actions.AbstractShowPropertiesDiffAction; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCClient; import java.io.DataInput; import java.io.DataOutput; @@ -74,6 +75,7 @@ public class SvnChangeList implements CommittedChangeList { private final Map myCopiedAddedPaths = new HashMap(); private RootUrlInfo myWcRoot; private final CommonPathSearcher myCommonPathSearcher; + private final Set myKnownAsDirectories; public SvnChangeList(@NotNull final List lists, @NotNull final SvnRepositoryLocation location) { @@ -94,6 +96,7 @@ public class SvnChangeList implements CommittedChangeList { myDeletedPaths.addAll(svnList.myDeletedPaths); myReplacedPaths.addAll(svnList.myReplacedPaths); } + myKnownAsDirectories = new HashSet(0); } public SvnChangeList(SvnVcs17 vcs, @NotNull final SvnRepositoryLocation location, final SVNLogEntry logEntry, String repositoryRoot) { @@ -110,10 +113,15 @@ public class SvnChangeList implements CommittedChangeList { myCommonPathSearcher = new CommonPathSearcher(); + myKnownAsDirectories = new HashSet(0); for(Object o: logEntry.getChangedPaths().values()) { final SVNLogEntryPath entry = (SVNLogEntryPath) o; final String path = entry.getPath(); + if (SVNNodeKind.DIR.equals(entry.getKind())) { + myKnownAsDirectories.add(path); + } + myCommonPathSearcher.next(path); if (entry.getType() == 'A') { @@ -149,6 +157,7 @@ public class SvnChangeList implements CommittedChangeList { for (String path : myChangedPaths) { myCommonPathSearcher.next(path); } + myKnownAsDirectories = new HashSet(0); } public Change getByPath(final String path) { @@ -284,6 +293,7 @@ public class SvnChangeList implements CommittedChangeList { } public void add(final String path, final Change change) { + patchChange(change, path); myList.add(change); myPathToChangeMapping.put(path, change); } @@ -310,15 +320,22 @@ public class SvnChangeList implements CommittedChangeList { } public SvnRepositoryContentRevision createRevisionLazily(final String path, final boolean isBeforeRevision) { - return SvnRepositoryContentRevision.create(myVcs, myRepositoryRoot, path, - getLocalPath(path, new NotNullFunction() { - @NotNull - public Boolean fun(final File file) { - // list will be next - myWithoutDirStatus.add(new Pair(myList.size(), isBeforeRevision)); - return Boolean.FALSE; - } - }), getRevision(isBeforeRevision)); + final boolean knownAsDirectory = myKnownAsDirectories.contains(path); + final FilePath localPath = getLocalPath(path, new NotNullFunction() { + @NotNull + public Boolean fun(final File file) { + if (knownAsDirectory) return Boolean.TRUE; + // list will be next + myWithoutDirStatus.add(new Pair(myList.size(), isBeforeRevision)); + return Boolean.FALSE; + } + }); + final SvnRepositoryContentRevision contentRevision = + SvnRepositoryContentRevision.create(myVcs, myRepositoryRoot, path, localPath, getRevision(isBeforeRevision)); + if (knownAsDirectory) { + ((FilePathImpl) contentRevision.getFile()).setIsDirectory(true); + } + return contentRevision; } public List getList() { @@ -433,6 +450,52 @@ public class SvnChangeList implements CommittedChangeList { } } + private void patchChange(Change change, final String path) { + final SVNURL becameUrl; + SVNURL wasUrl; + try { + becameUrl = SVNURL.parseURIEncoded(SVNPathUtil.append(myRepositoryRoot, path)); + wasUrl = becameUrl; + + if (change instanceof ExternallyRenamedChange && change.getBeforeRevision() != null) { + final ExternallyRenamedChange renamedChange = (ExternallyRenamedChange)change; + final String originUrl = renamedChange.getOriginUrl(); + if (originUrl != null) { + // use another url for origin + wasUrl = SVNURL.parseURIEncoded(SVNPathUtil.append(myRepositoryRoot, originUrl)); + } + } + } + catch (SVNException e) { + // nothing to do + LOG.info(e); + return; + } + + final FilePath filePath = ChangesUtil.getFilePath(change); + final SimpleContentRevision before = createRevisionForProperty(wasUrl, change.getBeforeRevision(), filePath); + final SimpleContentRevision after = createRevisionForProperty(becameUrl, change.getAfterRevision(), filePath); + final String beforeText = before == null ? null : before.getContent(); + final String afterText = after == null ? null : after.getContent(); + if (Comparing.equal(beforeText, afterText)) return; + final Change additional = new Change(before, after); + change.addAdditionalLayerElement(SvnChangeProvider.PROPERTY_LAYER, additional); + } + + private SimpleContentRevision createRevisionForProperty(final SVNURL url, final ContentRevision changeRevision, final FilePath newPath) { + if (changeRevision == null) return null; + final SVNWCClient client = myVcs.createWCClient(); + String list; + try { + list = + AbstractShowPropertiesDiffAction.getPropertyList(url, ((SvnRevisionNumber)changeRevision.getRevisionNumber()).getRevision(), client); + } + catch (SVNException e) { + list = "Can not get properties: " + e.getMessage(); + } + return new SimpleContentRevision(list, newPath, changeRevision.getRevisionNumber().asString()); + } + @NotNull public String getName() { return myMessage; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnCommittedChangesProvider.java index a846fefba253..7d2b348201f0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnCommittedChangesProvider.java @@ -580,7 +580,7 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi for (Object o : changedPaths.values()) { final SVNLogEntryPath entryPath = (SVNLogEntryPath) o; - if (entryPath != null && 'A' == entryPath.getType()) { + if (entryPath != null && 'A' == entryPath.getType() && entryPath.getCopyPath() != null) { if (myCurrentPath.equals(entryPath.getPath())) { myHadChanged = true; myCurrentPath = entryPath.getCopyPath(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/properties/SvnPropDetailsProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/properties/SvnPropDetailsProvider.java new file mode 100644 index 000000000000..1a596fdfe367 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/properties/SvnPropDetailsProvider.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2012 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 org.jetbrains.idea.svn17.properties; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/12/12 + * Time: 8:40 PM + */ +public class SvnPropDetailsProvider { +} diff --git a/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java index a771a6866dda..c6dcf626802d 100644 --- a/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java @@ -591,7 +591,7 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi for (Object o : changedPaths.values()) { final SVNLogEntryPath entryPath = (SVNLogEntryPath) o; - if (entryPath != null && 'A' == entryPath.getType()) { + if (entryPath != null && 'A' == entryPath.getType() && entryPath.getCopyPath() != null) { if (myCurrentPath.equals(entryPath.getPath())) { myHadChanged = true; myCurrentPath = entryPath.getCopyPath(); diff --git a/plugins/testng/lib/src/testng.zip b/plugins/testng/lib/src/testng.zip index e510ff8091c5..c20697953852 100644 Binary files a/plugins/testng/lib/src/testng.zip and b/plugins/testng/lib/src/testng.zip differ diff --git a/plugins/testng/lib/testng-jdk15.jar b/plugins/testng/lib/testng-jdk15.jar index 8f7d5f46cc4c..505188be0e5d 100644 Binary files a/plugins/testng/lib/testng-jdk15.jar and b/plugins/testng/lib/testng-jdk15.jar differ