diff: Add option to reduce diff granularity and to turn diff highlighting off.
authorAleksey Pivovarov <Aleksey.Pivovarov@jetbrains.com>
Mon, 3 Feb 2014 10:31:12 +0000 (14:31 +0400)
committerAleksey Pivovarov <Aleksey.Pivovarov@jetbrains.com>
Mon, 3 Feb 2014 12:35:03 +0000 (16:35 +0400)
platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/SimpleDiffPanelState.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/processing/TextCompareProcessor.java
platform/platform-resources-en/src/messages/CommonBundle.properties
platform/platform-resources-en/src/messages/DiffBundle.properties
platform/platform-resources/src/idea/PlatformActions.xml
platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java [new file with mode: 0644]

diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java
new file mode 100644 (file)
index 0000000..06e25a9
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000-2014 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.actions;
+
+import com.intellij.CommonBundle;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
+import com.intellij.openapi.diff.DiffBundle;
+import com.intellij.openapi.diff.ex.DiffPanelEx;
+import com.intellij.openapi.diff.impl.DiffPanelImpl;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Map;
+
+public class HighlightModeAction extends ComboBoxAction implements DumbAware {
+  private final Map<HighlightMode, AnAction> myActions = new HashMap<HighlightMode, AnAction>();
+  private static final HighlightMode[] ourActionOrder =
+    new HighlightMode[]{HighlightMode.BY_WORD, HighlightMode.BY_LINE, HighlightMode.NO_HIGHLIGHTING};
+
+  public HighlightModeAction() {
+    myActions.put(HighlightMode.BY_WORD,
+                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.word"), HighlightMode.BY_WORD));
+    myActions.put(HighlightMode.BY_LINE,
+                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.by.line"), HighlightMode.BY_LINE));
+    myActions.put(HighlightMode.NO_HIGHLIGHTING,
+                  new SetHighlightModeAction(DiffBundle.message("diff.acton.highlight.mode.action.no.highlighting"),
+                                             HighlightMode.NO_HIGHLIGHTING));
+  }
+
+  @Override
+  public JComponent createCustomComponent(final Presentation presentation) {
+    JPanel panel = new JPanel(new BorderLayout());
+    final JLabel label = new JLabel(CommonBundle.message("diff.acton.highlight.mode.action.name"));
+    label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
+    panel.add(label, BorderLayout.WEST);
+    panel.add(super.createCustomComponent(presentation), BorderLayout.CENTER);
+    return panel;
+  }
+
+  @NotNull
+  protected DefaultActionGroup createPopupActionGroup(JComponent button) {
+    DefaultActionGroup actionGroup = new DefaultActionGroup();
+    for (HighlightMode comparisonPolicy : ourActionOrder) {
+      actionGroup.add(myActions.get(comparisonPolicy));
+    }
+    return actionGroup;
+  }
+
+  public void update(AnActionEvent e) {
+    super.update(e);
+    Presentation presentation = e.getPresentation();
+    DiffPanelEx diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
+    if (diffPanel != null && diffPanel.getComponent().isDisplayable()) {
+      AnAction action = myActions.get(diffPanel.getHighlightMode());
+      Presentation templatePresentation = action.getTemplatePresentation();
+      presentation.setIcon(templatePresentation.getIcon());
+      presentation.setText(templatePresentation.getText());
+      presentation.setEnabled(true);
+    }
+    else {
+      presentation.setIcon(null);
+      presentation.setText(DiffBundle.message("diff.acton.highlight.mode.not.available.action.name"));
+      presentation.setEnabled(false);
+    }
+  }
+
+  private static class SetHighlightModeAction extends AnAction implements DumbAware {
+    private final HighlightMode myHighlightMode;
+
+    public SetHighlightModeAction(String text, HighlightMode mode) {
+      super(text);
+      myHighlightMode = mode;
+    }
+
+    public void actionPerformed(AnActionEvent e) {
+      final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
+      if (diffPanel != null) {
+        diffPanel.setHighlightMode(myHighlightMode);
+      }
+    }
+  }
+}
index c3bf682ab9f71508d57d13b83e21ad57914b271e..933d017be2ef9b458c199931c2750cacc197f57d 100644 (file)
@@ -27,6 +27,7 @@ package com.intellij.openapi.diff.ex;
 import com.intellij.openapi.Disposable;
 import com.intellij.openapi.diff.DiffPanel;
 import com.intellij.openapi.diff.impl.ComparisonPolicy;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
 import com.intellij.openapi.editor.Editor;
 import org.jetbrains.annotations.Nullable;
 
@@ -45,4 +46,8 @@ public interface DiffPanelEx extends DiffPanel, Disposable {
   void setAutoScrollEnabled(boolean enabled);
 
   boolean isAutoScrollEnabled();
+
+  void setHighlightMode(HighlightMode highlightMode);
+
+  HighlightMode getHighlightMode();
 }
index 37b9438522b279c1dde9fde6ba309ab2f49b7aee..913d5e7cc8f914e22754e208af21c7acb5ee8c03 100644 (file)
@@ -34,6 +34,7 @@ import com.intellij.openapi.diff.impl.fragments.Fragment;
 import com.intellij.openapi.diff.impl.fragments.FragmentList;
 import com.intellij.openapi.diff.impl.highlighting.DiffPanelState;
 import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
 import com.intellij.openapi.diff.impl.processing.HorizontalDiffSplitter;
 import com.intellij.openapi.diff.impl.settings.DiffMergeEditorSetting;
 import com.intellij.openapi.diff.impl.settings.DiffMergeSettings;
@@ -483,6 +484,15 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
     setComparisonPolicy(comparisonPolicy, true);
   }
 
+  public void setHighlightMode(HighlightMode highlightMode) {
+    myData.setHighlightMode(highlightMode);
+    rediff();
+  }
+
+  public HighlightMode getHighlightMode() {
+    return myData.getHighlightMode();
+  }
+
   public Rediffers getDiffUpdater() {
     return myDiffUpdater;
   }
index 5446f66e50c60ffba845f6c22060fe716e079fa7..d90005d7067869da3c08bb44db9235e3293cec57 100644 (file)
@@ -24,6 +24,7 @@ import com.intellij.openapi.diff.impl.fragments.FragmentList;
 import com.intellij.openapi.diff.impl.fragments.FragmentListImpl;
 import com.intellij.openapi.diff.impl.fragments.LineFragment;
 import com.intellij.openapi.diff.impl.processing.DiffPolicy;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
 import com.intellij.openapi.diff.impl.processing.TextCompareProcessor;
 import com.intellij.openapi.diff.impl.splitter.LineBlocks;
 import com.intellij.openapi.project.Project;
@@ -37,6 +38,7 @@ import java.util.Iterator;
 public abstract class SimpleDiffPanelState implements Disposable  {
   protected ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT;
   protected DiffPolicy myDiffPolicy;
+  protected HighlightMode myHighlightMode;
   protected final EditorPlaceHolder myAppender1;
   protected final EditorPlaceHolder myAppender2;
   protected FragmentList myFragmentList = FragmentList.EMPTY;
@@ -47,6 +49,7 @@ public abstract class SimpleDiffPanelState implements Disposable  {
     myAppender2 = createEditorWrapper(project, changeListener, FragmentSide.SIDE2);
     myProject = project;
     myDiffPolicy = DiffPolicy.LINES_WO_FORMATTING;
+    myHighlightMode = HighlightMode.BY_WORD;
     Disposer.register(parentDisposable, this);
   }
 
@@ -72,6 +75,14 @@ public abstract class SimpleDiffPanelState implements Disposable  {
     return myComparisonPolicy;
   }
 
+  public HighlightMode getHighlightMode() {
+    return myHighlightMode;
+  }
+
+  public void setHighlightMode(HighlightMode highlightMode) {
+    myHighlightMode = highlightMode;
+  }
+
   public void dispose() {
   }
 
@@ -105,7 +116,12 @@ public abstract class SimpleDiffPanelState implements Disposable  {
       return LineBlocks.EMPTY;
     }
 
-    return addMarkup(new TextCompareProcessor(myComparisonPolicy, myDiffPolicy).process(myAppender1.getText(), myAppender2.getText()));
+    if (myHighlightMode == HighlightMode.NO_HIGHLIGHTING) {
+      return LineBlocks.fromLineFragments(new ArrayList<LineFragment>());
+    }
+
+    return addMarkup(new TextCompareProcessor(myComparisonPolicy, myDiffPolicy, myHighlightMode == HighlightMode.BY_WORD)
+                       .process(myAppender1.getText(), myAppender2.getText()));
   }
 
   public Project getProject() { return myProject; }
index 1555656c3865745909033ff61175944aaf765a34..01534b487ff58e9e824c6bc955281a7a71e8bfe6 100644 (file)
@@ -32,28 +32,38 @@ public class TextCompareProcessor {
   private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.processing.Processor");
   private final DiffPolicy myDiffPolicy;
   @NotNull private final ComparisonPolicy myComparisonPolicy;
+  private final boolean mySearchForSubFragments;
 
-  public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) {
+  public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy,
+                              final DiffPolicy diffPolicy,
+                              boolean searchForSubFragments) {
     myComparisonPolicy = comparisonPolicy;
     myDiffPolicy = diffPolicy;
+    mySearchForSubFragments = searchForSubFragments;
+  }
+
+  public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) {
+    this(comparisonPolicy, diffPolicy, true);
   }
 
-  public TextCompareProcessor(ComparisonPolicy comparisonPolicy) {
+  public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy) {
     this(comparisonPolicy, DiffPolicy.LINES_WO_FORMATTING);
   }
 
   public ArrayList<LineFragment> process(String text1, String text2) throws FilesTooBigForDiffException {
     DiffFragment[] woFormattingBlocks = myDiffPolicy.buildFragments(text1, text2);
-    DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).
-        correctAndNormalize(woFormattingBlocks);
+    DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).correctAndNormalize(woFormattingBlocks);
     ArrayList<LineFragment> lineBlocks = new DiffFragmentsProcessor().process(step1lineFragments);
-    for (LineFragment lineBlock : lineBlocks) {
-      if (lineBlock.isOneSide() || lineBlock.isEqual()) continue;
-      String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1);
-      String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2);
-      ArrayList<LineFragment> subFragments = findSubFragments(subText1, subText2);
-      lineBlock.setChildren(new ArrayList<Fragment>(subFragments));
-      lineBlock.adjustTypeFromChildrenTypes();
+
+    if (mySearchForSubFragments) {
+      for (LineFragment lineBlock : lineBlocks) {
+        if (lineBlock.isOneSide() || lineBlock.isEqual()) continue;
+        String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1);
+        String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2);
+        ArrayList<LineFragment> subFragments = findSubFragments(subText1, subText2);
+        lineBlock.setChildren(new ArrayList<Fragment>(subFragments));
+        lineBlock.adjustTypeFromChildrenTypes();
+      }
     }
     return lineBlocks;
   }
index a07d1631bad558a381c7d4ec95f3e6a194a6f7ed..e027bc32a12da2ed099ac3578cae00af625004fc 100644 (file)
@@ -175,4 +175,5 @@ This may lead to incorrect behaviour. Proxy should be set in Settings | HTTP Pro
 This JVM property is old and its usage is not recommended by Oracle.\n\
 \n(Note: It could have been assigned by some code dynamically.)
 label.proxy.exceptions.text=Example\: *.domain.com, 192.168.*
-checkbox.automatic.proxy.configuration.url=Automatic proxy configuration URL\:
\ No newline at end of file
+checkbox.automatic.proxy.configuration.url=Automatic proxy configuration URL\:
+diff.acton.highlight.mode.action.name=Highlighting Mode
\ No newline at end of file
index cb6a0d72819bab0b033f2eef86d722f1acf913a9..b0515df7f6f269446fee4407a371e5a636c7269b 100644 (file)
@@ -83,3 +83,7 @@ diff.content.selected.value=Selected Value
 diff.clipboard.vs.value.dialog.title=Clipboard vs Selected Value
 
 diff.can.not.show.unknown=Can not show diff for unknown file type
+diff.acton.highlight.mode.action.by.word=By Word
+diff.acton.highlight.mode.action.by.line=By Line
+diff.acton.highlight.mode.action.no.highlighting=No Highlighting
+diff.acton.highlight.mode.not.available.action.name=<Not available>
index c2e5c4aafaacd55724beca4159a0c717d6eed9ea..ab70a8603df4f49cae8a91974d3205eb7ee4094d 100644 (file)
       <reference ref="NextDiff"/>
       <separator/>
       <action id="Diff.IgnoreWhitespace" class="com.intellij.openapi.diff.actions.IgnoreWhiteSpacesAction" text=""/>
+      <separator/>
+      <action id="Diff.HighlightMode" class="com.intellij.openapi.diff.actions.HighlightModeAction" text=""/>
     </group>
 
     <group id="ChangeScheme">
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java
new file mode 100644 (file)
index 0000000..441aca3
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2000-2014 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.processing;
+
+public enum HighlightMode {
+  BY_WORD, BY_LINE, NO_HIGHLIGHTING
+}