View Javadoc

1   /**
2    * This program is free software: you can redistribute it and/or modify
3    * it under the terms of the GNU General Public License as published by
4    * the Free Software Foundation, version 3.
5    *
6    * This program is distributed in the hope that it will be useful,
7    * but WITHOUT ANY WARRANTY; without even the implied warranty of
8    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9    * GNU General Public License for more details.
10   *
11   * You should have received a copy of the GNU General Public License
12   * along with this program. If not, see <http://www.gnu.org/licenses/>.
13   */
14  
15  package net.curre.prefcount.gui;
16  
17  import java.awt.*;
18  import java.awt.geom.Ellipse2D;
19  import java.awt.geom.GeneralPath;
20  import java.awt.geom.Line2D;
21  import java.awt.geom.Point2D;
22  import java.awt.geom.Rectangle2D;
23  import java.util.List;
24  import java.util.Map;
25  
26  import net.curre.prefcount.bean.GameResultBean;
27  import net.curre.prefcount.bean.PlayerStatistics;
28  import net.curre.prefcount.bean.Settings;
29  import net.curre.prefcount.gui.theme.skin.PrefSkin;
30  import net.curre.prefcount.gui.aa.AAJPanel;
31  import net.curre.prefcount.service.LafThemeService;
32  import net.curre.prefcount.service.SettingsService;
33  import net.curre.prefcount.util.Utilities;
34  
35  /**
36   * Object of this class represents the score board panel
37   * where all players scores and totals are drawn.
38   * <p/>
39   * Created date: Apr 8, 2007
40   *
41   * @author Yevgeny Nyden
42   */
43  public class ScoreBoardPanel extends AAJPanel {
44  
45    /** Package protected game scores bean. */
46    GameResultBean results;
47  
48    /**
49     * Reference to the map that stores/computes
50     * locations for all items on the board.
51     */
52    ScoreBoardLocationsMap locationsMap;
53  
54    /**
55     * Constructor with a GameResultBean argument.
56     *
57     * @param results Game results bean.
58     */
59    public ScoreBoardPanel(GameResultBean results) {
60      Settings settings = SettingsService.getSettings();
61      super.setSize(settings.getDialogFrameWidth(), settings.getDialogFrameHeight());
62      this.results = results;
63      locationsMap = new ScoreBoardLocationsMap(this);
64    }
65  
66    /**
67     * {@inheritDoc}
68     *
69     * @throws UnsupportedOperationException If number of player is not supported.
70     */
71    public void paintComponent(Graphics g) {
72  
73      Graphics2D g2 = (Graphics2D) g;
74  //    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
75      final PrefSkin skin = LafThemeService.getInstance().getCurrentSkin();
76  
77      final float width = (float) super.getSize().getWidth();
78      final float height = (float) super.getSize().getHeight();
79      locationsMap.computeLocations();
80  
81      final float centerX = width / 2f;
82      final float centerY = height / 2f;
83      final float incrX = centerX / 3f;
84      final float incrY = centerY / 3f - 7f;
85  
86      final float oneThirdX = width / 3f;
87      final float twoThirdX = oneThirdX * 2f;
88      final float oneThirdY = height / 3f;
89      final float twoThirdY = oneThirdY * 2f;
90  
91      // setting main backgound (outer area)
92      g2.setColor(skin.getMainBackgroundColor());
93      g2.fillRect(0, 0, (int) Math.ceil(width), (int) Math.ceil(height));
94  
95      // drawing nice borders
96      Color bordColor = Utilities.createDarkerColor(skin.getMainBackgroundColor(), 20);
97      g2.setColor(bordColor);
98      g2.draw(new Rectangle2D.Double(4d, 4d, width - 8d, height - 8d));
99      bordColor = Utilities.createDarkerColor(bordColor, 20);
100     g2.setColor(bordColor);
101     g2.draw(new Rectangle2D.Double(5d, 5d, width - 10d, height - 10d));
102 
103     // painting score board backgound
104     g2.setPaint(skin.getBoardBackgroundPaint());
105     g2.fillRect(6, 6, (int) width - 11, (int) height - 11);
106 
107     // player sections lines
108     prepareBoardLinePen(g2, skin);
109     Ellipse2D e = new Ellipse2D.Double();
110     e.setFrameFromCenter(centerX + 1d, centerY, centerX + 32d, centerY + 30d);
111     g2.draw(e);
112     g2.draw(new Rectangle2D.Double(incrX, 7d + incrY, twoThirdX, twoThirdY));
113     g2.draw(new Rectangle2D.Double(oneThirdX - 7d, oneThirdY - 7d,
114                                    oneThirdX + 14d, oneThirdY + 14d));
115 
116     prepareBoardLinePen(g2, skin);
117 
118     // section borders and players information
119     List<PlayerStatistics> statistics = results.getPlayerStats();
120     if (statistics.size() == 3) {
121       // drawing section borders (assuming the pen didn't change)
122       g2.drawLine(7, (int) height - 7, (int) centerX, (int) centerY);
123       g2.drawLine((int) width - 7, (int) height - 7, (int) centerX, (int) centerY);
124       g2.drawLine((int) centerX, (int) centerY, (int) centerX, 7);
125       g2.drawLine((int) centerX, (int) (height - incrY - 7), (int) centerX, (int) height - 7);
126       g2.drawLine(7, 7, (int) incrX, (int) incrY + 7);
127       g2.drawLine((int) width - 7, 7, (int) (width - incrX), (int) incrY + 7);
128 
129       // displaying player 0 information
130       drawPlayerScores(0, g2, skin, statistics.get(0), 1, 2);
131 
132       // displaying player 1 information
133       drawPlayerScores(1, g2, skin, statistics.get(1), 0, 2);
134 
135       // displaying player 2 information
136       drawPlayerScores(2, g2, skin, statistics.get(2), 0, 1);
137 
138     } else if (statistics.size() == 4) {
139       // drawing section borders (assuming the pen didn't change)
140       g2.drawLine(7, 7, (int) width - 7, (int) height - 7);
141       g2.drawLine((int) width - 7, 7, 7, (int) height - 7);
142 
143       g2.drawLine(7, (int) oneThirdY, (int) incrX, (int) oneThirdY);
144       g2.drawLine(7, (int) twoThirdY, (int) incrX, (int) twoThirdY);
145       g2.drawLine((int) (width - incrX), (int) oneThirdY, (int) width - 7, (int) oneThirdY);
146       g2.drawLine((int) (width - incrX), (int) twoThirdY, (int) width - 7, (int) twoThirdY);
147 
148       g2.drawLine((int) oneThirdX, 7, (int) oneThirdX, (int) incrY + 7);
149       g2.drawLine((int) twoThirdX, 7, (int) twoThirdX, (int) incrY + 7);
150       g2.drawLine((int) oneThirdX, (int) (height - incrY - 7), (int) oneThirdX, (int) height - 7);
151       g2.drawLine((int) twoThirdX, (int) (height - incrY - 7), (int) twoThirdX, (int) height - 7);
152 
153       // displaying player 0 information
154       drawPlayerScores(0, g2, skin, statistics.get(0), 1, 2, 3);
155 
156       // displaying player 1 information
157       drawPlayerScores(1, g2, skin, statistics.get(1), 0, 2, 3);
158 
159       // displaying player 2 information
160       drawPlayerScores(2, g2, skin, statistics.get(2), 0, 1, 3);
161 
162       // displaying player 3 information
163       drawPlayerScores(3, g2, skin, statistics.get(3), 0, 1, 2);
164 
165     } else {
166       throw new UnsupportedOperationException(statistics.size() + " number of players is NOT supported!");
167     }
168   }
169 
170   /***************** PRIVATE STATIC METHODS *******************/
171 
172   /**
173    * Method to draw all player scores. Note that the pen
174    * (Color, Fond, Stroke) will not be saved after this
175    * method returns.
176    *
177    * @param currPlayerInd Current player index.
178    * @param g2            Graphics object to use.
179    * @param skin          Current skin.
180    * @param stats         Player statistics bean.
181    * @param otherPlayers  Indexes of other players.
182    */
183   private void drawPlayerScores(int currPlayerInd,
184                                 Graphics2D g2,
185                                 PrefSkin skin,
186                                 PlayerStatistics stats,
187                                 int... otherPlayers) {
188     Map<String, Point2D.Float> locations = locationsMap.getLocationsMap(currPlayerInd);
189     preparePlayerNamePen(g2, skin);
190     Point.Float point = locations.get(ScoreBoardLocationsMap.PLAYER_NAME);
191     g2.drawString(stats.getPlayerNameLetter(), (float) point.getX(), (float) point.getY());
192     preparePlayerScorePen(g2, skin);
193     point = locations.get(ScoreBoardLocationsMap.PLAYER_MOUNT);
194     g2.drawString(getStringFromInt(stats.getMountain()), (float) point.getX(), (float) point.getY());
195     point = locations.get(ScoreBoardLocationsMap.PLAYER_BULLET);
196     g2.drawString(getStringFromInt(stats.getBullet()), (float) point.getX(), (float) point.getY());
197     for (int other : otherPlayers) {
198       point = locations.get(ScoreBoardLocationsMap.VISTS_FOR + other);
199       g2.drawString(stats.getVistsStringForPlayer(other), (float) point.getX(), (float) point.getY());
200     }
201     if (results.isFinalScoresReady()) {
202       for (int other : otherPlayers) {
203         drawVistSaldo(g2, stats.getVistSaldoMap().get(other),
204                       locations.get(ScoreBoardLocationsMap.VIST_SALDO_FOR + other), false);
205       }
206       drawVistSaldo(g2, stats.getVistSaldoMap().get(currPlayerInd),
207                     locations.get(ScoreBoardLocationsMap.VIST_SALDO), true);
208       boolean isVertical = (otherPlayers.length == 3);
209       if (currPlayerInd == 0 || currPlayerInd == 2) {
210         isVertical = !isVertical;
211       }
212       drawNewMountain(g2, stats, locations.get(ScoreBoardLocationsMap.PLAYER_MOUNT), isVertical);
213       drawNewBullet(g2, stats, locations.get(ScoreBoardLocationsMap.PLAYER_BULLET), isVertical);
214       preparePlayerTotalsPen(g2, skin);
215       drawFinalMountain(g2, stats, locations.get(ScoreBoardLocationsMap.FINAL_MOUNT));
216       drawFinalScore(g2, stats, locations.get(ScoreBoardLocationsMap.FINAL_SCORE));
217     }
218   }
219 
220   /**
221    * Draws a number with an oval or a rectangle around it at the
222    * given position (x, y) - used for displaying players vist saldo.
223    *
224    * @param g2         Graphics2D to use.
225    * @param saldo      Number to draw.
226    * @param point      Coordinates.
227    * @param totalSaldo True indicates that this is a total saldo,
228    *                   therefore, a rectangle is drawn around the number;
229    *                   false draws an oval instead.
230    */
231   private static void drawVistSaldo(Graphics2D g2, final Integer saldo,
232                                     final Point2D.Float point, boolean totalSaldo) {
233     final String str = saldo.toString();
234     final int width = 16 + str.length() * 14;
235     final int adjustX = 10 + (saldo < 0 ? 4 : 0);
236     final float x = point.x;
237     final float y = point.y;
238     g2.drawString(str, x, y);
239     if (totalSaldo) {
240       g2.drawRect((int) x - adjustX, (int) y - 16, width, 20);
241     } else {
242       g2.drawOval((int) x - adjustX, (int) y - 16, width, 20);
243     }
244   }
245 
246   /**
247    * Draws new bullet value (target bullet).
248    *
249    * @param g2       Graphics2D to use.
250    * @param stats    Player statistics object.
251    * @param point    Coordinates of the original bullet string.
252    * @param vertical If true, indicates vertical positioning
253    *                 of the string; false - horizontal positioning.
254    */
255   private void drawNewBullet(Graphics2D g2, PlayerStatistics stats,
256                              final Point2D.Float point, final boolean vertical) {
257     final String str = getStringFromInt(results.getTargetBullet());
258     final float width = (float) Utilities.determineSizeOfString(g2, stats.getBullet().toString()).getWidth();
259     final float x = point.x;
260     final float y = point.y;
261     Stroke tempStroke = g2.getStroke();
262     g2.setStroke(new BasicStroke(2));
263     g2.draw(new Line2D.Float(x, y - 2f, x + width + 2f, y - 8f));
264     g2.setStroke(tempStroke);
265     if (vertical) {
266       g2.drawString(str, x + 6f, y + 20f);
267     } else {
268       g2.drawString(str, x + 7f + width, y);
269     }
270   }
271 
272   /**
273    * Draws new mountain value.
274    *
275    * @param g2       Graphics2D to use.
276    * @param stats    Player statistics object.
277    * @param point    Coordinates of the original mountain string.
278    * @param vertical If true, indicates vertical positioning
279    *                 of the string; false - horizontal positioning.
280    */
281   private static void drawNewMountain(Graphics2D g2, PlayerStatistics stats,
282                                       final Point2D.Float point, final boolean vertical) {
283     final String str = getStringFromInt(stats.getNewMountain());
284     final float width = (float) Utilities.determineSizeOfString(g2, stats.getMountain().toString()).getWidth();
285     final float x = point.x;
286     final float y = point.y;
287     Stroke tempStroke = g2.getStroke();
288     g2.setStroke(new BasicStroke(2));
289     g2.draw(new Line2D.Float(x, y - 2f, x + width + 2f, y - 8f));
290     g2.setStroke(tempStroke);
291     if (vertical) {
292       g2.drawString(str, x + 6f, y + 20f);
293     } else {
294       g2.drawString(str, x + 7f + width, y);
295     }
296   }
297 
298   /**
299    * Draws new mountain value.
300    *
301    * @param g2    Graphics2D to use.
302    * @param stats Player statistics object.
303    * @param point Point's coordinates.
304    */
305   private static void drawFinalMountain(Graphics2D g2, PlayerStatistics stats,
306                                         final Point2D.Float point) {
307     int mount = stats.getFinalMountainInVists();
308     final String str = String.valueOf(mount);
309     final int width = 16 + str.length() * 14;
310     final int adjustX = 10 + (mount < 0 ? 4 : 0);
311     final float x = point.x;
312     final float y = point.y;
313     g2.drawString(str, x, y);
314     g2.drawRect((int) x - adjustX, (int) y - 16, width, 20);
315   }
316 
317   /**
318    * Draws final score and a thombus around it
319    * at the given location.
320    *
321    * @param g2    Graphics2D to use.
322    * @param stats Player statistics object.
323    * @param point Point's coordinates.
324    */
325   private static void drawFinalScore(Graphics2D g2, PlayerStatistics stats,
326                                      final Point2D.Float point) {
327     final float x = point.x;
328     final float y = point.y;
329     final String score = stats.getFinalScoreInVists().toString();
330     g2.drawString(score, x, y);
331 
332     final Dimension corrSize = Utilities.determineSizeOfString(g2, score);
333     final float halfWidth = (float) corrSize.getWidth() / 2;
334     final float halfHeight = (float) corrSize.getHeight() / 2;
335     final float realCenterX = x + halfWidth;
336     final float realCenterY = y - halfHeight + 5f;
337     final float leftX = realCenterX - halfWidth - 15f;
338     final float rightX = realCenterX + halfWidth + 15f;
339     final float upY = realCenterY - halfHeight - 15f;
340     final float downY = realCenterY + halfHeight + 15f;
341 
342     GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 4);
343     polygon.moveTo(realCenterX, upY);
344     polygon.lineTo(rightX, realCenterY);
345     polygon.lineTo(realCenterX, downY);
346     polygon.lineTo(leftX, realCenterY);
347     polygon.closePath();
348     g2.draw(polygon);
349   }
350 
351   /**
352    * Converts passed Integer to a String appending a '.'
353    * ant the end; if the passed value is null an empty string
354    * is returned.
355    *
356    * @param value Inetger value to convert.
357    * @return String representation of the passed integer
358    *         with a period at the end or an empty string
359    *         if the passed integer is null.
360    */
361   private static String getStringFromInt(final Integer value) {
362     return value == null ? "" : value.toString() + ".";
363   }
364 
365   /**
366    * Sets the color and stroke on the graphics object
367    * for the score board lines painting.
368    *
369    * @param g2   Graphics object.
370    * @param skin Current prefcount skin.
371    */
372   private static void prepareBoardLinePen(Graphics2D g2, PrefSkin skin) {
373     g2.setStroke(skin.getBoardLineStroke());
374     g2.setColor(skin.getBoardLineColor());
375   }
376 
377   /**
378    * Sets the color, stroke and font on the graphics
379    * object for the player name painting.
380    *
381    * @param g2   Graphics object.
382    * @param skin Current prefcount skin.
383    */
384   private static void preparePlayerNamePen(Graphics2D g2, PrefSkin skin) {
385     g2.setColor(skin.getPlayerNameColor());
386     g2.setFont(skin.getPlayerNameFont());
387     g2.setStroke(skin.getPlayerNameStroke());
388   }
389 
390   /**
391    * Sets the color, stroke and font on the graphics
392    * object for the player score painting.
393    *
394    * @param g2   Graphics object.
395    * @param skin Current prefcount skin.
396    */
397   private static void preparePlayerScorePen(Graphics2D g2, PrefSkin skin) {
398     g2.setColor(skin.getPlayerScoreColor());
399     g2.setFont(skin.getPlayerScoreFont());
400     g2.setStroke(skin.getPlayerScoreStroke());
401   }
402 
403   /**
404    * Sets the color, stroke and font on the graphics
405    * object for the player (score) totals painting.
406    *
407    * @param g2   Graphics object.
408    * @param skin Current prefcount skin.
409    */
410   private static void preparePlayerTotalsPen(Graphics2D g2, PrefSkin skin) {
411     g2.setColor(skin.getPlayerTotalsColor());
412     g2.setFont(skin.getPlayerTotalsFont());
413     g2.setStroke(skin.getPlayerTotalsStroke());
414   }
415 
416 }