diff --git a/app/src/processing/app/Util.java b/app/src/processing/app/Util.java index 8e2063337..dd959dc08 100644 --- a/app/src/processing/app/Util.java +++ b/app/src/processing/app/Util.java @@ -25,6 +25,8 @@ package processing.app; import java.io.*; import java.nio.file.Files; import java.util.Enumeration; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.zip.*; import processing.core.PApplet; @@ -53,7 +55,7 @@ public class Util { static public byte[] loadBytesRaw(File file) throws IOException { int size = (int) file.length(); FileInputStream input = new FileInputStream(file); - byte buffer[] = new byte[size]; + byte[] buffer = new byte[size]; int offset = 0; int bytesRead; while ((bytesRead = input.read(buffer, offset, size-offset)) != -1) { @@ -668,10 +670,73 @@ public class Util { } - static public final boolean containsNonASCII(String what) { + static public boolean containsNonASCII(String what) { for (char c : what.toCharArray()) { if (c < 32 || c > 127) return true; } return false; } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + static public String sanitizeHtmlTags(String str) { + return str.replaceAll("<", "<") + .replaceAll(">", ">"); + } + + + /** + * This has a [link](http://example.com/) in [it](http://example.org/). + * + * Becomes... + * + * This has a link in it. + */ + static public String markDownLinksToHtml(String str) { + Pattern p = Pattern.compile("\\[(.*?)]\\((.*?)\\)"); + Matcher m = p.matcher(str); + + StringBuilder sb = new StringBuilder(); + + int start = 0; + while (m.find(start)) { + sb.append(str, start, m.start()); + + String text = m.group(1); + String url = m.group(2); + + sb.append(""); + sb.append(text); + sb.append(""); + + start = m.end(); + } + sb.append(str.substring(start)); + return sb.toString(); + } + + + static public String removeMarkDownLinks(String str) { + StringBuilder name = new StringBuilder(); + if (str != null) { + int parentheses = 0; + for (char c : str.toCharArray()) { + if (c == '[' || c == ']') { + // pass + } else if (c == '(') { + parentheses++; + } else if (c == ')') { + parentheses--; + } else if (parentheses == 0) { + name.append(c); + } + } + } + return name.toString(); + } } diff --git a/app/src/processing/app/contrib/DetailPanel.java b/app/src/processing/app/contrib/DetailPanel.java index 7e2ed37cf..c42fb40c9 100644 --- a/app/src/processing/app/contrib/DetailPanel.java +++ b/app/src/processing/app/contrib/DetailPanel.java @@ -26,9 +26,6 @@ import java.awt.event.*; import java.io.File; import java.net.MalformedURLException; import java.net.URL; -import java.util.Iterator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.Date; import java.text.DateFormat; @@ -39,10 +36,7 @@ import javax.swing.text.Document; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.StyleSheet; -import processing.app.Base; -import processing.app.Language; -import processing.app.Messages; -import processing.app.Platform; +import processing.app.*; import processing.app.ui.Editor; import processing.app.ui.Toolkit; @@ -275,8 +269,8 @@ class DetailPanel extends JPanel { rightPane.add(barButtonCardPane); - // Set the minimum size of this pane to be the sum of the height of the - // progress bar and install button + // Set the minimum size of this pane to be the sum + // of the height of the progress bar and install button Dimension dim = new Dimension(BUTTON_WIDTH, installRemoveButton.getPreferredSize().height); @@ -419,7 +413,7 @@ class DetailPanel extends JPanel { String authorList = contrib.getAuthorList(); if (authorList != null && !authorList.isEmpty()) { - desc.append(toHtmlLinks(contrib.getAuthorList())); + desc.append(Util.markDownLinksToHtml(contrib.getAuthorList())); } desc.append("

"); @@ -434,8 +428,8 @@ class DetailPanel extends JPanel { if (sentence == null || sentence.isEmpty()) { sentence = String.format("%s", Language.text("contrib.errors.description_unavailable")); } else { - sentence = sanitizeHtmlTags(sentence); - sentence = toHtmlLinks(sentence); + sentence = Util.sanitizeHtmlTags(sentence); + sentence = Util.markDownLinksToHtml(sentence); } desc.append(sentence); } @@ -466,7 +460,9 @@ class DetailPanel extends JPanel { } else { String latestVersion = contribListing.getLatestPrettyVersion(contrib); if (latestVersion != null) { - versionText.append("New version (" + latestVersion + ") available."); + versionText.append("New version (") + .append(latestVersion) + .append(") available."); } else { versionText.append("New version available."); } @@ -542,9 +538,7 @@ class DetailPanel extends JPanel { installProgressBar.setVisible(true); ContribProgressBar downloadProgress = new ContribProgressBar(installProgressBar) { - public void finishedAction() { - // nothing? - } + public void finishedAction() { } public void cancelAction() { finishInstall(false); @@ -593,7 +587,7 @@ class DetailPanel extends JPanel { * Should be called whenever this component is selected (clicked on) * or unselected, even if it is already selected. */ - public void setSelected(boolean isSelected) { + void setSelected(boolean selected) { // Only enable hyperlinks if this component is already selected. // Why? Because otherwise if the user happened to click on what is // now a hyperlink, it will be opened as the mouse is released. @@ -607,30 +601,19 @@ class DetailPanel extends JPanel { installRemoveButton.setEnabled(installRemoveButton.getText().equals(Language.text("contrib.remove")) || contribListing.listDownloadSuccessful()); reorganizePaneComponents(); - /* - descriptionPane.removeHyperlinkListener(NULL_HYPERLINK_LISTENER); - descriptionPane.removeHyperlinkListener(conditionalHyperlinkOpener); - if (isSelected()) { - descriptionPane.addHyperlinkListener(conditionalHyperlinkOpener); -// descriptionPane.setEditable(false); - } else { - descriptionPane.addHyperlinkListener(NULL_HYPERLINK_LISTENER); -// descriptionPane.setEditable(true); - } - */ - // Update style of hyperlinks - setSelectionStyle(descriptionPane, isSelected()); + //setSelectionStyle(descriptionPane, selected); - alreadySelected = isSelected(); + alreadySelected = selected; } - public boolean isSelected() { + boolean isSelected() { return listPanel.getSelectedPanel() == this; } + @Override public void setForeground(Color fg) { super.setForeground(fg); @@ -644,50 +627,6 @@ class DetailPanel extends JPanel { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - static String sanitizeHtmlTags(String stringIn) { - stringIn = stringIn.replaceAll("<", "<"); - stringIn = stringIn.replaceAll(">", ">"); - return stringIn; - } - - - /** - * This has a [link](http://example.com/) in [it](http://example.org/). - * - * Becomes... - * - * This has a link in it. - */ - static String toHtmlLinks(String stringIn) { - Pattern p = Pattern.compile("\\[(.*?)]\\((.*?)\\)"); - Matcher m = p.matcher(stringIn); - - StringBuilder sb = new StringBuilder(); - - int start = 0; - while (m.find(start)) { - sb.append(stringIn, start, m.start()); - - String text = m.group(1); - String url = m.group(2); - - sb.append(""); - sb.append(text); - sb.append(""); - - start = m.end(); - } - sb.append(stringIn.substring(start)); - return sb.toString(); - } - - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - /** * Sets coloring based on whether installed or not; * also makes ugly blue HTML links into the specified color (black). @@ -702,7 +641,7 @@ class DetailPanel extends JPanel { // slightly grayed when installed String c = (installed && !selected) ? "#555555" : "#000000"; stylesheet.addRule("body { color:" + c + "; }"); - stylesheet.addRule("a { color:" + c + "; }"); + stylesheet.addRule("a { color:" + c + "; text-decoration:underline }"); } } @@ -721,6 +660,7 @@ class DetailPanel extends JPanel { } + /* static void setSelectionStyle(JTextPane textPane, boolean selected) { Document doc = textPane.getDocument(); if (doc instanceof HTMLDocument) { @@ -733,6 +673,7 @@ class DetailPanel extends JPanel { } } } + */ public void install() { @@ -795,7 +736,7 @@ class DetailPanel extends JPanel { if (isModeActive(contrib)) { updateButton.setEnabled(true); - } else { + //} else { // TODO: remove or uncomment if the button was added //listPanel.contributionTab.restartButton.setVisible(true); } @@ -842,7 +783,7 @@ class DetailPanel extends JPanel { if (isModeActive(contrib)) { updateButton.setEnabled(true); - } else { + //} else { // TODO: remove or uncomment if the button was added //contributionTab.restartButton.setVisible(true); } @@ -856,14 +797,12 @@ class DetailPanel extends JPanel { LocalContribution installed = getLocalContrib(); installed.setDeletionFlag(false); contribListing.replaceContribution(contrib, contrib); // ?? - Iterator contribsListIter = contribListing.allContributions.iterator(); - boolean toBeRestarted = false; - while (contribsListIter.hasNext()) { - Contribution contribElement = contribsListIter.next(); + // boolean toBeRestarted = false; + for (Contribution contribElement : contribListing.allContributions) { if (contrib.getType().equals(contribElement.getType())) { if (contribElement.isDeletionFlagged() || contribElement.isUpdateFlagged()) { - toBeRestarted = !toBeRestarted; +// toBeRestarted = !toBeRestarted; break; } } diff --git a/app/src/processing/app/contrib/ListPanel.java b/app/src/processing/app/contrib/ListPanel.java index 43958c4c9..25194b112 100644 --- a/app/src/processing/app/contrib/ListPanel.java +++ b/app/src/processing/app/contrib/ListPanel.java @@ -33,6 +33,7 @@ import javax.swing.table.*; import processing.app.Base; import processing.app.Platform; +import processing.app.Util; import processing.app.ui.Toolkit; @@ -358,14 +359,14 @@ implements Scrollable, ContributionListing.ChangeListener { FontMetrics fontMetrics = table.getFontMetrics(boldFont); int colSize = table.getColumnModel().getColumn(1).getWidth(); int currentWidth = fontMetrics.stringWidth(contribution.getName() + " | ..."); - String sentence = contribution.getSentence(); + String sentence = Util.removeMarkDownLinks(contribution.getSentence()); StringBuilder text = new StringBuilder("") .append(contribution.getName()); - if (sentence == null) { + if (sentence.length() == 0) { text.append(""); } else { int index; @@ -391,7 +392,7 @@ implements Scrollable, ContributionListing.ChangeListener { label.setIcon(foundationIcon); } String authorList = contribution.getAuthorList(); - String name = removeMarkDownLinks(authorList); + String name = Util.removeMarkDownLinks(authorList); label.setText(name); label.setHorizontalAlignment(SwingConstants.LEFT); label.setForeground(Color.BLACK); @@ -420,7 +421,7 @@ implements Scrollable, ContributionListing.ChangeListener { if (this == STATUS || this == STATUS_NO_HEADER) { return comparator.thenComparingInt(ListPanel::getContributionStatusRank); } else if (this == AUTHOR) { - return comparator.thenComparing(contribution -> removeMarkDownLinks(contribution.getAuthorList())); + return comparator.thenComparing(contribution -> Util.removeMarkDownLinks(contribution.getAuthorList())); } else { // default case, or this == NAME return comparator.thenComparing(Contribution::getName, String.CASE_INSENSITIVE_ORDER); } @@ -558,26 +559,6 @@ implements Scrollable, ContributionListing.ChangeListener { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - static String removeMarkDownLinks(String str) { - StringBuilder name = new StringBuilder(); - if (str != null) { - int parentheses = 0; - for (char c : str.toCharArray()) { - if (c == '[' || c == ']') { - // pass - } else if (c == '(') { - parentheses++; - } else if (c == ')') { - parentheses--; - } else if (parentheses == 0) { - name.append(c); - } - } - } - return name.toString(); - } - - // Thread: EDT public void contributionAdded(final Contribution contribution) { if (!panelByContribution.containsKey(contribution)) { @@ -682,9 +663,9 @@ implements Scrollable, ContributionListing.ChangeListener { ? UIManager.getBorder("List.oddRowBackgroundPainter") : UIManager.getBorder("List.evenRowBackgroundPainter"); } else { - bgColor = oddRow - ? new Color(219, 224, 229) - : new Color(241, 241, 241); + bgColor = oddRow ? + new Color(219, 224, 229) : + new Color(241, 241, 241); } panel.setForeground(fgColor); diff --git a/todo.txt b/todo.txt index efd0a7001..e71a5de4d 100755 --- a/todo.txt +++ b/todo.txt @@ -16,6 +16,13 @@ X bump JNA from 5.8.0 to 5.10.0 X remove "Illegal reflective access" warning on Linux X https://github.com/processing/processing4/issues/207 +manager +X contrib list entry in the table sometimes contains markdown +X at least hide the syntax parts (and show the text) +_ description panel in contribs contains markdown +_ cursor even changes to link, but the links don't have colors, +_ and no links open when clicked + contribs X select entire line when doing Edit > Copy on an empty selection X https://github.com/processing/processing4/pull/100 @@ -40,6 +47,7 @@ design/next _ update theme _ icon for exported app _ icon for document +_ update the foundation icons _ redesign of the Contribution Manager _ identify coloring for icons _ how much of theme to inherit