001package squidpony.squidgrid.gui.gdx; 002 003import com.badlogic.gdx.graphics.Color; 004import squidpony.panel.IColoredString; 005 006import java.util.ArrayList; 007import java.util.Collection; 008import java.util.Iterator; 009import java.util.List; 010 011/** 012 * A screen designed to write some text in full screen. This class supports text 013 * alignment (left, center, right) and text wrapping (see {@link #wrap(int)}). 014 * 015 * <p> 016 * If you use libgdx {@link Color} as your type of color, you can use a less 017 * abstract subtype: {@link TextScreen}. 018 * </p> 019 * 020 * @author smelC 021 * 022 * @see TextScreen 023 */ 024public abstract class AbstractTextScreen<T extends Color> extends AbstractSquidScreen<T> { 025 026 /** Can contain null members (denoting empty lines) */ 027 protected List<IColoredString<T>> text; 028 protected /* @Nullable */ int[] alignment; 029 030 /** 031 * @param ssi 032 * See super class 033 * @param text 034 * The text to display. From top to bottom. Use {@code null} 035 * members to jump lines. 036 * 037 * <p> 038 * Give {@code null} if you wanna set it later (using 039 * {@link #init(List, int[])}). 040 * </p> 041 * @param alignment 042 * How to alignment members of {@code text}. -1 for left, 0 for 043 * center, 1 for right. The default is to align left 044 * 045 * <p> 046 * Give {@code null} if you wanna set it later (using 047 * {@link #init(List, int[])}). 048 * </p> 049 */ 050 public AbstractTextScreen(SquidScreenInput<T> ssi, /* @Nullable */ List<IColoredString<T>> text, 051 /* @Nullable */ int[] alignment) { 052 super(ssi); 053 this.text = text; 054 this.alignment = alignment; 055 } 056 057 /** 058 * You should call this method at most once. You should call this method 059 * only before rendering this screen. 060 * 061 * @param text 062 * The text to display. From top to bottom. Use {@code null} 063 * members to jump lines. 064 * @param alignment 065 * How to alignment members of {@code text}. -1 for left, 0 for 066 * center, 1 for right. The default is to align left 067 */ 068 public void init(List<IColoredString<T>> text, /* @Nullable */ int[] alignment) { 069 this.text = text; 070 this.alignment = alignment; 071 } 072 073 /** 074 * Wraps the text inside {@code this} according to {@code width}. This 075 * screen's text must have been set already. This, of course, preserves the 076 * text alignment (if any). 077 * 078 * @param width 079 * 080 * @throws IllegalStateException 081 * If {@code this}'s text hasn't been initialized yet. 082 */ 083 public void wrap(int width) { 084 if (text == null) 085 throw new IllegalStateException("Cannot wrap an unitialized " + getClass().getSimpleName()); 086 087 final List<IColoredString<T>> tsave = text; 088 text = new ArrayList<>(tsave.size() * 2); 089 final int[] asave = alignment; 090 final /* @Nullable */ List<Integer> newAlignments = asave == null ? null 091 : new ArrayList<Integer>(asave.length * 2); 092 int i = 0; 093 for (IColoredString<T> t : tsave) { 094 /* Wrap line */ 095 if (t == null) { 096 /* An empty line */ 097 text.add(null); 098 if (newAlignments != null) 099 newAlignments.add(/* doesn't matter */ 0); 100 } else { 101 final List<IColoredString<T>> wrapped = t.wrap(width); 102 final /* @Nullable */Integer alignment = asave == null || asave.length <= i ? null : asave[i]; 103 for (IColoredString<T> line : wrapped) { 104 /* Add wrapped */ 105 text.add(line); 106 if (newAlignments != null && alignment != null) 107 /* Keep alignment */ 108 newAlignments.add(alignment); 109 } 110 } 111 i++; 112 } 113 alignment = newAlignments == null ? null : toIntArray(newAlignments); 114 } 115 116 protected int[] toIntArray(Collection<Integer> l) { 117 final int[] result = new int[l.size()]; 118 int j = 0; 119 for (int i : l) 120 result[j++] = i; 121 return result; 122 } 123 124 @Override 125 public String toString() { 126 final StringBuilder buf = new StringBuilder(); 127 buf.append(getClass().getSimpleName()); 128 if (text != null) { 129 /* Show text */ 130 final Iterator<? extends IColoredString<?>> it = text.iterator(); 131 final String eol = System.getProperty("line.separator"); 132 buf.append(eol); 133 while (it.hasNext()) { 134 final IColoredString<?> ics = it.next(); 135 buf.append(ics == null ? "" : ics.present()); 136 if (it.hasNext()) 137 buf.append(eol); 138 } 139 } 140 return buf.toString(); 141 } 142 143}