package squidpony.squidgrid.gui.gdx; import com.badlogic.gdx.graphics.Color; import squidpony.panel.IColoredString; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * A screen designed to write some text in full screen. This class supports text * alignment (left, center, right) and text wrapping (see {@link #wrap(int)}). * <p> * You may prefer using {@link TextPanel} or sometimes {@link LinesPanel} where * you want to display more than a few words of legible wrapped text. * </p> * * @author smelC */ public abstract class AbstractTextScreen<T extends Color> extends AbstractSquidScreen<T> { /** * Can contain null members (denoting empty lines) */ protected List<IColoredString<T>> text; protected /* @Nullable */ int[] alignment; /** * @param ssi See super class * @param text The text to display. From top to bottom. Use {@code null} * members to jump lines. * <p> * Give {@code null} if you want to set it later (using * {@link #init(List, int[])}). * </p> * @param alignment How to alignment members of {@code text}. -1 for left, 0 for * center, 1 for right. The default is to align left * <p> * Give {@code null} if you want to set it later (using * {@link #init(List, int[])}). * </p> */ public AbstractTextScreen(SquidScreenInput<T> ssi, /* @Nullable */ List<IColoredString<T>> text, /* @Nullable */ int[] alignment) { super(ssi); this.text = text; this.alignment = alignment; } /** * You should call this method at most once. You should call this method * only before rendering this screen. * * @param text The text to display. From top to bottom. Use {@code null} * members to jump lines. * @param alignment How to alignment members of {@code text}. -1 for left, 0 for * center, 1 for right. The default is to align left */ public void init(List<IColoredString<T>> text, /* @Nullable */ int[] alignment) { this.text = text; this.alignment = alignment; } /** * Wraps the text inside {@code this} according to {@code width}. This * screen's text must have been set already. This, of course, preserves the * text alignment (if any). * * @param width * @throws IllegalStateException If {@code this}'s text hasn't been initialized yet. */ public void wrap(int width) { if (text == null) throw new IllegalStateException("Cannot wrap an unitialized " + getClass().getSimpleName()); final List<IColoredString<T>> tsave = text; text = new ArrayList<>(tsave.size() * 2); final int[] asave = alignment; final /* @Nullable */ List<Integer> newAlignments = asave == null ? null : new ArrayList<Integer>(asave.length * 2); int i = 0; for (IColoredString<T> t : tsave) { /* Wrap line */ if (t == null) { /* An empty line */ text.add(null); if (newAlignments != null) newAlignments.add(/* doesn't matter */ 0); } else { final List<IColoredString<T>> wrapped = t.wrap(width); final /* @Nullable */ Integer alignment = asave == null || asave.length <= i ? null : asave[i]; for (IColoredString<T> line : wrapped) { /* Add wrapped */ text.add(line); if (newAlignments != null && alignment != null) /* Keep alignment */ newAlignments.add(alignment); } } i++; } alignment = newAlignments == null ? null : toIntArray(newAlignments); } protected int[] toIntArray(Collection<Integer> l) { final int[] result = new int[l.size()]; int j = 0; for (int i : l) result[j++] = i; return result; } @Override public String toString() { final StringBuilder buf = new StringBuilder(); buf.append(getClass().getSimpleName()); if (text != null) { /* Show text */ final Iterator<? extends IColoredString<?>> it = text.iterator(); final String eol = System.getProperty("line.separator"); buf.append(eol); while (it.hasNext()) { final IColoredString<?> ics = it.next(); buf.append(ics == null ? "" : ics.present()); if (it.hasNext()) buf.append(eol); } } return buf.toString(); } }