diff: add option to enable align changes in side by side diff
authorDmitry Zhuravlev <dmitry.zhuravlev@jetbrains.com>
Thu, 30 Sep 2021 17:19:54 +0000 (20:19 +0300)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Fri, 1 Oct 2021 15:06:07 +0000 (15:06 +0000)
GitOrigin-RevId: 16f516bebd89b4bdeb2b5857510033d61de2c7fc

platform/diff-api/src/com/intellij/diff/util/DiffUserDataKeys.java
platform/diff-impl/src/com/intellij/diff/actions/impl/ToggleDiffAligningModeAction.kt [new file with mode: 0644]
platform/diff-impl/src/com/intellij/diff/statistics/DiffUsagesCollector.kt
platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleAlignedDiffModel.kt
platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java
platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffSettingsHolder.kt
platform/platform-resources-en/src/messages/ActionsBundle.properties
platform/vcs-impl/resources/META-INF/VcsActions.xml

index 6b92662d7cfb1fcf20f9fc4dd0047c243f2f6b94..db00b3a5c2be68567f9d227bb036f35e604d2353 100644 (file)
@@ -136,5 +136,11 @@ public interface DiffUserDataKeys {
    */
   Key<Boolean> MERGE_EDITOR_FLAG = Key.create("Diff.mergeEditor");
 
+  /**
+   * Force aligning changes in side-by-side viewer.<br/>
+   * This can be used in viewers, where aligning is critical (e.g. {@link com.intellij.diff.tools.combined.CombinedDiffViewer}).
+   *
+   * @see com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings#isEnableAligningChangesMode
+   */
   Key<Boolean> ALIGNED_TWO_SIDED_DIFF = Key.create("Diff.AlignTwoSidedDiff");
 }
diff --git a/platform/diff-impl/src/com/intellij/diff/actions/impl/ToggleDiffAligningModeAction.kt b/platform/diff-impl/src/com/intellij/diff/actions/impl/ToggleDiffAligningModeAction.kt
new file mode 100644 (file)
index 0000000..7e79c1d
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.diff.actions.impl
+
+import com.intellij.diff.tools.simple.SimpleDiffViewer
+import com.intellij.diff.tools.util.DiffDataKeys.DIFF_VIEWER
+import com.intellij.diff.tools.util.base.TextDiffViewerUtil
+import com.intellij.diff.util.DiffUserDataKeys.ALIGNED_TWO_SIDED_DIFF
+import com.intellij.diff.util.DiffUtil
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.project.DumbAwareToggleAction
+
+class ToggleDiffAligningModeAction : DumbAwareToggleAction() {
+
+  override fun update(e: AnActionEvent) {
+    val viewer = e.getData(DIFF_VIEWER)
+    val available = e.project != null
+                    && viewer is SimpleDiffViewer
+                    && !DiffUtil.isUserDataFlagSet(ALIGNED_TWO_SIDED_DIFF, viewer.request)
+    if (!available) {
+      e.presentation.isEnabledAndVisible = available
+      return
+    }
+
+    super.update(e)
+  }
+
+  override fun isSelected(e: AnActionEvent): Boolean {
+    val viewer = e.getData(DIFF_VIEWER) as SimpleDiffViewer
+    return TextDiffViewerUtil.getTextSettings(viewer.context).isEnableAligningChangesMode
+  }
+
+  override fun setSelected(e: AnActionEvent, state: Boolean) {
+    val viewer = e.getData(DIFF_VIEWER) as SimpleDiffViewer
+
+    TextDiffViewerUtil.getTextSettings(viewer.context).isEnableAligningChangesMode = state
+    viewer.rediff()
+  }
+}
index 20075d16cd069e5fce201b7ad324490a493013e9..7ec270507665aa49cc1ac73b2fa93fcfa119426a 100644 (file)
@@ -33,6 +33,7 @@ class DiffUsagesCollector : ApplicationUsagesCollector() {
 
     private val DIFF_PLACE = EventFields.String("diff_place", places)
     private val SYNC_SCROLL = GROUP.registerVarargEvent("sync.scroll", DIFF_PLACE, EventFields.Enabled)
+    private val ALIGNED_CHANGES = GROUP.registerVarargEvent("aligned.changes", DIFF_PLACE, EventFields.Enabled)
     private val IGNORE_POLICY_VALUE = EventFields.Enum("value", IgnorePolicy::class.java)
     private val IGNORE_POLICY = GROUP.registerVarargEvent("ignore.policy", DIFF_PLACE, IGNORE_POLICY_VALUE)
     private val HIGHLIGHT_POLICY_VALUE = EventFields.Enum("value", HighlightPolicy::class.java)
@@ -63,7 +64,6 @@ class DiffUsagesCollector : ApplicationUsagesCollector() {
   override fun getMetrics(): Set<MetricEvent> {
     val set = HashSet<MetricEvent>()
 
-
     for (place in places) {
       val data: MutableList<EventPair<*>> = mutableListOf(DIFF_PLACE.with(place))
 
@@ -74,6 +74,7 @@ class DiffUsagesCollector : ApplicationUsagesCollector() {
       val defaultTextSettings = TextDiffSettings.getDefaultSettings(place)
 
       addBoolIfDiffers(set, textSettings, defaultTextSettings, { it.isEnableSyncScroll }, SYNC_SCROLL, data)
+      addBoolIfDiffers(set, textSettings, defaultTextSettings, { it.isEnableAligningChangesMode }, ALIGNED_CHANGES, data)
       addIfDiffers(set, textSettings, defaultTextSettings, { it.ignorePolicy }, IGNORE_POLICY, IGNORE_POLICY_VALUE, data)
       addIfDiffers(set, textSettings, defaultTextSettings, { it.highlightPolicy }, HIGHLIGHT_POLICY, HIGHLIGHT_POLICY_VALUE, data)
       addIfDiffers(set, textSettings, defaultTextSettings, { it.highlightingLevel }, SHOW_WARNINGS_POLICY, HIGHLIGHTING_LEVEL_VALUE,
index 714351521c8f53863ef863209e33ef8cf3a2ac16..164b9ca1a0e2d8042a92b09dd67dd3c85c55fe48 100644 (file)
@@ -33,11 +33,9 @@ class SimpleAlignedDiffModel(private val viewer: SimpleDiffViewer) {
   private val inlayHighlighters = mutableMapOf<Side, MutableList<RangeHighlighter>>()
 
   init {
-    if (viewer.needAlignChanges()) {
-      val inlayListener = MyInlayModelListener()
-      viewer.getEditor(Side.LEFT).inlayModel.addListener(inlayListener, viewer)
-      viewer.getEditor(Side.RIGHT).inlayModel.addListener(inlayListener, viewer)
-    }
+    val inlayListener = MyInlayModelListener()
+    viewer.getEditor(Side.LEFT).inlayModel.addListener(inlayListener, viewer)
+    viewer.getEditor(Side.RIGHT).inlayModel.addListener(inlayListener, viewer)
   }
 
   fun alignChange(change: SimpleDiffChange) {
@@ -155,6 +153,7 @@ class SimpleAlignedDiffModel(private val viewer: SimpleDiffViewer) {
   private enum class ProcessType { ADDED, REMOVED, HEIGHT_UPDATED }
 
   private fun processInlay(inlay: Inlay<*>, processType: ProcessType) {
+    if (!viewer.needAlignChanges()) return
     if (inlay.renderer is BaseAlignDiffInlayPresentation) return //skip self
 
     val inlayLine = inlay.logicalLine
index 81d947697f97bd733faad15c461937ae80bc3d90..5360a4a11121d2ffe54eef092d9f65ad46e7ffa4 100644 (file)
@@ -171,7 +171,8 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
   }
 
   boolean needAlignChanges() {
-    return Boolean.TRUE.equals(myRequest.getUserData(DiffUserDataKeys.ALIGNED_TWO_SIDED_DIFF));
+    return Boolean.TRUE.equals(myRequest.getUserData(DiffUserDataKeys.ALIGNED_TWO_SIDED_DIFF))
+           || getTextSettings().isEnableAligningChangesMode();
   }
 
   @NotNull
index 4a4185570db4afe6afab68f06a602f915522819d..6a6098abe50927efed92a71818cc44622310b538 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 package com.intellij.diff.tools.util.base
 
 import com.intellij.diff.tools.util.breadcrumbs.BreadcrumbsPlacement
@@ -27,7 +27,8 @@ class TextDiffSettingsHolder : PersistentStateComponent<TextDiffSettingsHolder.S
     var CONTEXT_RANGE: Int = 4,
 
     var MERGE_AUTO_APPLY_NON_CONFLICTED_CHANGES: Boolean = false,
-    var MERGE_LST_GUTTER_MARKERS: Boolean = true
+    var MERGE_LST_GUTTER_MARKERS: Boolean = true,
+    var ENABLE_ALIGNING_CHANGES_MODE: Boolean = false
   )
 
   data class PlaceSettings(
@@ -64,6 +65,10 @@ class TextDiffSettingsHolder : PersistentStateComponent<TextDiffSettingsHolder.S
 
     var isEnableSyncScroll: Boolean = true
 
+    var isEnableAligningChangesMode: Boolean
+      get() = SHARED_SETTINGS.ENABLE_ALIGNING_CHANGES_MODE
+      set(value) { SHARED_SETTINGS.ENABLE_ALIGNING_CHANGES_MODE = value }
+
     // Diff settings
 
     var highlightPolicy: HighlightPolicy = PLACE_SETTINGS.HIGHLIGHT_POLICY
@@ -201,4 +206,4 @@ class TextDiffSettingsHolder : PersistentStateComponent<TextDiffSettingsHolder.S
   override fun loadState(state: State) {
     myState = state
   }
-}
\ No newline at end of file
+}
index 9d49ff52330ada12b9a2f55eda0c73020eec44d3..99f5b85d7ab4f98a5d13eb0a7f5b5338f9371792 100644 (file)
@@ -1310,6 +1310,9 @@ action.Vcs.Diff.ShowDiffInEditorTab.text=Show Diff in Editor Tab
 action.Vcs.Diff.ShowDiffInNewWindow.text=Show Diff in Separate Window
 action.Vcs.Diff.ShowCombinedDiff.text=Show Combined Diff
 action.Vcs.Diff.ShowCombinedDiff.description=Show diff for all selected changes in one place
+action.Vcs.Diff.ToggleDiffAligningMode.text=Align Changes In Side-by-Side Diff
+action.Vcs.Diff.ToggleDiffAligningMode.popup@DiffToolbar.text=Align Changes Highlighting
+action.Vcs.Diff.ToggleDiffAligningMode.description=Turn on changes alignment for two-sided diff
 action.Vcs.RollbackChangedLines.text=Rollback Lines
 action.Vcs.RollbackChangedLines.description=Rollback changes in selected lines
 action.openAssertEqualsDiff.text=View assertEquals Difference
@@ -2529,4 +2532,4 @@ small.spacer=small spacer
 big.spacer=big spacer
 
 
-action.ListPersistentStateComponents.text=List Persistent State Components
\ No newline at end of file
+action.ListPersistentStateComponents.text=List Persistent State Components
index ab8473e9faedc3c461c2a143f9a658b12257ac4e..e34b39dcbf5312611bf101e2d725ed9b697e1a1b 100644 (file)
       <add-to-group group-id="Diff.EditorGutterPopupMenu.EditorSettings" anchor="last"/>
       <add-to-group group-id="Diff.Binary.Settings" anchor="last"/>
     </action>
+    <action id="Vcs.Diff.ToggleDiffAligningMode" class="com.intellij.diff.actions.impl.ToggleDiffAligningModeAction">
+      <add-to-group group-id="Diff.EditorGutterPopupMenu.EditorSettings"/>
+      <override-text place="popup@DiffToolbar"/>
+    </action>
     <group>
       <action id="Vcs.Diff.ShowDiffInNewWindow"
               icon="AllIcons.Actions.MoveToWindow"