001package squidpony.squidgrid.gui.gdx; 002 003import com.badlogic.gdx.assets.AssetManager; 004import com.badlogic.gdx.graphics.Color; 005import com.badlogic.gdx.graphics.Texture.TextureFilter; 006import com.badlogic.gdx.graphics.g2d.TextureRegion; 007 008import squidpony.IColorCenter; 009 010/** 011 * An almost-concrete implementation of {@link IPanelBuilder}. This class makes 012 * the assumption that font files are only available for square and even sizes. 013 * The only method to implement is {@link #fontfile(int)} that must return the 014 * name of the file where a font of a given size lives. 015 * 016 * <p> 017 * I think this class should be generalized so that it supports cell width and 018 * cell height that are proportional (for example: a height that is the double 019 * of the width), but not to arbitrary combinations. In that case 020 * {@link #adjustCellSize(int)} would become impossible to implement. 021 * </p> 022 * 023 * @author smelC 024 */ 025public abstract class SquidPanelBuilder extends IPanelBuilder.Skeleton { 026 027 protected final /* @Nullable */ IColorCenter<Color> icc; 028 public final /* @Nullable */ AssetManager assetManager; 029 030 protected final int smallestFont; 031 protected final int largestFont; 032 033 protected final int fontOffset; 034 035 /** 036 * The color passed to {@link SquidPanel#setDefaultForeground(Color)} when 037 * building a new panel, if non-{@code null}. 038 */ 039 protected /* @Nullable */ Color defaultForegroundColor; 040 041 /** 042 * @param smallestFont 043 * The smallest font size available. 044 * @param largestFont 045 * The largest font size available. 046 * @param fontOffset 047 * This offset is added to the cell size when computing the font 048 * size for a given cell size. 049 * @param icc 050 * The color center to give to 051 * {@link SquidPanel#setColorCenter(IColorCenter)}, or 052 * {@code null} not to call this method. 053 * @param assetManager 054 */ 055 public SquidPanelBuilder(int smallestFont, int largestFont, int fontOffset, 056 /* @Nullable */IColorCenter<Color> icc, /* @Nullable */ AssetManager assetManager) { 057 this.icc = icc; 058 this.assetManager = assetManager; 059 060 this.smallestFont = smallestFont; 061 this.largestFont = largestFont; 062 this.fontOffset = fontOffset; 063 } 064 065 @Override 066 public SquidPanel buildScreenWide(int screenWidth, int screenHeight, int desiredCellSize, 067 /* @Nullable */ TextCellFactory tcf) { 068 final int sz = adjustCellSize(desiredCellSize); 069 final int hcells = screenWidth / sz; 070 final int vcells = screenHeight / sz; 071 final SquidPanel result = buildByCells(hcells, vcells, sz, sz, tcf); 072 final int vmargin = screenHeight - (vcells * sz); 073 final int hmargin = screenWidth - (hcells * sz); 074 result.setPosition(hmargin / 2, vmargin / 2); 075 /* TODO smelC Draw margins ? */ 076 return result; 077 } 078 079 @Override 080 public SquidPanel buildByCells(int hCells, int vCells, int cellWidth, int cellHeight, 081 /*@Nullable*/ TextCellFactory tcf_) { 082 final TextCellFactory tcf; 083 final boolean freshTCF; 084 if (tcf_ != null && tcf_.width() == cellWidth && tcf_.height() == cellHeight) { 085 /* Can reuse */ 086 tcf = tcf_; 087 freshTCF = false; 088 } else { 089 tcf = new TextCellFactory(assetManager); 090 freshTCF = true; 091 } 092 093 if (cellWidth == cellHeight) { 094 final int fontSize = fontSizeForCellSize(cellWidth); 095 if (!hasFontOfSize(fontSize)) 096 throw new IllegalStateException("No font of size " + fontSize); 097 098 final String fontFile = fontfile(fontSize); 099 if (freshTCF) { 100 /* Initialize it */ 101 tcf.font(fontFile); 102 for (TextureRegion region : tcf.font().getRegions()) 103 region.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); 104 tcf.initByFont(); 105 tcf.width(cellWidth).height(cellHeight); 106 } 107 final SquidPanel result = new SquidPanel(hCells, vCells, tcf); 108 if (icc != null) 109 result.setColorCenter(icc); 110 if (defaultForegroundColor != null) 111 result.setDefaultForeground(defaultForegroundColor); 112 return result; 113 } else 114 throw new IllegalStateException("Non square cells aren't supported"); 115 } 116 117 /** 118 * @param sz 119 * @return A valid cell size, as close as possible to {@code sz}. 120 */ 121 @Override 122 public int adjustCellSize(int sz) { 123 int result = sz % 2 == 0 ? sz : sz - 1; 124 if (hasFontForCellOfSize(result)) 125 return result; 126 if (cellSizeTooBig(sz)) { 127 final int offset = -2; 128 while (0 < result) { 129 result += offset; 130 if (hasFontForCellOfSize(result)) 131 return result; 132 } 133 throw new IllegalStateException("There's a bug in the computation of the cell size"); 134 } else if (cellSizeTooSmall(result)) { 135 final int offset; 136 offset = 2; 137 while (/* It's better to stop one day */ result < 512) { 138 result += offset; 139 if (hasFontForCellOfSize(result)) 140 return result; 141 } 142 throw new IllegalStateException("There's a bug in the computation of the cell size"); 143 } else 144 throw new IllegalStateException("There's a bug in the computation of the cell size"); 145 146 } 147 148 @Override 149 public boolean cellSizeTooBig(int cellSize) { 150 return largestFont < fontSizeForCellSize(cellSize); 151 } 152 153 @Override 154 public boolean cellSizeTooSmall(int cellSize) { 155 return fontSizeForCellSize(cellSize) < smallestFont; 156 } 157 158 @Override 159 public boolean hasFontForCellOfSize(int cellSize) { 160 return hasFontOfSize(fontSizeForCellSize(cellSize)); 161 } 162 163 @Override 164 public int fontSizeForCellSize(int cellSize) { 165 return cellSize + fontOffset; 166 } 167 168 @Override 169 public boolean hasFontOfSize(int sz) { 170 return sz % 2 == 0 && smallestFont <= sz && sz <= largestFont; 171 } 172 173 /** 174 * @param c 175 * The default foreground color that freshly created panels will 176 * have. Can be {@code null} to use {@link SquidPanel}'s default. 177 */ 178 public void setDefaultForegroundColor(/* @Nullable */Color c) { 179 this.defaultForegroundColor = c; 180 } 181 182 /** 183 * @param sz 184 * @return The name of the file where the font of size {@code sz} lives. 185 */ 186 protected abstract String fontfile(int sz); 187}