Flow text on display

This is where you talk about the EV3 software itself, installation issues, and programming talk.

Moderators: roger, gloomyandy, skoehler

User avatar
Arqetype
New User
Posts: 6
Joined: Wed May 31, 2017 8:06 am
Location: Belgium

Flow text on display

Postby Arqetype » Mon Jul 31, 2017 12:41 pm

Hi,

When writing programs for the EV3 I always feel that getting messages properly on the screen is a hassle. When I edit the message, I often have to rework several lines of code to get things going. So I figured I could write a method that flows text onto my EV3 display.
After some trial and error I came up with a method that flows a string on the screen, breaking lines on spaces, dashes or new-line characters. If the text is longer than the 8 lines of the display, it will scroll using the DOWN button.

The method is part of an empty class so I can use it in any of my EV3 programs by calling the class with that method.

Any comments are welcome. And of course you're free to use this code in your own projects.

Arq

Screen.java

Code: Select all

package myEV3;
 /**
  * An 'empty' class to add a method that extends the LCD functionality
  * The 'flow' method will take a string and flow it on the screen
  * Text will break on spaces
  * New-line characters are kept, making paragraphs possible
  * Words also break on dashes
  * Words longer than 18 characters will break onto the next line
  * Text that flows on more than 8 lines will be scrolled through, using the down button
  *
  * @author Arqetype
  * @version 1.0
  */

import lejos.hardware.BrickFinder;
import lejos.hardware.Keys;
import lejos.hardware.lcd.LCD;
import lejos.utility.Delay;

public class Screen {
   
   private Screen() {
   }
   
   /**
    * Flow a message on the display, using word wrap, with scroll support
    * @param message String to flow on the display. New-line characters are supported.
    */
   public static void flow(String message) {
      String chopString = "";                  // define a string to store the result
      int counter = 1;                     // counter stores the number of paragraphs, default is 1
      String[] messages = {""};               // string array to store the paragraphs
      if (message.contains("\n")) {         // if new-line character is used...
         messages = message.split("\n");      // create an array of strings to store the paragraphs of the original message
         counter = messages.length;         // set the counter to the number of paragraphs
      }
      
      for (int count = 0; count < counter; count++) {   // iterate through the paragraphs
         if (counter > 1) {
            message = messages[count];            // pick the current paragraph
         }
         while (message.length() > 18) {            // while the paragraph is longer than 18 characters, chop it up
            for (int i=18; i > 0; i--) {         // start from the 18th character and go back
               if (message.substring(i,i+1).equals(" ")) {                  // find a space
                  chopString = chopString + message.substring(0, i) + "\n";      // put the first part as a separate line in the result, removing the space
                  message = message.substring(i+1);                        // remove the first part of the string
                  i = 0;                                             // stop searching
               } else if (message.substring(i,i+1).equals("-") && i < 18) {   // or find a dash
                  chopString = chopString + message.substring(0, i+1) + "\n";      // put the first part as a separate line in the result
                  message = message.substring(i+1);                        // remove the first part of the string
                  i = 0;                                             // stop searching
               }
               if (i == 1) {
                  chopString = chopString + message.substring(0, 18) + "\n";
                  message = message.substring(18);
               }
            }
         }
         if (message.length() > 0) {
            chopString = chopString + message;      // append the leftover string to the result
         }
         if (counter > 1) chopString = chopString + "\n";   // keep the original paragraphs
      }
      String[] chops = chopString.split("\n");      // create an array of strings to store all the lines
      LCD.clear();
      for (int i = 0; i < chops.length; i++) {   // iterate through the array
         if (i == chops.length-1 && i > 7) {
            LCD.drawString("" + chops[i], 0, 7);   // show the last line on the EV3 display
            Delay.msDelay(500);
         } else if (i > 6) {                     // if the text is longer than 7 lines
            LCD.drawString("\\/     ", 7, 7);   // display an arrow at the bottom
            while (BrickFinder.getLocal().getKeys().getButtons() != Keys.ID_DOWN);   // wait for the user to press the down button
            LCD.scroll();                     // scroll the screen up
            LCD.drawString("  ", 7, 6);
            LCD.drawString("" + chops[i], 0, 6);   // show the next string on line 7
            Delay.msDelay(250);                  // wait to prevent the key press be used again
         }
         else {
            LCD.drawString("" + chops[i], 0, i);   // show the line on the EV3 display
            Delay.msDelay(100);
         }
      }
      return;
   }

}


Testing code:

Code: Select all

import lejos.hardware.Button;
import myEV3.Screen;

public class DisplayScreen {

   public static void main(String[] args) {
      Screen.flow("This paragraph shows that new-line characters and dashes are supported.\n   this piece\n   shows that\n   spaces are kept\nAnd by now you've surely noticed the scroll-functionality. Califragialisticexpialodouscious is a long word that can't break, so it simply flow to the next line.");
      Button.waitForAnyPress();
      Screen.flow("This string is far too long to fit on the LCD-display. So pressing the down button will scroll the text up and add a line at the bottom. Whether it is good practice to have users press the button all the time is another question.");
      Button.waitForAnyPress();
   }
}
Arqetype, Pixar aficionado

User avatar
WizGeek
New User
Posts: 19
Joined: Sun Sep 08, 2013 9:07 pm
Location: Tampa Bay Area

Re: Flow text on display

Postby WizGeek » Fri Aug 11, 2017 5:39 pm

Awesome idea! I was so inspired that I wrote a new offering, FlowLCD, that addresses a few anomalies in Screen.flow() implementation:

Sourceforge project link: https://sourceforge.net/projects/lejos-flowlcd/

Image

Features and difference:
  • Naming matches leJOS more closely: FlowLCD.drawString("text");
  • If the flowed text fits on a single page (e.g., 8 lines on an 8 row LCD,) no scrolling occurs.
  • Automatically adjusts to different LCD text dimensions and resolutions.
  • Wiki pages explain the details of the logic and usage.
  • Fully unit tested with private test doubles.
  • Future enhancements:
    • Start at a specific (col,row)
    • constrain to a portion of the screen
    • custom scroll prompt

Code: Select all

    public static void main (String[] args) {
        FlowLCD.drawString("First Line\nSecond line will flow to the third!");
    }
WizGeek
"No-no, Fizzgig, you stay here." :cry:

User avatar
Arqetype
New User
Posts: 6
Joined: Wed May 31, 2017 8:06 am
Location: Belgium

Re: Flow text on display

Postby Arqetype » Sat Aug 12, 2017 10:23 pm

Thanks for liking my idea, WizGeek :D

And even more so for enhancing it! I will certainly take a look at your code when I have some time to spare...
Arqetype, Pixar aficionado

User avatar
WizGeek
New User
Posts: 19
Joined: Sun Sep 08, 2013 9:07 pm
Location: Tampa Bay Area

Re: Flow text on display

Postby WizGeek » Tue Aug 15, 2017 3:44 pm

WizGeek
"No-no, Fizzgig, you stay here." :cry:


Return to “EV3 Software”

Who is online

Users browsing this forum: No registered users and 1 guest