diff --git a/platform/diff-api/resources/messages/DiffBundle.properties b/platform/diff-api/resources/messages/DiffBundle.properties
index b3b6eaa4cdc0..d532d42bf6e9 100644
--- a/platform/diff-api/resources/messages/DiffBundle.properties
+++ b/platform/diff-api/resources/messages/DiffBundle.properties
@@ -74,8 +74,10 @@ apply.somehow.status.message.cant.apply.some=Cannot apply {0, number} of {1, num
merge.dialog.apply.partially.resolved.changes.confirmation.message=There {0, choice, 0#'{1, choice, 1#is|2#are}'|1#is|2#are} {0, choice, 0#|1#one change|2#{0, number} changes}{0, choice, 0#|1#'{1, choice, 0#|1# and }'}{1, choice, 0#|1#one conflict|2#{1, number} conflicts} left unprocessed.\nSave changes and mark the conflict resolved anyway?
apply.patch.partially.resolved.changes.confirmation.message=There {0, choice, 1#is one hunk|2#are {0, number} hunks} left unprocessed.\nSave changes and finish resolve?
apply.partially.resolved.merge.dialog.title=Apply Changes
-merge.all.changes.processed.message.text=All changes have been processed.
Save changes and finish merging
-apply.patch.all.changes.processed.message.text=All hunks have been processed.
Save changes and finish resolve
+merge.all.changes.processed.title.text=All changes have been processed
+merge.all.changes.processed.message.text=Save changes and finish merging
+apply.patch.all.changes.processed.title.text=All hunks have been processed
+apply.patch.all.changes.processed.message.text=Save changes and finish resolve
merge.save.and.finish.button=Save and &Finish
merge.continue.button=&Continue
merge.color.options.background.color.label=Important
diff --git a/platform/diff-impl/src/com/intellij/diff/merge/MergeThreesideViewer.java b/platform/diff-impl/src/com/intellij/diff/merge/MergeThreesideViewer.java
index f69ddf902897..031429aba605 100644
--- a/platform/diff-impl/src/com/intellij/diff/merge/MergeThreesideViewer.java
+++ b/platform/diff-impl/src/com/intellij/diff/merge/MergeThreesideViewer.java
@@ -58,10 +58,7 @@ import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageDialogBuilder;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.ex.Range;
@@ -78,6 +75,7 @@ import com.intellij.util.concurrency.annotations.RequiresEdt;
import com.intellij.util.concurrency.annotations.RequiresWriteLock;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.util.XmlStringUtil;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import org.jetbrains.annotations.ApiStatus;
@@ -717,8 +715,9 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
JComponent component = getEditor().getComponent();
RelativePoint point = new RelativePoint(component, new Point(component.getWidth() / 2, JBUIScale.scale(5)));
- String message = DiffBundle.message("merge.all.changes.processed.message.text");
- DiffUtil.showSuccessPopup(message, point, this, () -> {
+ String title = DiffBundle.message("merge.all.changes.processed.title.text");
+ @NlsSafe String message = XmlStringUtil.wrapInHtmlTag(DiffBundle.message("merge.all.changes.processed.message.text"), "a");
+ DiffBalloons.showSuccessPopup(title, message, point, this, () -> {
if (isDisposed() || myLoadingPanel.isLoading()) return;
destroyChangedBlocks();
myMergeContext.finishMerge(MergeResult.RESOLVED);
diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffBalloons.kt b/platform/diff-impl/src/com/intellij/diff/util/DiffBalloons.kt
new file mode 100644
index 000000000000..7608879d64d7
--- /dev/null
+++ b/platform/diff-impl/src/com/intellij/diff/util/DiffBalloons.kt
@@ -0,0 +1,93 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.diff.util
+
+import com.intellij.icons.AllIcons
+import com.intellij.icons.ExpUiIcons
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.ui.popup.Balloon
+import com.intellij.openapi.ui.popup.JBPopupFactory
+import com.intellij.openapi.util.Disposer
+import com.intellij.openapi.util.NlsContexts
+import com.intellij.ui.ExperimentalUI
+import com.intellij.ui.awt.RelativePoint
+import com.intellij.ui.dsl.builder.HyperlinkEventAction
+import com.intellij.ui.dsl.builder.panel
+import com.intellij.ui.dsl.gridLayout.UnscaledGaps
+import com.intellij.ui.dsl.gridLayout.UnscaledGapsY
+import com.intellij.util.ui.EmptyIcon
+import com.intellij.util.ui.JBUI
+import java.awt.Color
+import javax.swing.Icon
+
+object DiffBalloons {
+ @JvmStatic
+ fun showSuccessPopup(title: @NlsContexts.PopupContent String,
+ message: @NlsContexts.PopupContent String,
+ point: RelativePoint,
+ disposable: Disposable,
+ hyperlinkHandler: Runnable) {
+ createAndShowBalloon(
+ title, message,
+ if (ExperimentalUI.isNewUI()) ExpUiIcons.Status.Success else null,
+ JBUI.CurrentTheme.Editor.Tooltip.SUCCESS_BACKGROUND,
+ JBUI.CurrentTheme.Editor.Tooltip.SUCCESS_BORDER,
+ point,
+ disposable,
+ HyperlinkEventAction { hyperlinkHandler.run() }
+ )
+ }
+
+ @JvmStatic
+ fun showWarningPopup(title: @NlsContexts.PopupContent String,
+ message: @NlsContexts.PopupContent String,
+ point: RelativePoint,
+ disposable: Disposable
+ ) {
+ createAndShowBalloon(
+ title, message,
+ if (ExperimentalUI.isNewUI()) ExpUiIcons.Status.Warning else AllIcons.General.Warning,
+ JBUI.CurrentTheme.Editor.Tooltip.WARNING_BACKGROUND,
+ JBUI.CurrentTheme.Editor.Tooltip.WARNING_BORDER,
+ point,
+ disposable
+ )
+ }
+
+ private fun createAndShowBalloon(
+ title: @NlsContexts.PopupContent String,
+ message: @NlsContexts.PopupContent String,
+ icon: Icon?,
+ fillColor: Color,
+ borderColor: Color,
+ point: RelativePoint,
+ disposable: Disposable,
+ listener: HyperlinkEventAction? = null
+ ) {
+ val balloonContent = panel {
+ val gap = 6
+ row {
+ if (icon!= null) {
+ icon(icon).customize(UnscaledGaps(right = gap, bottom = gap))
+ }
+ text(title).bold().customize(UnscaledGaps(bottom = gap))
+ }.customize(UnscaledGapsY.EMPTY)
+ row {
+ if (icon!= null) {
+ icon(EmptyIcon.create(icon)).customize(UnscaledGaps(right = gap))
+ }
+ text(message, action = listener ?: HyperlinkEventAction.HTML_HYPERLINK_INSTANCE).customize(UnscaledGaps.EMPTY)
+ }
+ }.andTransparent()
+
+ val balloon = JBPopupFactory.getInstance()
+ .createBalloonBuilder(balloonContent)
+ .setBorderInsets(JBUI.insets(12, 13, 12, 21))
+ .setFillColor(fillColor)
+ .setBorderColor(borderColor)
+ .setAnimationCycle(200)
+ .createBalloon()
+ balloon.show(point, Balloon.Position.below)
+
+ Disposer.register(disposable, balloon)
+ }
+}
\ No newline at end of file
diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java
index f67ad062a2ba..b5d2d66f3f41 100644
--- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java
+++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java
@@ -68,10 +68,7 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.DialogWrapperDialog;
-import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.WindowWrapper;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.HtmlBuilder;
@@ -90,7 +87,6 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.ui.*;
-import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.panels.VerticalLayout;
@@ -110,8 +106,6 @@ import org.jetbrains.annotations.*;
import javax.swing.*;
import javax.swing.border.Border;
-import javax.swing.event.HyperlinkEvent;
-import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -565,30 +559,6 @@ public final class DiffUtil {
return result.wrapWithHtmlBody().toString();
}
- public static void showSuccessPopup(@NotNull @NlsContexts.PopupContent String message,
- @NotNull RelativePoint point,
- @NotNull Disposable disposable,
- @Nullable Runnable hyperlinkHandler) {
- HyperlinkListener listener = null;
- if (hyperlinkHandler != null) {
- listener = new HyperlinkAdapter() {
- @Override
- protected void hyperlinkActivated(@NotNull HyperlinkEvent e) {
- hyperlinkHandler.run();
- }
- };
- }
-
- Color bgColor = MessageType.INFO.getPopupBackground();
-
- Balloon balloon = JBPopupFactory.getInstance()
- .createHtmlTextBalloonBuilder(message, null, bgColor, listener)
- .setAnimationCycle(200)
- .createBalloon();
- balloon.show(point, Balloon.Position.below);
- Disposer.register(disposable, balloon);
- }
-
//
// Titles
//
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeTool.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeTool.java
index d2d36586398c..d227369daefc 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeTool.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchMergeTool.java
@@ -3,14 +3,16 @@ package com.intellij.openapi.vcs.changes.patch.tool;
import com.intellij.diff.DiffContext;
import com.intellij.diff.merge.*;
+import com.intellij.diff.util.DiffBalloons;
import com.intellij.diff.util.DiffUserDataKeys;
-import com.intellij.diff.util.DiffUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.ui.MessageDialogBuilder;
+import com.intellij.openapi.util.NlsSafe;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.scale.JBUIScale;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -112,8 +114,9 @@ final class ApplyPatchMergeTool implements MergeTool {
int yOffset = new RelativePoint(getResultEditor().getComponent(), new Point(0, JBUIScale.scale(5))).getPoint(component).y;
RelativePoint point = new RelativePoint(component, new Point(component.getWidth() / 2, yOffset));
- String message = DiffBundle.message("apply.patch.all.changes.processed.message.text");
- DiffUtil.showSuccessPopup(message, point, this, () -> {
+ String title = DiffBundle.message("apply.patch.all.changes.processed.title.text");
+ @NlsSafe String message = XmlStringUtil.wrapInHtmlTag(DiffBundle.message("apply.patch.all.changes.processed.message.text"), "a");
+ DiffBalloons.showSuccessPopup(title, message, point, this, () -> {
if (isDisposed()) return;
myMergeContext.finishMerge(MergeResult.RESOLVED);
});