Skip to content

Instantly share code, notes, and snippets.

@rbrick
Last active October 21, 2018 02:40
Show Gist options
  • Select an option

  • Save rbrick/19636182062754980ab99ea6747757fc to your computer and use it in GitHub Desktop.

Select an option

Save rbrick/19636182062754980ab99ea6747757fc to your computer and use it in GitHub Desktop.
import java.util.concurrent.TimeUnit;
public final class TestClass {
public static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
"In in pellentesque sem, quis iaculis sapien. Quisque ut velit vel ex facilisis euismod in et " +
"neque. Donec eget ex in nisl dapibus congue id ultricies odio. Nulla et nibh nec nunc pretium aliquet " +
"in quis augue. Aenean sit amet nisi eu tortor malesuada tincidunt. Fusce in pulvinar sapien, vitae mollis orci. " +
"Donec sed purus luctus, convallis metus sit amet, volutpat turpis. Sed quis nunc id nisl fringilla tincidunt a ut urna.";
public static void main(String[] args) throws InterruptedException {
Marquee marquee = Marquee.newMarquee()
.text(LOREM_IPSUM) // the text we want to scroll
.limit(32) // The character limit to display
.interval(500, TimeUnit.MILLISECONDS) // The update interval
.create();
for (String text : marquee) {
System.out.println('\r' + text);
// This will constantly be rewriting the line, and not look nice.
// To fix this, we sleep for a few hundred milliseconds
Thread.sleep(250);
}
}
}
import com.google.common.base.Preconditions;
import javax.annotation.Nonnull;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
public final class Marquee implements Iterator<String>, Iterable<String> {
public interface Factory {
@Nonnull
Marquee create();
}
private String text;
private int limit;
private long interval;
private String currentText;
private int currentIndex;
private long lastSent;
private Marquee(String text, int limit, long interval) {
this.text = text;
this.limit = limit;
this.interval = interval;
}
@Override
public boolean hasNext() {
return true;
}
@Override
public String next() {
if (this.text.length() - 1 <= limit) {
return this.text;
} else {
// only update the current text if the time has passed.
if (System.nanoTime() >= lastSent + interval || lastSent <= 0) {
if (this.currentIndex >= this.text.length() - 1) {
this.currentIndex = 0;
}
int finalLimit = Math.min(this.currentIndex + limit, this.text.length());
if (finalLimit <= this.text.length()) {
if (finalLimit == this.text.length()) {
int diff = (this.currentIndex + limit) - this.text.length();
String endText = text.substring(this.currentIndex, finalLimit);
String startText = text.substring(0, diff);
this.currentText = String.valueOf(endText + " " + startText).substring(0, limit);
} else {
this.currentText = text.substring(this.currentIndex, finalLimit);
}
}
this.currentIndex++;
if (this.interval > 0) {
this.lastSent = System.nanoTime();
}
}
return this.currentText;
}
}
@Override
@Nonnull
public Iterator<String> iterator() {
return this;
}
@Nonnull
public static Builder newMarquee() {
return new Builder();
}
public static final class Builder implements Factory {
private String text;
private int limit;
private long interval;
public Builder text(String text) {
Preconditions.checkArgument(text != null && !text.isEmpty(), "text cannot be null or empty!");
this.text = text;
return this;
}
public Builder limit(int limit) {
Preconditions.checkArgument(limit >= 16 && limit <= 32, "limit not in range (must be between 16 & 32)!");
this.limit = limit;
return this;
}
public Builder interval(long time, TimeUnit unit) {
this.interval = unit.toNanos(time);
return this;
}
@Override
@Nonnull
public Marquee create() {
return new Marquee(this.text, this.limit, this.interval);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment