001package squidpony.panel; 002 003import squidpony.IColorCenter; 004import squidpony.annotation.Beta; 005 006/** 007 * The combination of two panels, one to color the background, the other to 008 * write characters on the foreground. 009 * 010 * <p> 011 * <ul> 012 * <li> 013 * There is a very generic implementation in this file: {@link Impl} that you 014 * should use if you're combining generic things. 015 * </li> 016 * <li> 017 * There is a libgdx-{@code Group} based implementation that offers more 018 * features and that you should likely use if you're a new user (in 019 * squidlib-gdx). 020 * </li> 021 * </ul> 022 * 023 * @author smelC 024 * 025 * @param <T> 026 * The type of colors. 027 */ 028@Beta 029public interface ICombinedPanel<T> { 030 031 /** 032 * Puts the character {@code c} at {@code (x, y)}. 033 * 034 * @param x 035 * @param y 036 * @param c 037 */ 038 void putFG(int x, int y, char c); 039 040 /** 041 * Puts the character {@code c} at {@code (x, y)} with some {@code color}. 042 * 043 * @param x 044 * @param y 045 * @param c 046 * @param color 047 */ 048 void putFG(int x, int y, char c, T color); 049 050 /** 051 * Puts the given string horizontally with the first character at the given 052 * offset. 053 * 054 * Does not word wrap. Characters that are not renderable (due to being at 055 * negative offsets or offsets greater than the grid size) will not be shown 056 * but will not cause any malfunctions. 057 * 058 * @param x 059 * the x coordinate of the first character 060 * @param y 061 * the y coordinate of the first character 062 * @param string 063 * the characters to be displayed 064 * @param color 065 * the color to draw the characters 066 */ 067 void putFG(int x, int y, String string, T color); 068 069 /** 070 * Puts the given string horizontally with the first character at the given 071 * offset. 072 * 073 * Does not word wrap. Characters that are not renderable (due to being at 074 * negative offsets or offsets greater than the grid size) will not be shown 075 * but will not cause any malfunctions. 076 * 077 * @param x 078 * the x coordinate of the first character 079 * @param y 080 * the y coordinate of the first character 081 * @param cs 082 * the text to be displayed, with its color. 083 */ 084 void putFG(int x, int y, IColoredString<T> cs); 085 086 /** 087 * Puts the color {@code c} at {@code (x, y)}. 088 * 089 * @param x 090 * @param y 091 * @param color 092 */ 093 void putBG(int x, int y, T color); 094 095 /** 096 * Puts {@code c} at (x, y), using {@code fgc} for {@code c} and {@code bgc} 097 * for the background. 098 */ 099 void put(int x, int y, char c, T bgc, T fgc); 100 101 /** 102 * Put {@code cs} at (x,y) using {@code bgc} for the background. 103 */ 104 void put(int x, int y, T bgc, IColoredString<T> cs); 105 106 /** 107 * Put {@code cs} at (x,y) using {@code bgc} for the background and 108 * {@code fgc} for the foreground. 109 */ 110 void put(int x, int y, String s, T bgc, T fgc); 111 112 /** 113 * @param what 114 * What to fill 115 * @param color 116 * The color to put within this panel. 117 */ 118 void fill(What what, T color); 119 120 /** 121 * @return Returns true if there are animations running when this method is 122 * called. 123 */ 124 boolean hasActiveAnimations(); 125 126 /** 127 * Changes the underlying {@link IColorCenter}. 128 * 129 * @param icc 130 */ 131 void setColorCenter(IColorCenter<T> icc); 132 133 /** 134 * What to fill 135 * 136 * @author smelC 137 */ 138 enum What { 139 BG, 140 FG, 141 BG_AND_FG; 142 143 /** 144 * @return {@code true} if {@code this} contains the background. 145 */ 146 public boolean hasBG() { 147 switch (this) { 148 case BG: 149 case BG_AND_FG: 150 return true; 151 case FG: 152 return false; 153 } 154 throw new IllegalStateException("Unmatched value: " + this); 155 } 156 157 /** 158 * @return {@code true} if {@code this} contains the foreground. 159 */ 160 public boolean hasFG() { 161 switch (this) { 162 case FG: 163 case BG_AND_FG: 164 return true; 165 case BG: 166 return false; 167 } 168 throw new IllegalStateException("Unmatched value: " + this); 169 } 170 } 171 172 /** 173 * A generic implementation of {@link ICombinedPanel}. Useful to combine 174 * things. If you're a new user, you likely would prefer the more specific 175 * implementation using libGDX, GroupCombinedPanel, instead. 176 * 177 * @author smelC 178 * 179 * @param <T> 180 * The type of colors. 181 */ 182 @Beta 183 class Impl<T> implements ICombinedPanel<T> { 184 185 protected final ISquidPanel<T> bg; 186 protected final ISquidPanel<T> fg; 187 188 protected final int width; 189 protected final int height; 190 191 /** 192 * @param bg 193 * The backing background panel. 194 * @param fg 195 * The backing foreground panel. 196 * @param width 197 * The width of this panel, used for {@link #fillBG(Object)} 198 * (so that it fills within {@code [0, width)}). 199 * @param height 200 * The height of this panel, used for {@link #fillBG(Object)} 201 * (so that it fills within {@code [0, height)}). 202 * @throws IllegalStateException 203 * In various cases of errors regarding sizes of panels. 204 */ 205 public Impl(ISquidPanel<T> bg, ISquidPanel<T> fg, int width, int height) { 206 if (bg.gridWidth() != fg.gridWidth()) 207 throw new IllegalStateException( 208 "Cannot build a combined panel with backers of different widths"); 209 if (bg.gridHeight() != fg.gridHeight()) 210 throw new IllegalStateException( 211 "Cannot build a combined panel with backers of different heights"); 212 213 this.bg = bg; 214 this.fg = fg; 215 if (width < 0) 216 throw new IllegalStateException("Cannot create a panel with a negative width"); 217 this.width = width; 218 if (height < 0) 219 throw new IllegalStateException("Cannot create a panel with a negative height"); 220 this.height = height; 221 } 222 223 @Override 224 public void putFG(int x, int y, char c) { 225 fg.put(x, y, c); 226 } 227 228 @Override 229 public void putFG(int x, int y, char c, T color) { 230 fg.put(x, y, c, color); 231 } 232 233 @Override 234 public void putFG(int x, int y, String string, T foreground) { 235 fg.put(x, y, string, foreground); 236 } 237 238 @Override 239 public void putFG(int x, int y, IColoredString<T> cs) { 240 fg.put(x, y, cs); 241 } 242 243 @Override 244 public void putBG(int x, int y, T color) { 245 bg.put(x, y, color); 246 } 247 248 @Override 249 public void put(int x, int y, char c, T bgc, T fgc) { 250 bg.put(x, y, bgc); 251 fg.put(x, y, c, fgc); 252 } 253 254 @Override 255 public void put(int x, int y, T bgc, IColoredString<T> cs) { 256 final int l = cs.length(); 257 for (int i = x; i < l && i < width; i++) 258 bg.put(i, y, bgc); 259 fg.put(x, y, cs); 260 } 261 262 @Override 263 public void put(int x, int y, String s, T bgc, T fgc) { 264 final int l = s.length(); 265 for (int i = x; i < l && i < width; i++) 266 bg.put(i, y, bgc); 267 fg.put(x, y, s, fgc); 268 } 269 270 @Override 271 public void fill(What what, T color) { 272 /* Nope, not Doom's Big Fucking Gun */ 273 final boolean bfg = what.hasFG(); 274 final boolean bbg = what.hasBG(); 275 for (int x = 0; x < width; x++) { 276 for (int y = 0; y < height; y++) { 277 if (bfg) 278 putFG(x, y, ' ', color); 279 if (bbg) 280 putBG(x, y, color); 281 } 282 } 283 } 284 285 @Override 286 public boolean hasActiveAnimations() { 287 return bg.hasActiveAnimations() || fg.hasActiveAnimations(); 288 } 289 290 @Override 291 public void setColorCenter(IColorCenter<T> icc) { 292 bg.setColorCenter(icc); 293 fg.setColorCenter(icc); 294 } 295 296 } 297 298}