mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-14 18:05:27 +07:00
DBE-15813: Converted ErrorNotificationPanel.java to Kotlin
GitOrigin-RevId: 11da616e78b6bdf749c5e376b503d7bbbbf0b3d3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
39e9216447
commit
cd39f261dd
@@ -1,301 +0,0 @@
|
||||
package com.intellij.database.run.ui;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.database.DataGridBundle;
|
||||
import com.intellij.database.datagrid.GridUtil;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.CopyProvider;
|
||||
import com.intellij.ide.IdeTooltipManager;
|
||||
import com.intellij.ide.TextCopyProvider;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.HintHint;
|
||||
import com.intellij.ui.HyperlinkAdapter;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.JBInsets;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.HierarchyEvent;
|
||||
import java.awt.event.HierarchyListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public final class ErrorNotificationPanel extends JPanel {
|
||||
|
||||
private final JEditorPane myMessagePane;
|
||||
private final Map<String, Runnable> myActions;
|
||||
private final CopyProvider myCopyProvider;
|
||||
private final MessageType myType;
|
||||
|
||||
private ErrorNotificationPanel(@NlsContexts.NotificationContent @NotNull String htmlErrorMessage,
|
||||
@NotNull Map<String, Runnable> actions,
|
||||
@NotNull MessageType type) {
|
||||
super(new BorderLayout());
|
||||
myActions = actions;
|
||||
myType = type;
|
||||
|
||||
setBorder(JBUI.Borders.empty(0, 4));
|
||||
|
||||
myMessagePane = IdeTooltipManager.initPane(htmlErrorMessage, new HintHint()
|
||||
.setAwtTooltip(false)
|
||||
.setTextFg(getForeground())
|
||||
.setTextBg(getBackground())
|
||||
.setBorderColor(getBackground())
|
||||
.setBorderInsets(JBInsets.emptyInsets()), null);
|
||||
myMessagePane.setBorder(null);
|
||||
myMessagePane.addHyperlinkListener(new HyperlinkAdapter() {
|
||||
@Override
|
||||
protected void hyperlinkActivated(@NotNull HyperlinkEvent e) {
|
||||
performAction(e.getDescription());
|
||||
}
|
||||
});
|
||||
myCopyProvider = new TextCopyProvider() {
|
||||
@Override
|
||||
public @NotNull ActionUpdateThread getActionUpdateThread() {
|
||||
return ActionUpdateThread.EDT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Collection<String> getTextLinesToCopy() {
|
||||
String text = myMessagePane.getSelectedText();
|
||||
return StringUtil.isEmpty(text) ? null : Collections.singleton(text);
|
||||
}
|
||||
};
|
||||
add(UiDataProvider.wrapComponent(myMessagePane, sink -> {
|
||||
sink.set(PlatformDataKeys.COPY_PROVIDER, this.myCopyProvider);
|
||||
}), BorderLayout.CENTER);
|
||||
|
||||
new DumbAwareAction(DataGridBundle.message("action.close.text")) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
performAction(DataGridBundle.message("action.close.text"));
|
||||
}
|
||||
}.registerCustomShortcutSet(new CustomShortcutSet(KeyEvent.VK_ESCAPE), this);
|
||||
}
|
||||
|
||||
private void performAction(String actionName) {
|
||||
Runnable action = myActions.get(actionName);
|
||||
if (action != null) {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Color getBackground() {
|
||||
return getType().getPopupBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Color getForeground() {
|
||||
return getType().getTitleForeground();
|
||||
}
|
||||
|
||||
private @NotNull MessageType getType() {
|
||||
return ObjectUtils.chooseNotNull(myType, MessageType.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Dimension getMinimumSize() {
|
||||
return JBUI.emptySize();
|
||||
}
|
||||
|
||||
public JComponent getContent() {
|
||||
return myMessagePane;
|
||||
}
|
||||
|
||||
public static @NotNull Builder create(@Nullable @NlsContexts.NotificationContent String message, @Nullable Throwable error, @NotNull JComponent baseComponent) {
|
||||
return new Builder(message, error, baseComponent);
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private final boolean myLongMessage;
|
||||
private final Throwable myError;
|
||||
private final @NlsContexts.NotificationContent String myMessage;
|
||||
private final JComponent myBaseComponent;
|
||||
|
||||
private final Map<String, Runnable> myActions = new LinkedHashMap<>();
|
||||
private final List<Consumer<Disposable>> myShowHideHandlers = new ArrayList<>();
|
||||
private final StringBuilder myHtmlBuilder = new StringBuilder();
|
||||
|
||||
private boolean isChoppedMessage = false;
|
||||
|
||||
private MessageType myType = MessageType.ERROR;
|
||||
|
||||
private Builder(@NlsContexts.NotificationContent @Nullable String message, @Nullable Throwable error, @NotNull JComponent baseComponent) {
|
||||
myError = error;
|
||||
myMessage = message;
|
||||
myBaseComponent = baseComponent;
|
||||
|
||||
String errorMessage = message == null ? error == null ? null : getNormalizedMessage(error) : getNormalized(message);
|
||||
Font font = IdeTooltipManager.getInstance().getTextFont(true);
|
||||
FontMetrics fm = baseComponent.getFontMetrics(font);
|
||||
myLongMessage = SwingUtilities.computeStringWidth(fm, errorMessage) > baseComponent.getWidth() * 3 / 4;
|
||||
if (errorMessage != null) {
|
||||
errorMessage = StringUtil.escapeXmlEntities(errorMessage).replace("\n", "<br>");
|
||||
}
|
||||
|
||||
myHtmlBuilder.append("<html><head><style type=\"text/css\">a:link {text-decoration:none;}</style></head><body>");
|
||||
myHtmlBuilder.append("<font face=\"verdana\"><table width=\"100%\"><tr valign=\"top\"><td>");
|
||||
myHtmlBuilder.append(errorMessage);
|
||||
myHtmlBuilder.append("</td>");
|
||||
}
|
||||
|
||||
public @NotNull Builder messageType(@NotNull MessageType type) {
|
||||
myType = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder addIconLink(String command, @NlsContexts.Tooltip String tooltipText, @NotNull Icon realIcon, @Nullable Runnable action) {
|
||||
String iconPath = GridUtil.getIconPath(realIcon);
|
||||
|
||||
startActionColumn();
|
||||
myHtmlBuilder.append("<a href=\"")
|
||||
.append(command).append("\"><icon alt=\"").append(tooltipText).append("\"")
|
||||
.append("\" src=\"");
|
||||
myHtmlBuilder.append(iconPath).append("\"></a>");
|
||||
endActionColumn();
|
||||
|
||||
if (action != null) {
|
||||
myActions.put(command, action);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder addSpace() {
|
||||
startActionColumn();
|
||||
endActionColumn();
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder addLink(@NonNls @NotNull String command, @NlsActions.ActionText @NotNull String linkHtml, @NotNull Runnable action) {
|
||||
startActionColumn();
|
||||
int mnemonicIndex = UIUtil.getDisplayMnemonicIndex(command);
|
||||
@NlsSafe
|
||||
String fixedCommand = mnemonicIndex < 0 ? command : command.substring(0, mnemonicIndex) + command.substring(mnemonicIndex + 1);
|
||||
ContainerUtil.addIfNotNull(myShowHideHandlers, createMnemonicActionIfNeeded(fixedCommand, mnemonicIndex, action, myBaseComponent));
|
||||
myHtmlBuilder.append("<a style=\"text-decoration:none;\" href=\"").append(fixedCommand).append("\">").append(linkHtml).append("</a>");
|
||||
endActionColumn();
|
||||
myActions.put(fixedCommand, action);
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder addDetailsButton() {
|
||||
final String message = myError == null ? myMessage : myError.getStackTrace().length > 0 ? ExceptionUtil.getThrowableText(myError, "com.intellij.") : myError.getMessage();
|
||||
if (StringUtil.contains(myHtmlBuilder, message)) return this;
|
||||
return addLink("details", DataGridBundle.message("action.details.text"), () -> Messages.showIdeaMessageDialog(null, message,
|
||||
DataGridBundle.message("dialog.title.query.error"),
|
||||
new String[]{CommonBundle.getOkButtonText()}, 0, Messages.getErrorIcon(), null));
|
||||
}
|
||||
|
||||
public @NotNull Builder addFullMessageButtonIfNeeded() {
|
||||
if (!isChoppedMessage) return this;
|
||||
return addLink("details", DataGridBundle.message("action.full.message.text"), () -> Messages.showIdeaMessageDialog(null, myMessage,
|
||||
DataGridBundle.message("dialog.title.query.error"),
|
||||
new String[]{CommonBundle.getOkButtonText()}, 0, Messages.getErrorIcon(), null));
|
||||
|
||||
}
|
||||
|
||||
public @NotNull Builder addCloseButton(Runnable action) {
|
||||
return addIconLink(DataGridBundle.message("action.close.text"), DataGridBundle.message("tooltip.close.esc"), AllIcons.Actions.Close, action);
|
||||
}
|
||||
|
||||
public @NotNull ErrorNotificationPanel build() {
|
||||
myHtmlBuilder.append("</tr></table></font></body>");
|
||||
ErrorNotificationPanel result = new ErrorNotificationPanel(myHtmlBuilder.toString(), myActions, myType); //NON-NLS
|
||||
registerShowHideHandlers(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void startActionColumn() {
|
||||
myHtmlBuilder.append("<td width=\"1%\" align=\"right\" valign=\"")
|
||||
.append(myLongMessage ? "top" : "middle")
|
||||
.append("\" nowrap><div style='margin:0px 2px 0px 2px'>");
|
||||
}
|
||||
|
||||
private void endActionColumn() {
|
||||
myHtmlBuilder.append("</div></td>");
|
||||
}
|
||||
|
||||
private @NlsContexts.NotificationContent @NotNull String getNormalizedMessage(@NotNull Throwable error) {
|
||||
String sourceMessage = StringUtil.notNullize(error.getMessage(),
|
||||
DataGridBundle.message("notification.content.unknown.problem.occurred.see.details")) + "kgmsdkgmksdfgnmksndfgknskdfgnksndgkndfkgnsdkfgnskdngkndsfgksnkgnfksdngksdnfgksndkgnsdkfgnksdnfgkndkfgnskngfksnkgfnksdnfgksdnfgknsdkgnslgnskldfnglksnfgksnfgksnkfgnksdfngksdnfgksdngksndfgknsdkf";
|
||||
// In some cases source message contains stacktrace inside. Let's chop it
|
||||
int divPos = sourceMessage.indexOf("\n\tat ");
|
||||
if (divPos != -1) {
|
||||
sourceMessage = sourceMessage.substring(0, divPos);
|
||||
isChoppedMessage = true;
|
||||
}
|
||||
return getNormalized(sourceMessage);
|
||||
}
|
||||
|
||||
private @NlsContexts.NotificationContent @NotNull String getNormalized(@NlsContexts.NotificationContent @NotNull String sourceMessage) {
|
||||
int lineLimit = StringUtil.lineColToOffset(sourceMessage, 5, 0);
|
||||
int charLimit = 1024;
|
||||
int limit = lineLimit == -1 || lineLimit > charLimit ? charLimit : lineLimit;
|
||||
if (sourceMessage.length() > limit) isChoppedMessage = true;
|
||||
return StringUtil.trimLog(sourceMessage, limit + 1);
|
||||
}
|
||||
|
||||
private void registerShowHideHandlers(@NotNull JComponent component) {
|
||||
if (myShowHideHandlers.isEmpty()) return;
|
||||
|
||||
component.addHierarchyListener(new HierarchyListener() {
|
||||
private Disposable myShownDisposable;
|
||||
@Override
|
||||
public void hierarchyChanged(HierarchyEvent e) {
|
||||
Component c = e.getComponent();
|
||||
if (c == null || (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) <= 0) return;
|
||||
|
||||
if (c.isShowing()) {
|
||||
myShownDisposable = Disposer.newDisposable();
|
||||
for (Consumer<Disposable> handler : myShowHideHandlers) {
|
||||
handler.consume(myShownDisposable);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (myShownDisposable != null) Disposer.dispose(myShownDisposable);
|
||||
myShownDisposable = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static @Nullable Consumer<Disposable> createMnemonicActionIfNeeded(final @NlsActions.ActionText String command,
|
||||
final int mnemonicIndex,
|
||||
final Runnable runnable,
|
||||
final JComponent component) {
|
||||
if (mnemonicIndex < 0) return null;
|
||||
return (parentDisposable) -> {
|
||||
DumbAwareAction a = new DumbAwareAction(command) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
runnable.run();
|
||||
}
|
||||
};
|
||||
int modifiers = SystemInfo.isMac && !Registry.is("ide.mac.alt.mnemonic.without.ctrl") ?
|
||||
InputEvent.ALT_MASK | InputEvent.CTRL_MASK : InputEvent.ALT_MASK;
|
||||
KeyStroke keyStroke = KeyStroke.getKeyStroke(Character.toUpperCase(command.charAt(mnemonicIndex)), modifiers);
|
||||
a.registerCustomShortcutSet(new CustomShortcutSet(keyStroke), component, parentDisposable);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
296
grid/impl/src/run/ui/ErrorNotificationPanel.kt
Normal file
296
grid/impl/src/run/ui/ErrorNotificationPanel.kt
Normal file
@@ -0,0 +1,296 @@
|
||||
package com.intellij.database.run.ui
|
||||
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.database.DataGridBundle
|
||||
import com.intellij.database.datagrid.GridUtil
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.CopyProvider
|
||||
import com.intellij.ide.IdeTooltipManager.Companion.getInstance
|
||||
import com.intellij.ide.IdeTooltipManager.Companion.initPane
|
||||
import com.intellij.ide.TextCopyProvider
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.actionSystem.UiDataProvider.Companion.wrapComponent
|
||||
import com.intellij.openapi.project.DumbAwareAction
|
||||
import com.intellij.openapi.ui.MessageType
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.util.*
|
||||
import com.intellij.openapi.util.registry.Registry.Companion.`is`
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.ui.HintHint
|
||||
import com.intellij.ui.HyperlinkAdapter
|
||||
import com.intellij.util.Consumer
|
||||
import com.intellij.util.ObjectUtils
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.ui.JBInsets
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Color
|
||||
import java.awt.Dimension
|
||||
import java.awt.event.HierarchyEvent
|
||||
import java.awt.event.HierarchyListener
|
||||
import java.awt.event.InputEvent
|
||||
import java.awt.event.KeyEvent
|
||||
import javax.swing.*
|
||||
import javax.swing.event.HyperlinkEvent
|
||||
|
||||
class ErrorNotificationPanel private constructor(
|
||||
htmlErrorMessage: @NlsContexts.NotificationContent String,
|
||||
private val myActions: MutableMap<String?, Runnable?>,
|
||||
private val myType: MessageType
|
||||
) : JPanel(BorderLayout()) {
|
||||
private val myMessagePane: JEditorPane
|
||||
private val myCopyProvider: CopyProvider
|
||||
|
||||
init {
|
||||
setBorder(JBUI.Borders.empty(0, 4))
|
||||
|
||||
myMessagePane = initPane(htmlErrorMessage, HintHint()
|
||||
.setAwtTooltip(false)
|
||||
.setTextFg(getForeground())
|
||||
.setTextBg(getBackground())
|
||||
.setBorderColor(getBackground())
|
||||
.setBorderInsets(JBInsets.emptyInsets()), null)
|
||||
myMessagePane.setBorder(null)
|
||||
myMessagePane.addHyperlinkListener(object : HyperlinkAdapter() {
|
||||
override fun hyperlinkActivated(e: HyperlinkEvent) {
|
||||
performAction(e.description)
|
||||
}
|
||||
})
|
||||
myCopyProvider = object : TextCopyProvider() {
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.EDT
|
||||
}
|
||||
|
||||
override fun getTextLinesToCopy(): MutableCollection<String?>? {
|
||||
val text = myMessagePane.getSelectedText()
|
||||
return if (StringUtil.isEmpty(text)) null else mutableSetOf<String?>(text)
|
||||
}
|
||||
}
|
||||
add(wrapComponent(myMessagePane, UiDataProvider { sink: DataSink? ->
|
||||
sink!!.set<CopyProvider>(PlatformDataKeys.COPY_PROVIDER, this.myCopyProvider)
|
||||
}), BorderLayout.CENTER)
|
||||
|
||||
object : DumbAwareAction(DataGridBundle.message("action.close.text")) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
performAction(DataGridBundle.message("action.close.text"))
|
||||
}
|
||||
}.registerCustomShortcutSet(CustomShortcutSet(KeyEvent.VK_ESCAPE), this)
|
||||
}
|
||||
|
||||
private fun performAction(actionName: String?) {
|
||||
myActions[actionName]?.run()
|
||||
}
|
||||
|
||||
override fun getBackground(): Color {
|
||||
return type.popupBackground
|
||||
}
|
||||
|
||||
override fun getForeground(): Color {
|
||||
return type.titleForeground
|
||||
}
|
||||
|
||||
private val type: MessageType
|
||||
get() = ObjectUtils.chooseNotNull<MessageType>(myType, MessageType.ERROR)
|
||||
|
||||
override fun getMinimumSize(): Dimension {
|
||||
return JBUI.emptySize()
|
||||
}
|
||||
|
||||
val content: JComponent
|
||||
get() = myMessagePane
|
||||
|
||||
class Builder internal constructor(
|
||||
private val myMessage: @NlsContexts.NotificationContent String?,
|
||||
private val myError: Throwable?,
|
||||
private val myBaseComponent: JComponent
|
||||
) {
|
||||
private val myLongMessage: Boolean
|
||||
|
||||
private val myActions: MutableMap<String?, Runnable?> = LinkedHashMap<String?, Runnable?>()
|
||||
private val myShowHideHandlers: MutableList<Consumer<Disposable?>> = ArrayList<Consumer<Disposable?>>()
|
||||
private val myHtmlBuilder = StringBuilder()
|
||||
|
||||
private var isChoppedMessage = false
|
||||
|
||||
private var myType: MessageType = MessageType.ERROR
|
||||
|
||||
init {
|
||||
var errorMessage = if (myMessage == null) if (myError == null) null else getNormalizedMessage(myError)
|
||||
else getNormalized(
|
||||
myMessage)
|
||||
val font = getInstance().getTextFont(true)
|
||||
val fm = myBaseComponent.getFontMetrics(font)
|
||||
myLongMessage = SwingUtilities.computeStringWidth(fm, errorMessage) > myBaseComponent.getWidth() * 3 / 4
|
||||
if (errorMessage != null) {
|
||||
errorMessage = StringUtil.escapeXmlEntities(errorMessage).replace("\n", "<br>")
|
||||
}
|
||||
|
||||
myHtmlBuilder.append("<html><head><style type=\"text/css\">a:link {text-decoration:none;}</style></head><body>")
|
||||
myHtmlBuilder.append("<font face=\"verdana\"><table width=\"100%\"><tr valign=\"top\"><td>")
|
||||
myHtmlBuilder.append(errorMessage)
|
||||
myHtmlBuilder.append("</td>")
|
||||
}
|
||||
|
||||
fun messageType(type: MessageType): Builder {
|
||||
myType = type
|
||||
return this
|
||||
}
|
||||
|
||||
fun addIconLink(command: String?, tooltipText: @NlsContexts.Tooltip String?, realIcon: Icon, action: Runnable?): Builder {
|
||||
val iconPath = GridUtil.getIconPath(realIcon)
|
||||
|
||||
startActionColumn()
|
||||
myHtmlBuilder.append("<a href=\"")
|
||||
.append(command).append("\"><icon alt=\"").append(tooltipText).append("\"")
|
||||
.append("\" src=\"")
|
||||
myHtmlBuilder.append(iconPath).append("\"></a>")
|
||||
endActionColumn()
|
||||
|
||||
if (action != null) {
|
||||
myActions.put(command, action)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fun addSpace(): Builder {
|
||||
startActionColumn()
|
||||
endActionColumn()
|
||||
return this
|
||||
}
|
||||
|
||||
fun addLink(command: @NonNls String, linkHtml: @NlsActions.ActionText String, action: Runnable): Builder {
|
||||
startActionColumn()
|
||||
val mnemonicIndex = UIUtil.getDisplayMnemonicIndex(command)
|
||||
val fixedCommand: @NlsSafe String = if (mnemonicIndex < 0) command else command.substring(0, mnemonicIndex) + command.substring(mnemonicIndex + 1)
|
||||
ContainerUtil.addIfNotNull<Consumer<Disposable?>?>(myShowHideHandlers,
|
||||
createMnemonicActionIfNeeded(fixedCommand, mnemonicIndex, action, myBaseComponent))
|
||||
myHtmlBuilder.append("<a style=\"text-decoration:none;\" href=\"").append(fixedCommand).append("\">").append(linkHtml).append("</a>")
|
||||
endActionColumn()
|
||||
myActions.put(fixedCommand, action)
|
||||
return this
|
||||
}
|
||||
|
||||
fun addDetailsButton(): Builder {
|
||||
val message: String = (if (myError == null) myMessage
|
||||
else if (myError.stackTrace.size > 0) com.intellij.util.ExceptionUtil.getThrowableText(myError, "com.intellij.")
|
||||
else myError.message)!!
|
||||
if (StringUtil.contains(myHtmlBuilder, message)) return this
|
||||
return addLink("details", DataGridBundle.message("action.details.text"), Runnable {
|
||||
Messages.showIdeaMessageDialog(null, message,
|
||||
DataGridBundle.message("dialog.title.query.error"),
|
||||
arrayOf<String>(CommonBundle.getOkButtonText()), 0, Messages.getErrorIcon(), null)
|
||||
})
|
||||
}
|
||||
|
||||
fun addFullMessageButtonIfNeeded(): Builder {
|
||||
if (!isChoppedMessage) return this
|
||||
return addLink("details", DataGridBundle.message("action.full.message.text"), Runnable {
|
||||
Messages.showIdeaMessageDialog(null, myMessage,
|
||||
DataGridBundle.message("dialog.title.query.error"),
|
||||
arrayOf<String>(CommonBundle.getOkButtonText()), 0, Messages.getErrorIcon(), null
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fun addCloseButton(action: Runnable?): Builder {
|
||||
return addIconLink(DataGridBundle.message("action.close.text"), DataGridBundle.message("tooltip.close.esc"),
|
||||
AllIcons.Actions.Close, action)
|
||||
}
|
||||
|
||||
fun build(): ErrorNotificationPanel {
|
||||
myHtmlBuilder.append("</tr></table></font></body>")
|
||||
val result = ErrorNotificationPanel(myHtmlBuilder.toString(), myActions, myType) //NON-NLS
|
||||
registerShowHideHandlers(result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun startActionColumn() {
|
||||
myHtmlBuilder.append("<td width=\"1%\" align=\"right\" valign=\"")
|
||||
.append(if (myLongMessage) "top" else "middle")
|
||||
.append("\" nowrap><div style='margin:0px 2px 0px 2px'>")
|
||||
}
|
||||
|
||||
private fun endActionColumn() {
|
||||
myHtmlBuilder.append("</div></td>")
|
||||
}
|
||||
|
||||
private fun getNormalizedMessage(error: Throwable): @NlsContexts.NotificationContent String {
|
||||
var sourceMessage = StringUtil.notNullize(error.message,
|
||||
DataGridBundle.message(
|
||||
"notification.content.unknown.problem.occurred.see.details")) + "kgmsdkgmksdfgnmksndfgknskdfgnksndgkndfkgnsdkfgnskdngkndsfgksnkgnfksdngksdnfgksndkgnsdkfgnksdnfgkndkfgnskngfksnkgfnksdnfgksdnfgknsdkgnslgnskldfnglksnfgksnfgksnkfgnksdfngksdnfgksdngksndfgknsdkf"
|
||||
// In some cases source message contains stacktrace inside. Let's chop it
|
||||
val divPos = sourceMessage.indexOf("\n\tat ")
|
||||
if (divPos != -1) {
|
||||
sourceMessage = sourceMessage.substring(0, divPos)
|
||||
isChoppedMessage = true
|
||||
}
|
||||
return getNormalized(sourceMessage)
|
||||
}
|
||||
|
||||
private fun getNormalized(sourceMessage: @NlsContexts.NotificationContent String): @NlsContexts.NotificationContent String {
|
||||
val lineLimit = StringUtil.lineColToOffset(sourceMessage, 5, 0)
|
||||
val charLimit = 1024
|
||||
val limit = if (lineLimit == -1 || lineLimit > charLimit) charLimit else lineLimit
|
||||
if (sourceMessage.length > limit) isChoppedMessage = true
|
||||
return StringUtil.trimLog(sourceMessage, limit + 1)
|
||||
}
|
||||
|
||||
private fun registerShowHideHandlers(component: JComponent) {
|
||||
if (myShowHideHandlers.isEmpty()) return
|
||||
|
||||
component.addHierarchyListener(object : HierarchyListener {
|
||||
private var myShownDisposable: Disposable? = null
|
||||
override fun hierarchyChanged(e: HierarchyEvent) {
|
||||
val c = e.component
|
||||
if (c == null || (e.getChangeFlags() and HierarchyEvent.SHOWING_CHANGED.toLong()) <= 0) return
|
||||
|
||||
if (c.isShowing()) {
|
||||
myShownDisposable = Disposer.newDisposable()
|
||||
for (handler in myShowHideHandlers) {
|
||||
handler.consume(myShownDisposable)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (myShownDisposable != null) Disposer.dispose(myShownDisposable!!)
|
||||
myShownDisposable = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun createMnemonicActionIfNeeded(
|
||||
command: @NlsActions.ActionText String,
|
||||
mnemonicIndex: Int,
|
||||
runnable: Runnable,
|
||||
component: JComponent?
|
||||
): Consumer<Disposable?>? {
|
||||
if (mnemonicIndex < 0) return null
|
||||
return { parentDisposable: Disposable? ->
|
||||
val a: DumbAwareAction = object : DumbAwareAction(command) {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
runnable.run()
|
||||
}
|
||||
}
|
||||
val modifiers = if (SystemInfo.isMac && !`is`(
|
||||
"ide.mac.alt.mnemonic.without.ctrl")
|
||||
) InputEvent.ALT_MASK or InputEvent.CTRL_MASK
|
||||
else InputEvent.ALT_MASK
|
||||
val keyStroke = KeyStroke.getKeyStroke(command.get(mnemonicIndex).uppercaseChar().code, modifiers)
|
||||
a.registerCustomShortcutSet(CustomShortcutSet(keyStroke), component, parentDisposable)
|
||||
} as? Consumer<Disposable?>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun create(message: @NlsContexts.NotificationContent String?, error: Throwable?, baseComponent: JComponent): Builder {
|
||||
return Builder(message, error, baseComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user