Skip to content

Friendly error messages with expanded content #771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1d200f6
Merge branch 'differentiate-offset' into sam-preview
sampottinger May 17, 2023
c7aea0e
Merge remote-tracking branch 'origin/fix-606-willrabalais' into sam-p…
sampottinger May 17, 2023
777d051
New identifier status text.
sampottinger Jul 13, 2023
e541663
Merge branch 'main' into friendly-error-messages
sampottinger Jul 13, 2023
eddab45
Merge pull request #1 from processing/main
sampottinger Jul 24, 2023
92af6cf
Add line number for friendly error messages.
sampottinger Jul 24, 2023
52eb35a
up to flexmark
WillRabalais04 Aug 15, 2023
560bfcd
Merge pull request #2 from WillRabalais04/add-line-number
sampottinger Aug 15, 2023
12e6881
Merge pull request #4 from WillRabalais04/friendly-error-messages
sampottinger Aug 15, 2023
30fa34d
Merge pull request #3 from processing/main
sampottinger Aug 15, 2023
113fc46
Fix JNA jar
sampottinger Aug 15, 2023
5242f97
Update classpath.
sampottinger Aug 17, 2023
75374bd
Add classloader elements for st and flexmark.
sampottinger Aug 17, 2023
1803389
Move friendly error libs to app deps.
sampottinger Aug 17, 2023
0f9685f
stringtemplate draft
WillRabalais04 Aug 22, 2023
fd9eb6f
pde.properties updated
WillRabalais04 Aug 22, 2023
b5ca737
sam's build file fix
WillRabalais04 Aug 22, 2023
bc1f095
excluded compiler errors from using StringTemplate
WillRabalais04 Aug 24, 2023
9f3cdcb
formatting tweaks, undoing unintentional changes to CompileErrorMessa…
WillRabalais04 Aug 27, 2023
2182b63
removed unnecessary whitespaces on Lanaguage.java
WillRabalais04 Aug 27, 2023
f447c6b
removed print statements
WillRabalais04 Aug 27, 2023
cd44531
minor formatting + javadoc comments added
WillRabalais04 Aug 28, 2023
ab52316
fixed semicolon error
WillRabalais04 Aug 28, 2023
9ba4d30
Minor fix on DefaultMessageSimplifier
sampottinger Aug 28, 2023
44b35f6
Respond to @benfry on #771.
sampottinger Sep 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,7 @@ bin-test

# VS Code Java project files
.project
.vscode/
.vscode/

# ANTLR intermediate files
java/src/processing/mode/java/preproc/.antlr
4 changes: 3 additions & 1 deletion app/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@
lib/ant-launcher.jar;
lib/flatlaf.jar;
lib/jna.jar;
lib/jna-platform.jar"
lib/jna-platform.jar;
lib/build-flexmark-all.jar;
lib/ST-4.3.4.jar"
debug="on"
nowarn="true">
<compilerarg value="-Xlint:deprecation" />
Expand Down
Binary file added app/lib/build-flexmark-all.jar
Binary file not shown.
183 changes: 176 additions & 7 deletions app/src/processing/app/ui/EditorStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,30 @@
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Desktop;

import javax.swing.*;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import javax.swing.JScrollPane;
import javax.swing.event.*;
import javax.swing.border.Border;

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.net.URI;

import java.io.IOException;

import processing.app.Platform;
import processing.app.Preferences;
import processing.core.PApplet;

import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataSet;

/**
* Panel just below the editing area that contains status messages.
Expand All @@ -68,6 +83,7 @@ public class EditorStatus extends BasicSplitPaneDivider {

int mode;
String message = "";
String friendlyMessage = "";

int messageRight;
String url;
Expand All @@ -79,6 +95,8 @@ public class EditorStatus extends BasicSplitPaneDivider {
static final int COLLAPSE_PRESSED = 4;
static final int CLIPBOARD_ROLLOVER = 5;
static final int CLIPBOARD_PRESSED = 6;
static final int MORE_INFO_ROLLOVER = 7;
static final int MORE_INFO_PRESSED = 8;
int mouseState;

Font font;
Expand All @@ -91,6 +109,8 @@ public class EditorStatus extends BasicSplitPaneDivider {
ImageIcon[] searchIcon;
ImageIcon[] collapseIcon;
ImageIcon[] expandIcon;
ImageIcon[] moreInfoIcon;


float btnEnabledAlpha;
float btnRolloverAlpha;
Expand All @@ -108,7 +128,121 @@ public class EditorStatus extends BasicSplitPaneDivider {
boolean indeterminate;
Thread thread;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add javadoc

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Field name should be friendly, the isXxxx syntax is for methods, i.e.:

public boolean isFriendly() {
    return friendly;
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CC @WillRabalais04, @benfry this has been changed to friendly. Thanks!

/**
* The friendly instance variable that determines whether a given error passed in is friendly (has additional information to be shown in a popup).
*/
public boolean friendly = false;


/*
* Popup that shows additional info about the error message that shows up in the status bar.
*/

public class FriendlyErrorPopup{

private JFrame popupFrame;
final int PROCESSING_SAYS_OFFSET = 6;

private String markdownToHtml(String target) {
MutableDataSet options = new MutableDataSet();
Parser parser = Parser.builder(options).build();
HtmlRenderer renderer = HtmlRenderer.builder(options).build();
Node document = parser.parse(target);
String html = renderer.render(document);
html = "<div style=\"font-family: Source Code PRO;color:font-size: 13px " + "#0d335a" + ";\"> <br><b>🔵Processing says:</b>" + html + "</div>" ;
return html;
}

/**
* Constructor for FriendlyErrorPopup class.
* @param messageText a String containing the full message to be simplified.
*/
public FriendlyErrorPopup(String messageText){

int firstLineIndex = messageText.indexOf("<br>");
int lineCounter = 0;
int newLineCount = 0;

String firstSentence = messageText.substring(0,firstLineIndex);
String pureText = messageText;

Pattern newLineCounter = Pattern.compile("<br>");
Pattern linkSkipper = Pattern.compile("\\[([^\\]]+)\\]\\([^\\)]+\\)");
Matcher newLineMatcher = newLineCounter.matcher(pureText);
Matcher linkSkipperMatcher = linkSkipper.matcher(pureText);

// allows for error messages with markdown links in the first line although there currently are none
while (linkSkipperMatcher.find()){
pureText = pureText.replace(linkSkipperMatcher.group(0),linkSkipperMatcher.group(1));
}

firstSentence = pureText.substring(0,pureText.indexOf("<br>"));
firstLineIndex = firstSentence.length();

int index = 0;

while (index < pureText.length()) {
lineCounter++;
int nextBreakIndex = pureText.indexOf("<br>", index);
index = (((nextBreakIndex - index) <= firstLineIndex) && nextBreakIndex != -1) ? nextBreakIndex + 4 : index + firstLineIndex;
}

pureText = pureText.replaceAll("<br>","");
messageText = markdownToHtml(messageText);

JEditorPane errorPane = new JEditorPane();
errorPane.setContentType("text/html");

JScrollPane scrollPane = new JScrollPane(errorPane);

errorPane.setFont(new Font("Source Code PRO", Font.PLAIN, 13)); //not actually necessary but it allows the window resizing to work
errorPane.setText(messageText);
errorPane.setBackground(Color.decode("#fafcff"));
errorPane.setEditable(false);

java.awt.FontMetrics fontMetrics = errorPane.getFontMetrics(errorPane.getFont());

int popupWidth = fontMetrics.stringWidth(firstSentence) - 25;
int popupHeight = (lineCounter + PROCESSING_SAYS_OFFSET) * fontMetrics.getHeight();

errorPane.addHyperlinkListener((event) -> {
HyperlinkEvent.EventType eventType = event.getEventType();
boolean linkClicked = eventType == HyperlinkEvent.EventType.ACTIVATED;
if (linkClicked) {
String url = event.getURL().toString();
URI targetUri = URI.create(url);
try {
Desktop.getDesktop().browse(targetUri);
}
catch(IOException e) {
}
}
});

JFrame frame = new JFrame("Error Details");

Border paddingBorder = BorderFactory.createEmptyBorder(0, 20, 0, 0);
Border border = BorderFactory.createLineBorder(java.awt.Color.decode("#58a2d1"), 10);
Border compoundBorder = BorderFactory.createCompoundBorder(border, paddingBorder);

errorPane.setBorder(compoundBorder);
scrollPane.setBorder(null);
frame.setSize(popupWidth, popupHeight);

JPanel containerPanel = new JPanel(new BorderLayout());
containerPanel.add(scrollPane, BorderLayout.CENTER);
frame.setContentPane(containerPanel);
frame.setVisible(true);
}
}

/**
* A constructor for the EditorStatus class. It interacts with the BasicSplitPaneUI and Editor objects
* to handle mouse events for opening URLs, copying text to the clipboard, and toggling collapse.
*
* @param ui an instance of the BasicSplitPaneUI class.
* @param editor the editor panel associated with this status.
*/
public EditorStatus(BasicSplitPaneUI ui, Editor editor) {
super(ui);
this.editor = editor;
Expand Down Expand Up @@ -222,18 +356,26 @@ void updateMouse(MouseEvent e, boolean pressed) {
} else if (url != null && mouseX > LEFT_MARGIN && mouseX < messageRight) {
mouseState = pressed ? URL_PRESSED : URL_ROLLOVER;
}
else if (mouseX > sizeW - (buttonEach * 3) && mouseX < sizeW - (2 * buttonEach)) {
mouseState = pressed ? MORE_INFO_PRESSED : MORE_INFO_ROLLOVER;
}
}
}

// only change on the rollover, no need to update on press
switch (mouseState) {
case CLIPBOARD_ROLLOVER:
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
break;
case URL_ROLLOVER:
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
break;
case COLLAPSE_ROLLOVER:
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
break;
case MORE_INFO_ROLLOVER:
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
break;
case NONE:
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
break;
Expand All @@ -250,7 +392,6 @@ static String findURL(String message) {
return null;
}


protected void updateTheme() {
urlEnabledAlpha = 255 * Theme.getInteger("status.url.enabled.alpha") / 100;
urlRolloverAlpha = 255 * Theme.getInteger("status.url.rollover.alpha") / 100;
Expand All @@ -268,6 +409,8 @@ protected void updateTheme() {
searchIcon = renderIcons("status/search", stateColors);
collapseIcon = renderIcons("status/console-collapse", stateColors);
expandIcon = renderIcons("status/console-expand", stateColors);
moreInfoIcon = renderIcons("status/more-info", stateColors);


btnEnabledAlpha = Theme.getInteger("status.button.enabled.alpha") / 100f;
btnRolloverAlpha = Theme.getInteger("status.button.rollover.alpha") / 100f;
Expand Down Expand Up @@ -310,12 +453,23 @@ public void empty() {
repaint();
}


public void message(String message, int mode) {
this.message = message;
/**
* The message method updates the message and mode instance variables and determines whether the error message being passed in is friendly or not.
* @param message the error message being passed in.
* @param mode represents whether the message is friendly or not.
*/
public void message(String message, int mode) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Javadoc


String newMessage = message;
int indexOfNewLine = message.indexOf("<br>");
if (indexOfNewLine != -1) {
this.friendly = true;
this.friendlyMessage = message;
newMessage = message.substring(0,indexOfNewLine);
}
this.message = newMessage;
this.mode = mode;

url = findURL(message);
url = findURL(newMessage);
repaint();
}

Expand Down Expand Up @@ -449,9 +603,24 @@ public void paint(Graphics g) {
alpha = btnEnabledAlpha;
}
drawButton(g, 0, glyph, alpha);

// draw more info button
if (friendly) {
ImageIcon glyph2;
glyph2 = moreInfoIcon[mode];
if (mouseState == MORE_INFO_ROLLOVER) {
alpha = btnRolloverAlpha;
} else if (mouseState == MORE_INFO_PRESSED) {
alpha = btnPressedAlpha;
FriendlyErrorPopup friendlyPopup = new FriendlyErrorPopup(friendlyMessage);
}
else {
alpha = btnEnabledAlpha;
}
drawButton(g,2,moreInfoIcon[mode],alpha);
}
}


/**
* @param pos A zero-based button index with 0 as the rightmost button
*/
Expand Down
7 changes: 6 additions & 1 deletion build/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@
<include name="app/lib/jna-platform.jar" />
<include name="app/lib/ant.jar" />
<include name="app/lib/ant-launcher.jar" />
<include name="app/lib/build-flexmark-all.jar" />
<include name="app/lib/ST-4.3.4.jar" />
<include name="app/lib/flatlaf.jar" />
</fileset>

Expand Down Expand Up @@ -534,6 +536,9 @@
<classpath file="../app/lib/jna-platform.jar" />
<classpath file="../app/lib/ant.jar" />
<classpath file="../app/lib/ant-launcher.jar" />
<classpath file="../app/lib/ant-launcher.jar" />
<classpath file="../app/lib/build-flexmark-all.jar" />
<classpath file="../app/lib/ST-4.3.4.jar" />
<classpath file="../app/lib/flatlaf.jar" />


Expand Down Expand Up @@ -1636,4 +1641,4 @@
<subant buildpath="../java/libraries/svg" target="clean-libs"/>
</target>

</project>
</project>
Loading