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.BorderLayout;
18  import java.awt.event.KeyEvent;
19  import java.awt.event.KeyListener;
20  import java.util.Map;
21  import javax.swing.JLabel;
22  import javax.swing.JPanel;
23  import javax.swing.JTable;
24  import javax.swing.JTextField;
25  import javax.swing.SwingConstants;
26  import javax.swing.table.AbstractTableModel;
27  import javax.swing.table.JTableHeader;
28  import javax.swing.table.TableColumn;
29  
30  import net.curre.prefcount.PrefCountRegistry;
31  import net.curre.prefcount.bean.GameResultBean;
32  import net.curre.prefcount.bean.PlayerStatistics;
33  import net.curre.prefcount.gui.aa.AAJLabel;
34  import net.curre.prefcount.gui.aa.AAJPanel;
35  import net.curre.prefcount.gui.aa.AAJTextField;
36  import net.curre.prefcount.gui.type.Place;
37  import net.curre.prefcount.service.ResultService;
38  import net.curre.prefcount.util.LocaleExt;
39  import net.curre.prefcount.util.Utilities;
40  
41  import info.clearthought.layout.TableLayout;
42  import info.clearthought.layout.TableLayoutConstraints;
43  import org.apache.commons.lang.StringUtils;
44  
45  /**
46   * Object of this class represents the last input panel,
47   * where point cost is entered and the final scores are
48   * computed (initiated).
49   * <p/>
50   * Created date: Apr 8, 2007
51   *
52   * @author Yevgeny Nyden
53   */
54  public class LastInputPanel extends DialogInnerPanel {
55  
56    /** Reference to the point cost text field. */
57    private JTextField pointCost;
58  
59    /** Reference to the parent dialog frame. */
60    private PlayerDialogBaseFrame dialogWindow;
61  
62    /** Reference to the Jtable with players' scores. */
63    private JTable scoreTable;
64  
65    /** Reference to the panel that holds the table and it's header. */
66    JPanel tablePanel;
67  
68    /**
69     * Constructor.
70     *
71     * @param dialogWindow Reference to the dialog window/frame.
72     */
73    public LastInputPanel(final PlayerDialogBaseFrame dialogWindow) {
74      super("pref.dialog.totalsMessage", PanelPosition.LAST);
75      this.dialogWindow = dialogWindow;
76      this.setLayout(new BorderLayout(10, 10));
77  
78      // ======== final score panel ========
79      JPanel scorePanel = new AAJPanel();
80      TableLayout layout = new TableLayout(new double[][]{
81          {5d, TableLayout.FILL, 5d},
82          {19d, TableLayout.PREFERRED, 15d, TableLayout.PREFERRED}});
83      scorePanel.setLayout(layout);
84      scorePanel.setOpaque(false);
85      layout.setVGap(5);
86      JPanel emptyPanel = new JPanel(null);
87      emptyPanel.setOpaque(false);
88      scorePanel.add(emptyPanel,
89                     new TableLayoutConstraints(0, 0, 2, 0,
90                                                TableLayoutConstraints.FULL,
91                                                TableLayoutConstraints.FULL));
92  
93      this.tablePanel = new JPanel(new BorderLayout());
94      this.tablePanel.setOpaque(false);
95      this.scoreTable = new JTable(new ScoreTableModel());
96      this.scoreTable.setOpaque(false);
97      JTableHeader header = this.scoreTable.getTableHeader();
98      this.tablePanel.add(header, BorderLayout.NORTH);
99      this.tablePanel.add(this.scoreTable, BorderLayout.CENTER);
100 
101 
102     scorePanel.add(this.tablePanel,
103                    new TableLayoutConstraints(1, 1, 1, 1,
104                                               TableLayoutConstraints.FULL,
105                                               TableLayoutConstraints.FULL));
106     this.add(scorePanel, BorderLayout.CENTER);
107 
108     emptyPanel = new JPanel(null);
109     emptyPanel.setOpaque(false);
110     scorePanel.add(emptyPanel,
111                    new TableLayoutConstraints(0, 2, 2, 2,
112                                               TableLayoutConstraints.FULL,
113                                               TableLayoutConstraints.FULL));
114 
115     //---- point cost label ----
116     JPanel costPanel = new JPanel();
117     costPanel.setOpaque(false);
118     JLabel pointCostLabel = new AAJLabel();
119     pointCostLabel.setOpaque(false);
120     pointCostLabel.setText(LocaleExt.getString("pref.dialog.pointCost"));
121     pointCostLabel.setHorizontalAlignment(SwingConstants.RIGHT);
122     costPanel.add(pointCostLabel);
123     this.pointCost = new AAJTextField();
124     this.pointCost.setHorizontalAlignment(SwingConstants.RIGHT);
125     this.pointCost.setColumns(4);
126     this.pointCost.setOpaque(false);
127     costPanel.add(this.pointCost);
128     scorePanel.add(costPanel,
129                    new TableLayoutConstraints(1, 3, 1, 3,
130                                               TableLayoutConstraints.CENTER,
131                                               TableLayoutConstraints.FULL));
132     LocaleExt.registerComponent(pointCostLabel, "pref.dialog.pointCost");
133     this.localeSensitiveComps.add(pointCostLabel);
134 
135     this.pointCost.addKeyListener(new KeyListener() {
136 
137       /** Does nothing. */
138       public void keyTyped(KeyEvent event) {
139       }
140 
141       /** Does nothing. */
142       public void keyPressed(KeyEvent event) {
143       }
144 
145       /** {@inheritDoc} */
146       public void keyReleased(KeyEvent event) {
147         try {
148           String costStr = pointCost.getText().trim();
149           double cost = 0.0;
150           if (costStr.length() != 0 &&
151               costStr.equals("0.") == false && costStr.equals("0,") == false) {
152             cost = Double.parseDouble(costStr);
153           }
154           dialogWindow.toggleErrorField(null);
155           ScoreTableModel tableModel = (ScoreTableModel) scoreTable.getModel();
156           tableModel.refreshWinnings(cost);
157         } catch (NumberFormatException e) {
158           dialogWindow.toggleErrorField("pref.dialog.errorLabel.int");
159         }
160       }
161     });
162   }
163 
164   /** {@inheritDoc} */
165   @Override
166   public void focusFirstInputField() {
167     this.pointCost.requestFocus();
168   }
169 
170   /**
171    * Validates point cost input field.
172    *
173    * @return True if point cost input filed is valid; false otherwise.
174    */
175   @Override
176   public boolean validateFields() {
177     // blank point field is considered to be valid
178     if (StringUtils.isBlank(this.pointCost.getText())) {
179       this.dialogWindow.toggleErrorField(null);
180       return true;
181     }
182     // if there is text, it must be a double and be >= 0
183     if (Utilities.validateTextField(this.pointCost, Utilities.FieldType.DOUBLE)) {
184       Double cost = Double.valueOf(this.pointCost.getText().trim());
185       if (cost < 0) {
186         this.dialogWindow.toggleErrorField("pref.dialog.errorLabel.negPointCost");
187       } else {
188         this.dialogWindow.toggleErrorField(null);
189         return true;
190       }
191     } else {
192       this.dialogWindow.toggleErrorField("pref.dialog.errorLabel.int");
193     }
194 
195     this.pointCost.requestFocus();
196     return false;
197   }
198 
199   /** Does nothing. */
200   @Override
201   public void doOnEntry() {
202     MainWindow mainWindow = PrefCountRegistry.getInstance().getMainWindow();
203     GameResultBean resultBean = PrefCountRegistry.getInstance().getGameResultBean();
204     ResultService.generateFinalResults(resultBean);
205     mainWindow.repaint();
206     refreshTable();
207   }
208 
209   /**
210    * Clearing players game data in the results bean.
211    * <p/>
212    * {@inheritDoc}
213    */
214   @Override
215   public void doOnLeave() {
216     GameResultBean resultBean = PrefCountRegistry.getInstance().getGameResultBean();
217     ResultService.clearFinalResults(resultBean);
218     refreshTable();
219   }
220 
221   /**
222    * Sets point cost text value.
223    *
224    * @param value String value to set.
225    */
226   public void setPointCostText(String value) {
227     this.pointCost.setText(value);
228   }
229 
230   /**
231    * Parses and returns the point cost text field value.
232    * This method assumes that the field has been validated.
233    *
234    * @return Point cost text input field value.
235    */
236   public int getPointCostValue() {
237     return Utilities.parseIntFromTextField(this.pointCost);
238   }
239 
240   /**
241    * Refreshes the score table - updates the header
242    * labels according to the current locale.
243    */
244   public void refreshTable() {
245     ScoreTableModel tableModel = (ScoreTableModel) this.scoreTable.getModel();
246     tableModel.refreshTable();
247 
248     this.scoreTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
249     TableColumn col = this.scoreTable.getColumnModel().getColumn(0);
250     col.setPreferredWidth(20);
251     col = this.scoreTable.getColumnModel().getColumn(1);
252     col.setPreferredWidth(75);
253     col = this.scoreTable.getColumnModel().getColumn(2);
254     col.setPreferredWidth(65);
255     col = this.scoreTable.getColumnModel().getColumn(3);
256     col.setPreferredWidth(65);
257   }
258 
259   /** Private classes and methods ********************** */
260 
261   /** Helper class that represents model for the players' score table. */
262   private class ScoreTableModel extends AbstractTableModel {
263 
264     /** Array of column resource keys. */
265     private String[] columnNames = {null,
266                                     "pref.dialog.table.player",
267                                     "pref.dialog.table.score",
268                                     "pref.dialog.table.money"};
269 
270     /** Reference to the game result bean. */
271     private GameResultBean resultBean;
272 
273     /** Cost of one point. */
274     private double costOfOnePoint = 0.0;
275 
276     /** Refreshes table data and structure. */
277     public void refreshTable() {
278       this.resultBean = PrefCountRegistry.getInstance().getGameResultBean();
279       super.fireTableDataChanged();
280       super.fireTableStructureChanged();
281     }
282 
283     /**
284      * Refreshes winnings column in the main score table.
285      *
286      * @param cost cost of one point.
287      */
288     public void refreshWinnings(double cost) {
289       this.costOfOnePoint = cost;
290       super.fireTableDataChanged();
291     }
292 
293     /**
294      * Gets column count.
295      *
296      * @return column count.
297      */
298     public int getColumnCount() {
299       return columnNames.length;
300     }
301 
302     /**
303      * Gets the row count.
304      *
305      * @return the number of players.
306      */
307     public int getRowCount() {
308       if (this.resultBean == null) {
309         return 0;
310       }
311       return resultBean.getNumberOfPlayers();
312     }
313 
314     /** {@inheritDoc} */
315     @Override
316     public String getColumnName(int col) {
317       String key = this.columnNames[col];
318       return key == null ? " " : LocaleExt.getString(key);
319     }
320 
321     /**
322      * Gets value for the given row and the given column.
323      *
324      * @param row item's row.
325      * @param col item's column.
326      * @return item's value.
327      */
328     public Object getValueAt(int row, int col) {
329       if (this.resultBean != null && this.resultBean.isFinalScoresReady()) {
330         Map<Place, PlayerStatistics> stats = this.resultBean.getPlayerStats();
331         Place place = Place.getPlaceForIndex(row);
332         PlayerStatistics player = stats.get(place);
333         switch (col) {
334           case 0:
335             return LocaleExt.getString(place.shortKey);
336           case 1:
337             return player.getPlayerName();
338           case 2:
339             return player.getFinalScoreInWhists();
340           case 3:
341             if (this.costOfOnePoint > 0.0) {
342               return ((double) player.getFinalScoreInWhists()) * this.costOfOnePoint;
343             }
344         }
345       }
346       return 0;
347     }
348 
349     /** {@inheritDoc} */
350     @Override
351     public Class getColumnClass(int c) {
352       if (this.resultBean == null) {
353         return null;
354       }
355       return getValueAt(0, c).getClass();
356     }
357 
358     /**
359      * This method always returns false.
360      * <p/>
361      * {@inheritDoc}
362      */
363     @Override
364     public boolean isCellEditable(int row, int col) {
365       return false;
366     }
367 
368     /* This method does nothing. */
369     @Override
370     public void setValueAt(Object value, int row, int col) {
371     }
372 
373   }
374 
375 }