Skip to content

Commit 86fbdd7

Browse files
authored
Merge pull request #76 from khopland/feature/67-inline-click
added feature to hover and click in a error and get context window
2 parents 2adbca9 + 46a6aaf commit 86fbdd7

File tree

8 files changed

+111
-18
lines changed

8 files changed

+111
-18
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public void drawProblemLabel(InlineProblem problem) {
3838
problem,
3939
drawDetails.getTextColor(),
4040
drawDetails.getBackgroundColor(),
41+
drawDetails.getTextColor().brighter(),
4142
settings
4243
);
4344

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

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,50 @@
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;
40+
private final Color hoverColor;
2941
private final boolean isDrawBox;
3042
private final boolean isRoundedCorners;
3143
private final boolean isFillBackground;
44+
private boolean hovered;
45+
private final boolean clickableContext;
46+
private Inlay<?> inlay;
47+
private final int actualStartOffset;
3248

3349
@Setter
3450
private boolean isBlockElement;
@@ -47,10 +63,12 @@ public InlineProblemLabel(
4763
final InlineProblem problem,
4864
final Color textColor,
4965
final Color backgroundColor,
66+
final Color hoverColor,
5067
final SettingsState settings
5168
) {
5269
this.textColor = textColor;
5370
this.backgroundColor = backgroundColor;
71+
this.hoverColor = hoverColor;
5472
this.isDrawBox = settings.isDrawBoxesAroundErrorLabels();
5573
this.isRoundedCorners = settings.isRoundedCornerBoxes();
5674
this.text = problem.getText();
@@ -59,6 +77,9 @@ public InlineProblemLabel(
5977

6078
this.isUseEditorFont = settings.isUseEditorFont();
6179
this.inlayFontSizeDelta = settings.getInlayFontSizeDelta();
80+
this.hovered = false;
81+
this.actualStartOffset = problem.getActualStartffset();
82+
this.clickableContext = settings.isClickableContext();
6283
}
6384

6485
@Override
@@ -80,7 +101,7 @@ public int calcWidthInPixels(@NotNull Editor editor) {
80101
@Override
81102
public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rectangle targetRegion, @NotNull TextAttributes textAttributes) {
82103
Editor editor = inlay.getEditor();
83-
104+
this.inlay = inlay;
84105
// These offsets are applied here and not in the calc functions itself because we use it to shrink the drawn stuff a little bit
85106
int width = calcWidthInPixels(inlay) + DRAW_BOX_WIDTH_OFFSET;
86107
int height = calcHeightInPixels(inlay) + DRAW_BOX_HEIGHT_OFFSET;
@@ -92,7 +113,7 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
92113
// Apply delta on the boxes
93114
if (inlayFontSizeDelta != 0 && editorFontSize > inlayFontSizeDelta) {
94115
height -= inlayFontSizeDelta;
95-
targetRegionY += (int)(inlayFontSizeDelta / 1.5);
116+
targetRegionY += (int) (inlayFontSizeDelta / 1.5);
96117
}
97118

98119
if (isDrawBox) {
@@ -118,14 +139,13 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
118139
5
119140
);
120141
}
121-
}
122-
else {
123-
graphics.drawRect(
124-
targetRegion.x,
125-
targetRegionY,
126-
width,
127-
height
128-
);
142+
} else {
143+
graphics.drawRect(
144+
targetRegion.x,
145+
targetRegionY,
146+
width,
147+
height
148+
);
129149

130150
if (isFillBackground) {
131151
graphics.fillRect(
@@ -138,7 +158,7 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
138158
}
139159
}
140160

141-
graphics.setColor(textColor);
161+
graphics.setColor(hovered ? hoverColor : textColor);
142162

143163
graphics.setFont(FontUtil.getActiveFont(editor));
144164

@@ -147,10 +167,63 @@ public void paint(@NotNull Inlay inlay, @NotNull Graphics graphics, @NotNull Rec
147167
targetRegion.x + DRAW_STRING_LINE_PLACEMENT_OFFSET_X,
148168
targetRegion.y + DRAW_STRING_LINE_PLACEMENT_OFFSET_Y + editor.getAscent()
149169
);
170+
if (hovered)
171+
EffectPainter.LINE_UNDERSCORE.paint(
172+
(Graphics2D) graphics,
173+
targetRegion.x - DRAW_BOX_WIDTH_OFFSET,
174+
targetRegion.y + editor.getAscent() ,
175+
width + (DRAW_BOX_WIDTH_OFFSET * 2),
176+
editor.getAscent(),
177+
FontUtil.getActiveFont(editor));
178+
}
179+
180+
private void setHovered(boolean hovered) {
181+
if (!this.clickableContext || this.hovered == hovered) {
182+
return;
183+
}
184+
this.hovered = hovered;
185+
if (inlay != null)
186+
inlay.repaint();
150187
}
151188

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

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

@@ -68,6 +69,7 @@ public InlineProblem(
6869
this.project = textEditor.getEditor().getProject();
6970
this.highlightInfoStartOffset = highlightInfo.hashCode();
7071
this.rangeHighlighterHashCode = rangeHighlighter.hashCode();
72+
this.actualStartffset = highlightInfo.getStartOffset();
7173

7274
if (highlightInfo.getActualEndOffset() == 0)
7375
this.actualEndOffset = highlightInfo.getActualEndOffset();

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

Lines changed: 15 additions & 4 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 clickableContext = new JBCheckBox(SettingsBundle.message("settings.enableClickableContext"));
72+
7173
private final JBTextField problemFilterList = new JBTextField();
7274
private final JBTextField fileExtensionBlacklist = new JBTextField();
7375

@@ -77,7 +79,7 @@ public class SettingsComponent {
7779
private final JBTextField additionalInfoSeverities = new JBTextField();
7880
private final JBTextField additionalWarningSeverities = new JBTextField();
7981
private final JBTextField additionalWeakWarningSeverities = new JBTextField();
80-
private final JBTextField additionalErrorSeverities = new JBTextField();
82+
private final JBTextField additionalErrorSeverities = new JBTextField();
8183

8284
@Getter
8385
private final JPanel settingsPanel;
@@ -133,6 +135,7 @@ public SettingsComponent() {
133135
fillProblemLabels.setSelected(settingsState.isFillProblemLabels());
134136
boldProblemLabels.setSelected(settingsState.isBoldProblemLabels());
135137
italicProblemLabels.setSelected(settingsState.isItalicProblemLabels());
138+
clickableContext.setSelected(settingsState.isClickableContext());
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(clickableContext, 0)
157161
.addSeparator()
158162
.addComponent(new JBLabel(SettingsBundle.message("settings.submenu.general")))
159163
.addLabeledComponent(new JBLabel(SettingsBundle.message("settings.activeProblemListener")), enabledListener)
@@ -264,8 +268,8 @@ public int getInlayFontSizeDelta() {
264268
// Convert the String
265269
try {
266270
val = Integer.parseInt(inlayFontSizeDeltaText.getText());
271+
} catch (NumberFormatException ignored) {
267272
}
268-
catch (NumberFormatException ignored) {}
269273

270274
if (val < 0)
271275
val = 0;
@@ -317,6 +321,14 @@ public void setItalicProblemLabels(boolean isSelected) {
317321
italicProblemLabels.setSelected(isSelected);
318322
}
319323

324+
public boolean isClickableContext() {
325+
return clickableContext.isSelected();
326+
}
327+
328+
public void setClickableContext(boolean isSelected) {
329+
clickableContext.setSelected(isSelected);
330+
}
331+
320332
public boolean isShowErrors() {
321333
return showErrors.isSelected();
322334
}
@@ -600,8 +612,7 @@ private List<Integer> getSeverityIntegerList(String text) {
600612
public int getManualScannerDelay() {
601613
try {
602614
return Math.max(Integer.parseInt(manualScannerDelay.getText()), 10);
603-
}
604-
catch (NumberFormatException e) {
615+
} catch (NumberFormatException e) {
605616
return 100;
606617
}
607618
}

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.isClickableContext() == settingsComponent.isClickableContext() &&
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.setClickableContext(settingsComponent.isClickableContext());
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.setClickableContext(state.isClickableContext());
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 clickableContext = 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.enableClickableContext=Enable clickable inline problems for IDE context actions

src/main/resources/messages/SettingsBundle_zh_CN.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ settings.useEditorFont=\u4F7F\u7528\u7F16\u8F91\u5668\u5B57\u4F53\u800C\u4E0D\u6
5151
settings.showOnlyHighestPerLine=\u4ec5\u663e\u793a\u6bcf\u884c\u4e2d\u6700\u4e25\u91cd\u7684\u95ee\u9898
5252
settings.enableHtmlStripping=Enable stripping of HTML in the messages
5353
settings.enableXmlUnescaping=Enable unescaping of XML in the messages
54+
settings.enableClickableContext=Enable clickable inline problems for IDE context actions

0 commit comments

Comments
 (0)