diff --git a/src/main/java/de/neemann/gui/ErrorMessage.java b/src/main/java/de/neemann/gui/ErrorMessage.java index 6ffdb8048..49e17d394 100644 --- a/src/main/java/de/neemann/gui/ErrorMessage.java +++ b/src/main/java/de/neemann/gui/ErrorMessage.java @@ -63,7 +63,9 @@ public class ErrorMessage implements Runnable { * @return this for call chaining */ public ErrorMessage show(Component parent) { - JOptionPane.showMessageDialog(parent, message.toString(), Lang.get("error"), JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(parent, + new LineBreaker(120).toHTML().preserveContainedLineBreaks().breakLines(message.toString()), + Lang.get("error"), JOptionPane.ERROR_MESSAGE); return this; } diff --git a/src/main/java/de/neemann/gui/LineBreaker.java b/src/main/java/de/neemann/gui/LineBreaker.java new file mode 100644 index 000000000..a5ae7394d --- /dev/null +++ b/src/main/java/de/neemann/gui/LineBreaker.java @@ -0,0 +1,137 @@ +package de.neemann.gui; + +/** + * Used to break lines. + * Created by hneemann on 29.04.17. + */ +public class LineBreaker { + private static final int DEF_COLS = 70; + + private final String label; + private final int indent; + private final int cols; + private final StringBuilder outText; + private boolean isFirst; + private int pos; + private boolean preserveLineBreaks = false; + private boolean toHTML = false; + private boolean containsLineBreak = false; + + /** + * Creates a new instance + */ + public LineBreaker() { + this(DEF_COLS); + } + + /** + * Creates a new instance + * + * @param cols number of columns to use + */ + public LineBreaker(int cols) { + this("", 0, cols); + } + + /** + * Creates a new instance + * + * @param label the lable to use in the first line + * @param indent columns to indent + * @param cols number of columns to use + */ + public LineBreaker(String label, int indent, int cols) { + this.label = label; + this.indent = indent; + this.cols = cols; + outText = new StringBuilder(label); + isFirst = true; + } + + /** + * Breaks the line + * + * @param text the text to handle + * @return the text containing the line breaks + */ + public String breakLines(String text) { + if (text == null) + return null; + + for (int i = 0; i < indent - label.length(); i++) + outText.append(" "); + + StringBuilder word = new StringBuilder(); + pos = indent; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + switch (c) { + case '\n': + if (preserveLineBreaks) { + addWord(word); + lineBreak(); + isFirst = true; + break; + } + case '\r': + case ' ': + addWord(word); + break; + default: + word.append(c); + } + } + addWord(word); + + String ret = outText.toString(); + if (containsLineBreak && toHTML) + ret = "" + ret.replace("\n", "
") + ""; + + return ret; + } + + private void addWord(StringBuilder word) { + if (word.length() > 0) { + if (pos + (isFirst ? word.length() : word.length() + 1) > cols) { + lineBreak(); + } else { + if (!isFirst) { + outText.append(" "); + pos++; + } + } + outText.append(word); + pos += word.length(); + word.setLength(0); + isFirst = false; + } + } + + private void lineBreak() { + outText.append('\n'); + for (int j = 0; j < indent; j++) + outText.append(" "); + pos = indent; + containsLineBreak = true; + } + + /** + * Preserves the contained line breaks + * + * @return this for chained calls + */ + public LineBreaker preserveContainedLineBreaks() { + this.preserveLineBreaks = true; + return this; + } + + /** + * Returns an HTML string + * + * @return this for chained calls + */ + public LineBreaker toHTML() { + this.toHTML = true; + return this; + } +} diff --git a/src/main/java/de/neemann/gui/StringUtils.java b/src/main/java/de/neemann/gui/StringUtils.java index 484bfb002..dd9ff32f6 100644 --- a/src/main/java/de/neemann/gui/StringUtils.java +++ b/src/main/java/de/neemann/gui/StringUtils.java @@ -5,7 +5,6 @@ package de.neemann.gui; */ public final class StringUtils { - private static final int DEF_COLS = 70; private StringUtils() { } @@ -53,112 +52,13 @@ public final class StringUtils { /** * Formats text to html if it contains line breaks. - * Short texts are unchanged. + * Short texts are unchanged. Ignores the containing line breaks. * * @param text the text * @return the unchanged text or a HTML segment */ public static String textToHTML(String text) { - String toolTipText = StringUtils.breakLines(text); - if (toolTipText == null) - return null; - - if (toolTipText.indexOf('\n') >= 0) - toolTipText = "" + toolTipText.replace("\n", "
") + ""; - return toolTipText; - } - - - /** - * Breaks a string separate lines, all multiple spaces and line breaks are removed. - * calls {@code breakLines(text, 60)}. - * - * @param text the text to format - * @return the formatted text - */ - public static String breakLines(String text) { - return breakLines(text, DEF_COLS); - } - - /** - * Breaks a string into separate lines, all multiple blanks and line breaks are removed. - * - * @param text the text to format - * @param cols the number of columns - * @return the formatted text - */ - public static String breakLines(String text, int cols) { - return breakLinesLabel("", 0, text, cols); - } - - /** - * Format a text width indentation - * - * @param label label to print in front of the text - * @param indent cols to indent the label - * @param text the text - * @return the formatted text - */ - public static String breakLinesLabel(String label, int indent, String text) { - return breakLinesLabel(label, indent, text, DEF_COLS); - } - - /** - * Format a text width indentation - * - * @param label label to print in front of the text - * @param indent cols to indent the label - * @param text the text - * @param cols the number of columns - * @return the formatted text - */ - public static String breakLinesLabel(String label, int indent, String text, int cols) { - if (text == null) - return null; - - StringBuilder outText = new StringBuilder(label); - for (int i = 0; i < indent - label.length(); i++) - outText.append(" "); - - StringBuilder word = new StringBuilder(); - boolean isFirst = true; - int pos = indent; - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - switch (c) { - case '\n': - case '\r': - case ' ': - pos = addWord(indent, cols, outText, word, pos, isFirst); - isFirst = false; - break; - default: - word.append(c); - } - } - addWord(indent, cols, outText, word, pos, isFirst); - return outText.toString(); - } - - private static int addWord(int indent, int cols, StringBuilder outText, StringBuilder word, int pos, boolean isFirst) { - if (word.length() > 0) { - if (pos + (isFirst ? word.length() : word.length() + 1) > cols) { - outText.append('\n'); - for (int j = 0; j < indent; j++) - outText.append(" "); - - pos = indent; - } else { - if (!isFirst) { - outText.append(" "); - pos++; - } - } - outText.append(word); - pos += word.length(); - word.setLength(0); - } - return pos; + return new LineBreaker().toHTML().breakLines(text); } } diff --git a/src/test/java/de/neemann/gui/LineBreakerTest.java b/src/test/java/de/neemann/gui/LineBreakerTest.java new file mode 100644 index 000000000..fb483330c --- /dev/null +++ b/src/test/java/de/neemann/gui/LineBreakerTest.java @@ -0,0 +1,37 @@ +package de.neemann.gui; + +import junit.framework.TestCase; + +/** + * Created by hneemann on 29.04.17. + */ +public class LineBreakerTest extends TestCase { + + public void testBreakLines() throws Exception { + assertEquals("this is a test string", new LineBreaker(60).breakLines("this \n\n is \n a test \n\r string")); + assertEquals("this is a test\nstring", new LineBreaker(14).breakLines("this \n\n is \n a test \n\r string")); + assertEquals("This is a test string. This\n" + + "is a test string. This is a\n" + + "test string.", new LineBreaker(27).breakLines("This is a test string. This is a test string. This is a test string.")); + assertEquals("this is\naWordThatIsFarToLongToFitInASingleLine\nThis is a test string", new LineBreaker(21).breakLines("this is aWordThatIsFarToLongToFitInASingleLine This is a test string")); + } + + public void testBreakLinesLabel() throws Exception { + assertEquals("a) This is a test string. This\n" + + " is a test string. This is a\n" + + " test string.", new LineBreaker("a)", 3, 30).breakLines("This is a test string. This is a test string. This is a test string.")); + } + + + public void testBreakLinesPreserve() throws Exception { + assertEquals("this is a\ntest string", new LineBreaker(60).preserveContainedLineBreaks().breakLines("this is a\n test string")); + assertEquals("this is a\ntest string. This is\na test string.", new LineBreaker(20).preserveContainedLineBreaks().breakLines("this is a\n test string. This is a test string.")); + } + + public void testBreakLinesHTML() throws Exception { + assertEquals("this is a test string", new LineBreaker(60).toHTML().breakLines("this is a\n test string")); + assertEquals("this is a
test string", new LineBreaker(60).toHTML().preserveContainedLineBreaks().breakLines("this is a\n test string")); + } + + +} \ No newline at end of file diff --git a/src/test/java/de/neemann/gui/StringUtilsTest.java b/src/test/java/de/neemann/gui/StringUtilsTest.java deleted file mode 100644 index d97be4f8f..000000000 --- a/src/test/java/de/neemann/gui/StringUtilsTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package de.neemann.gui; - -import junit.framework.TestCase; - -/** - * Created by hneemann on 29.10.16. - */ -public class StringUtilsTest extends TestCase { - - public void testBreakLines() throws Exception { - assertEquals("this is a test string", StringUtils.breakLines("this \n\n is \n a test \n\r string", 60)); - assertEquals("this is a test\nstring", StringUtils.breakLines("this \n\n is \n a test \n\r string", 14)); - assertEquals("This is a test string. This\n" + - "is a test string. This is a\n" + - "test string.", StringUtils.breakLines("This is a test string. This is a test string. This is a test string.", 27)); - assertEquals("this is\naWordThatIsFarToLongToFitInASingleLine\nThis is a test string", StringUtils.breakLines("this is aWordThatIsFarToLongToFitInASingleLine This is a test string", 21)); - } - - public void testBreakLinesLabel() throws Exception { - assertEquals("a) This is a test string. This\n" + - " is a test string. This is a\n" + - " test string.", StringUtils.breakLinesLabel("a)", 3, "This is a test string. This is a test string. This is a test string.", 30)); - } - -} \ No newline at end of file