001package squidpony.squidgrid.gui.gdx;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import com.badlogic.gdx.Gdx;
007import com.badlogic.gdx.graphics.Color;
008
009import squidpony.SquidTags;
010import squidpony.panel.IColoredString;
011import squidpony.panel.ICombinedPanel;
012import squidpony.panel.ISquidPanel;
013import squidpony.squidgrid.gui.gdx.UIUtil.CornerStyle;
014
015/**
016 * A panel to display some text. It can either compute its size on its own or
017 * use preallocated panels to determine its size.
018 * 
019 * <p>
020 * This class is somehow doing a simpler business as {@link ButtonsPanel} but
021 * they did not get merged, because {@link ButtonsPanel} would then become a
022 * monster.
023 * </p>
024 * 
025 * <p>
026 * This class is deprecated. You should likely use {@link TextPanel} instead,
027 * because it directly relies on libgdx for rendering and hence has a more
028 * "serif" display, which is appropriate for text. Moreover {@link TextPanel}
029 * uses more recent stuff (such as {@link GDXMarkup}), supports scrolling, and
030 * is more memory efficient (no backing {@link SquidPanel} -> save on allocated
031 * arrays).
032 * </p>
033 * 
034 * @author smelC
035 * @param <T>
036 * 
037 * @deprecated Use {@link TextPanel} instead
038 * @see ButtonsPanel
039 */
040@Deprecated
041public abstract class SquidTextPanel<T extends Color> extends GroupCombinedPanel<T> {
042
043        protected List<IColoredString<T>> text;
044
045        /**
046         * The maximum width that this panel can take (in number of cells). This is
047         * a pretty much random value. Overwrite it with something computed from
048         * your game (for example, use your dungeon's width if you display it
049         * entirely, and want this panel fullscreen).
050         */
051        public int maxWidth = 8;
052
053        /**
054         * The maximum height that this panel can take (in number of cells). This is
055         * a pretty much random value. Overwrite it with something computed from
056         * your game (for example, use your dungeon's height if you display it
057         * entirely, and want this panel fullscreen).
058         */
059        public int maxHeight = 8;
060
061        /** The background color */
062        public T backgroundColor = null;
063
064        /** The border's color */
065        public T borderColor = null;
066
067        /** The style of the border */
068        public CornerStyle borderStyle = CornerStyle.ROUNDED;
069
070        public int borderSize = 0;
071        public float zoomMultiplierX = 1, zoomMultiplierY = 1;
072
073        /** Whether to use {@link IColoredString#justify(int)} on text */
074        public boolean justifyText = true;
075
076        protected int h = -1;
077
078        /**
079         * A panel with preallocated backers.
080         * 
081         * @param bg
082         * @param fg
083         */
084        public SquidTextPanel(ISquidPanel<T> bg, ISquidPanel<T> fg) {
085                super(bg, fg);
086        }
087
088        /**
089         * A panel with backers created lazily.
090         */
091        public SquidTextPanel() {
092                super();
093        }
094
095        /**
096         * Sets the text and prepares for display. This method should be called
097         * after the constructor, and before {@link #put(boolean)} or
098         * {@link #putBorder()}.
099         * 
100         * @param text
101         */
102        public void init(List<IColoredString<T>> text) {
103                this.text = new ArrayList<>(text);
104
105                prepare();
106        }
107
108        /**
109         * @param putBorders
110         *            Puts this panel on screen, but do not draw it yet (we'd need a
111         *            {@code Stage} for that).
112         */
113        public void put(boolean putBorders) {
114                if (h == -1)
115                        throw new IllegalStateException(
116                                        getClass().getSimpleName() + "::prepare() should be called before put(boolean)");
117
118                if (backgroundColor != null)
119                        fill(ICombinedPanel.What.BG, backgroundColor);
120
121                if (putBorders)
122                        putBorder();
123
124                for (int y = 0; y < h; y++) {
125                        /* Put text */
126                        putFG(0, y, text.get(y));
127                }
128        }
129
130        public void putBorder() {
131                if (bg == null)
132                        return;
133
134                if (borderColor != null && 0 < borderSize) {
135                        final float x = getX();
136                        final float y = getY();
137                        final int w = bg.gridWidth();
138                        final int h = bg.gridHeight();
139                        UIUtil.drawMarginsAround(null, x, y, w * bg.cellWidth(), h * bg.cellHeight(), borderSize,
140                                        borderColor, borderStyle, zoomMultiplierX, zoomMultiplierY);
141                }
142        }
143
144        /**
145         * This method can be left unimplemented if you give the panels at
146         * construction time.
147         * 
148         * @param width
149         *            The width that the panel must have.
150         * @param height
151         *            The height that the panel must have.
152         * @return A freshly allocated {@link ISquidPanel}.
153         */
154        protected abstract ISquidPanel<T> buildPanel(int width, int height);
155
156        protected void prepare() {
157                if (text == null)
158                        throw new NullPointerException(
159                                        "Text must be set before calling " + getClass().getSimpleName() + "::prepare()");
160
161                final int w;
162                if (bg == null) {
163                        /*
164                         * We need to allocate the panels, hence we need to compute their
165                         * sizes
166                         */
167                        final int w_ = computeRequiredWidth();
168                        if (maxWidth < w_) {
169                                /* Wrapping needed */
170                                final List<IColoredString<T>> wrapped = new ArrayList<>(text.size() * 2);
171                                for (IColoredString<T> t : text) {
172                                        final List<IColoredString<T>> wrap = t.wrap(maxWidth);
173                                        for (IColoredString<T> ics : wrap)
174                                                wrapped.add(justifyText ? ics.justify(maxWidth) : ics);
175                                }
176                                this.text = wrapped;
177                                w = maxWidth;
178                        } else
179                                w = w_;
180                        final int tsz = text.size();
181                        h = Math.min(maxHeight, tsz);
182
183                        Gdx.app.log(SquidTags.LAYOUT,
184                                        "Chosen size of " + getClass().getSimpleName() + ": " + w + "x" + h);
185
186                        setPanels(buildPanel(w, h), buildPanel(w, h));
187                } else {
188                        w = bg.gridWidth();
189                        h = bg.gridHeight();
190                        if (justifyText) {
191                                final List<IColoredString<T>> adjusted = new ArrayList<>(text.size());
192                                for (IColoredString<T> t : text)
193                                        adjusted.add(t.justify(w));
194                                text = adjusted;
195                        }
196                }
197        }
198
199        private int computeRequiredWidth() {
200                int result = 0;
201                for (IColoredString<?> ics : text)
202                        result = Math.max(result, ics.length());
203                return result;
204        }
205
206}