Skip to content

Commit 4dbdf85

Browse files
committed
added feature to hover and click in a error and get context window to popup
1 parent 2adbca9 commit 4dbdf85

File tree

6 files changed

+103
-14
lines changed

6 files changed

+103
-14
lines changed

src/main/java/org/overengineer/inlineproblems/InlineProblemLabel.java

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,49 @@
11
package org.overengineer.inlineproblems;
22

3+
import com.intellij.codeInsight.hints.presentation.InputHandler;
4+
import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
35
import com.intellij.ide.ui.AntialiasingType;
46
import com.intellij.ide.ui.UISettings;
7+
import com.intellij.openapi.actionSystem.AnAction;
8+
import com.intellij.openapi.actionSystem.IdeActions;
9+
import com.intellij.openapi.actionSystem.ex.ActionUtil;
510
import com.intellij.openapi.editor.Editor;
611
import com.intellij.openapi.editor.EditorCustomElementRenderer;
712
import com.intellij.openapi.editor.Inlay;
13+
import com.intellij.openapi.editor.ScrollType;
814
import com.intellij.openapi.editor.impl.FontInfo;
915
import com.intellij.openapi.editor.markup.GutterIconRenderer;
1016
import com.intellij.openapi.editor.markup.TextAttributes;
17+
import com.intellij.openapi.project.Project;
18+
import com.intellij.psi.PsiFile;
19+
import com.intellij.psi.util.PsiUtilBase;
20+
import com.intellij.ui.paint.EffectPainter;
1121
import lombok.Getter;
1222
import lombok.Setter;
23+
import org.jdesktop.swingx.action.ActionManager;
1324
import org.jetbrains.annotations.NotNull;
1425
import org.jetbrains.annotations.Nullable;
1526
import org.overengineer.inlineproblems.entities.InlineProblem;
1627
import org.overengineer.inlineproblems.settings.SettingsState;
1728
import org.overengineer.inlineproblems.utils.FontUtil;
1829

1930
import java.awt.*;
31+
import java.awt.event.MouseEvent;
2032
import java.awt.font.FontRenderContext;
2133

2234

2335
@Getter
24-
public class InlineProblemLabel implements EditorCustomElementRenderer {
25-
36+
public class InlineProblemLabel implements EditorCustomElementRenderer, InputHandler {
2637
private final String text;
2738
private final Color textColor;
2839
private final Color backgroundColor;
2940
private final boolean isDrawBox;
3041
private final boolean isRoundedCorners;
3142
private final boolean isFillBackground;
43+
private boolean hovered;
44+
private final boolean hoveredEnabled;
45+
private Inlay<?> inlay;
46+
private final int actualStartOffset;
3247

3348
@Setter
3449
private boolean isBlockElement;
@@ -59,6 +74,9 @@ public InlineProblemLabel(
5974

6075
this.isUseEditorFont = settings.isUseEditorFont();
6176
this.inlayFontSizeDelta = settings.getInlayFontSizeDelta();
77+
this.hovered = false;
78+
this.actualStartOffset = problem.getActualStartffset();
79+
hoveredEnabled = settings.isHovering();
6280
}
6381

6482
@Override
@@ -80,7 +98,7 @@ public int calcWidthInPixels(@NotNull Editor editor) {
8098
@Override
8199
public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rectangle targetRegion, @NotNull TextAttributes textAttributes) {
82100
Editor editor = inlay.getEditor();
83-
101+
this.inlay = inlay;
84102
// These offsets are applied here and not in the calc functions itself because we use it to shrink the drawn stuff a little bit
85103
int width = calcWidthInPixels(inlay) + DRAW_BOX_WIDTH_OFFSET;
86104
int height = calcHeightInPixels(inlay) + DRAW_BOX_HEIGHT_OFFSET;
@@ -92,7 +110,7 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
92110
// Apply delta on the boxes
93111
if (inlayFontSizeDelta != 0 && editorFontSize > inlayFontSizeDelta) {
94112
height -= inlayFontSizeDelta;
95-
targetRegionY += (int)(inlayFontSizeDelta / 1.5);
113+
targetRegionY += (int) (inlayFontSizeDelta / 1.5);
96114
}
97115

98116
if (isDrawBox) {
@@ -118,14 +136,13 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
118136
5
119137
);
120138
}
121-
}
122-
else {
123-
graphics.drawRect(
124-
targetRegion.x,
125-
targetRegionY,
126-
width,
127-
height
128-
);
139+
} else {
140+
graphics.drawRect(
141+
targetRegion.x,
142+
targetRegionY,
143+
width,
144+
height
145+
);
129146

130147
if (isFillBackground) {
131148
graphics.fillRect(
@@ -138,7 +155,7 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
138155
}
139156
}
140157

141-
graphics.setColor(textColor);
158+
graphics.setColor(hovered ? textColor.brighter() : textColor);
142159

143160
graphics.setFont(FontUtil.getActiveFont(editor));
144161

@@ -147,10 +164,64 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
147164
targetRegion.x + DRAW_STRING_LINE_PLACEMENT_OFFSET_X,
148165
targetRegion.y + DRAW_STRING_LINE_PLACEMENT_OFFSET_Y + editor.getAscent()
149166
);
167+
if (hovered)
168+
EffectPainter.LINE_UNDERSCORE.paint(
169+
(Graphics2D) graphics,
170+
targetRegion.x - DRAW_BOX_WIDTH_OFFSET,
171+
targetRegion.y + DRAW_STRING_LINE_PLACEMENT_OFFSET_Y + editor.getAscent(),
172+
width + (DRAW_BOX_WIDTH_OFFSET * 2),
173+
editor.getAscent(),
174+
FontUtil.getActiveFont(editor));
175+
}
176+
177+
private void setHovered(boolean hovered) {
178+
if (!this.hoveredEnabled || this.hovered == hovered) {
179+
return;
180+
}
181+
this.hovered = hovered;
182+
if (inlay != null)
183+
inlay.repaint();
150184
}
151185

152186
@Override
153187
public @Nullable GutterIconRenderer calcGutterIconRenderer(@NotNull Inlay inlay) {
154188
return EditorCustomElementRenderer.super.calcGutterIconRenderer(inlay);
155189
}
190+
191+
@Override
192+
public void mouseClicked(@NotNull MouseEvent mouseEvent, @NotNull Point point) {
193+
if (!hoveredEnabled) {
194+
return;
195+
}
196+
if (mouseEvent.getButton() == MouseEvent.BUTTON1) {
197+
mouseEvent.consume();
198+
199+
var editor = inlay.getEditor();
200+
editor.getCaretModel().moveToOffset(actualStartOffset);
201+
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
202+
203+
var action = ActionManager.getInstance().getAction(IdeActions.ACTION_SHOW_INTENTION_ACTIONS);
204+
if (action == null) {
205+
Project project = editor.getProject();
206+
if (project == null) return;
207+
PsiFile psiFileInEditor = PsiUtilBase.getPsiFileInEditor(editor, project);
208+
if (psiFileInEditor == null) return;
209+
new ShowIntentionActionsHandler().invoke(project, editor, psiFileInEditor, false);
210+
} else {
211+
ActionUtil.invokeAction((AnAction) action, editor.getComponent(), "EditorInlay", null, null);
212+
213+
}
214+
}
215+
}
216+
217+
@Override
218+
public void mouseMoved(@NotNull MouseEvent mouseEvent, @NotNull Point point) {
219+
setHovered(true);
220+
}
221+
222+
@Override
223+
public void mouseExited() {
224+
setHovered(false);
225+
}
226+
156227
}

src/main/java/org/overengineer/inlineproblems/entities/InlineProblem.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class InlineProblem {
3030
private DrawDetails drawDetails;
3131

3232
private int actualEndOffset;
33+
private int actualStartffset;
3334

3435
private boolean isBlockElement = false;
3536

@@ -73,6 +74,7 @@ public InlineProblem(
7374
this.actualEndOffset = highlightInfo.getActualEndOffset();
7475
else
7576
this.actualEndOffset = highlightInfo.getActualEndOffset() -1;
77+
this.actualStartffset = highlightInfo.getStartOffset();
7678
}
7779

7880
private String getTextWithHtmlStrippingAndXmlUnescaping(String text, SettingsState settingsState) {

src/main/java/org/overengineer/inlineproblems/settings/SettingsComponent.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public class SettingsComponent {
6868
private final JBCheckBox fillProblemLabels = new JBCheckBox(SettingsBundle.message("settings.fillProblemLabels"));
6969
private final JBCheckBox boldProblemLabels = new JBCheckBox(SettingsBundle.message("settings.boldProblemLabels"));
7070
private final JBCheckBox italicProblemLabels = new JBCheckBox(SettingsBundle.message("settings.italicProblemLabels"));
71+
private final JBCheckBox enableHovering = new JBCheckBox(SettingsBundle.message("settings.enableHovering"));
72+
7173
private final JBTextField problemFilterList = new JBTextField();
7274
private final JBTextField fileExtensionBlacklist = new JBTextField();
7375

@@ -133,6 +135,7 @@ public SettingsComponent() {
133135
fillProblemLabels.setSelected(settingsState.isFillProblemLabels());
134136
boldProblemLabels.setSelected(settingsState.isBoldProblemLabels());
135137
italicProblemLabels.setSelected(settingsState.isItalicProblemLabels());
138+
enableHovering.setSelected(settingsState.isHovering());
136139

137140
additionalInfoSeverities.setText(settingsState.getAdditionalInfoSeveritiesAsString());
138141
additionalWeakWarningSeverities.setText(settingsState.getAdditionalWeakWarningSeveritiesAsString());
@@ -154,6 +157,7 @@ public SettingsComponent() {
154157
.addComponent(fillProblemLabels, 0)
155158
.addComponent(boldProblemLabels, 0)
156159
.addComponent(italicProblemLabels, 0)
160+
.addComponent(enableHovering, 0)
157161
.addSeparator()
158162
.addComponent(new JBLabel(SettingsBundle.message("settings.submenu.general")))
159163
.addLabeledComponent(new JBLabel(SettingsBundle.message("settings.activeProblemListener")), enabledListener)
@@ -317,6 +321,13 @@ public void setItalicProblemLabels(boolean isSelected) {
317321
italicProblemLabels.setSelected(isSelected);
318322
}
319323

324+
public boolean isHovering() {
325+
return enableHovering.isSelected();
326+
}
327+
public void setHovering(boolean isSelected) {
328+
enableHovering.setSelected(isSelected);
329+
}
330+
320331
public boolean isShowErrors() {
321332
return showErrors.isSelected();
322333
}

src/main/java/org/overengineer/inlineproblems/settings/SettingsConfigurable.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public boolean isModified() {
5252
state.isFillProblemLabels() == settingsComponent.isFillProblemLabels() &&
5353
state.isBoldProblemLabels() == settingsComponent.isBoldProblemLabels() &&
5454
state.isItalicProblemLabels() == settingsComponent.isItalicProblemLabels() &&
55+
state.isHovering() == settingsComponent.isHovering() &&
5556

5657
state.getErrorTextColor().equals(settingsComponent.getErrorTextColor()) &&
5758
state.getErrorBackgroundColor().equals(settingsComponent.getErrorLabelBackgroundColor()) &&
@@ -143,6 +144,7 @@ public void apply() {
143144
state.setFillProblemLabels(settingsComponent.isFillProblemLabels());
144145
state.setBoldProblemLabels(settingsComponent.isBoldProblemLabels());
145146
state.setItalicProblemLabels(settingsComponent.isItalicProblemLabels());
147+
state.setHovering(settingsComponent.isHovering());
146148

147149
state.setEnabledListener(settingsComponent.getEnabledListener());
148150
state.setManualScannerDelay(settingsComponent.getManualScannerDelay());
@@ -213,6 +215,7 @@ public void reset() {
213215
settingsComponent.setFillProblemLabels(state.isFillProblemLabels());
214216
settingsComponent.setBoldProblemLabels(state.isBoldProblemLabels());
215217
settingsComponent.setItalicProblemLabels(state.isItalicProblemLabels());
218+
settingsComponent.setHovering(state.isHovering());
216219

217220
settingsComponent.setEnabledListener(state.getEnabledListener());
218221
settingsComponent.setManualScannerDelay(state.getManualScannerDelay());

src/main/java/org/overengineer/inlineproblems/settings/SettingsState.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class SettingsState implements PersistentStateComponent<SettingsState> {
4040
private boolean showInfos = false;
4141
private boolean highlightInfos = false;
4242
private boolean showInfosInGutter = false;
43+
private boolean hovering = false;
4344

4445
/**
4546
* Colors renamed from '<NAME>Color' to '<NAME>Col' to solve

src/main/resources/messages/SettingsBundle_en.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ settings.forceProblemsInOneLine=Force problems in the same line even if they are
5252
settings.useEditorFont=Use editor font instead of tooltip font
5353
settings.showOnlyHighestPerLine=Show only the problem with the highest severity per line
5454
settings.enableHtmlStripping=Enable stripping of HTML in the messages
55-
settings.enableXmlUnescaping=Enable unescaping of XML in the messages
55+
settings.enableXmlUnescaping=Enable unescaping of XML in the messages
56+
settings.enableHovering=Enable hovering

0 commit comments

Comments
 (0)