View Javadoc
1   /*******************************************************************************
2    * jhunters: Pool League
3    * Copyright 2015 Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   ********************************************************************************/
17  package net.sourceforge.jhunters.pool.ui;
18  
19  import java.util.Iterator;
20  import java.util.List;
21  
22  import javafx.beans.value.ChangeListener;
23  import javafx.beans.value.ObservableValue;
24  import javafx.collections.FXCollections;
25  import javafx.collections.ObservableList;
26  import javafx.event.ActionEvent;
27  import javafx.event.EventHandler;
28  import javafx.geometry.Pos;
29  import javafx.print.PageOrientation;
30  import javafx.scene.Node;
31  import javafx.scene.control.Button;
32  import javafx.scene.control.ChoiceBox;
33  import javafx.scene.control.ComboBox;
34  import javafx.scene.control.Label;
35  import javafx.scene.control.Spinner;
36  import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory;
37  import javafx.scene.control.Tooltip;
38  import javafx.scene.layout.HBox;
39  import javafx.scene.layout.Priority;
40  import javafx.scene.layout.Region;
41  import javafx.scene.layout.VBox;
42  import net.sourceforge.jhunters.pool.PoolException;
43  import net.sourceforge.jhunters.pool.data.Competition;
44  import net.sourceforge.jhunters.pool.data.CompetitionList;
45  import net.sourceforge.jhunters.pool.data.DataSet;
46  import net.sourceforge.jhunters.pool.data.FixtureSet;
47  import net.sourceforge.jhunters.pool.ui.AppControl.WindowAdjustment;
48  import net.sourceforge.jhunters.pool.ui.GuiIcons.IconId;
49  import net.sourceforge.jhunters.pool.ui.ReportPanel.TableSource;
50  
51  /**
52   * Competition Panel.
53   */
54  public class CompetitionPanel
55          extends VBox {
56      /**
57       * The print button text.
58       */
59      private static final String PRINT_TEXT = GuiResource.BUTTON_PRINT.getValue();
60  
61      /**
62       * The web button text.
63       */
64      private static final String WEB_TEXT = GuiResource.BUTTON_WEB.getValue();
65  
66      /**
67       * The save button text.
68       */
69      private static final String SAVE_TEXT = GuiResource.BUTTON_SAVE.getValue();
70  
71      /**
72       * The weekNo label text.
73       */
74      private static final String WEEKNO_TEXT = GuiResource.LABEL_WEEKNO.getValue();
75  
76      /**
77       * The spinner width.
78       */
79      private static final int WIDTH_SPINNER = 80;
80  
81      /**
82       * the Control.
83       */
84      private final AppControl theControl;
85  
86      /**
87       * Competition select.
88       */
89      private final ComboBox<Competition> theCompetitionSelect;
90  
91      /**
92       * View select.
93       */
94      private final ChoiceBox<ViewSelect> theViewSelect;
95  
96      /**
97       * FixtureSet Spinner Configuration.
98       */
99      private final IntegerSpinnerValueFactory theFixtureSetConfig;
100 
101     /**
102      * FixtureSet Spinner.
103      */
104     private final HBox theFixtureSetBox;
105 
106     /**
107      * FixtureSet table.
108      */
109     private final FixtureSetTable theFixtureTable;
110 
111     /**
112      * League table.
113      */
114     private final LeagueTable theLeagueTable;
115 
116     /**
117      * Results table.
118      */
119     private final ResultsTable theResultsTable;
120 
121     /**
122      * Outlook table.
123      */
124     private final OutlookTable theOutlookTable;
125 
126     /**
127      * Outstanding table.
128      */
129     private final OutstandingTable theOutstandingTable;
130 
131     /**
132      * Participant table.
133      */
134     private final ParticipantsTable theParticipantTable;
135 
136     /**
137      * The current dataSet.
138      */
139     private DataSet theData;
140 
141     /**
142      * Selected competition.
143      */
144     private Competition theCompetition;
145 
146     /**
147      * Selected fixtureSet.
148      */
149     private FixtureSet theFixtureSet;
150 
151     /**
152      * Visible Node.
153      */
154     private Node theCurView;
155 
156     /**
157      * The save button.
158      */
159     private final Button theSaveButton;
160 
161     /**
162      * Print button.
163      */
164     private final Button thePrintButton;
165 
166     /**
167      * Source button.
168      */
169     private final Button theSourceButton;
170 
171     /**
172      * The buttons view.
173      */
174     private final HBox theButtonsView;
175 
176     /**
177      * Constructor.
178      * @param pControl the control
179      * @throws PoolException on error
180      */
181     protected CompetitionPanel(final AppControl pControl) throws PoolException {
182         /* Store the control */
183         theControl = pControl;
184 
185         /* Create a selection box for the competition */
186         theCompetitionSelect = new ComboBox<Competition>();
187 
188         /* Handle changes of value */
189         theCompetitionSelect.valueProperty().addListener(new ChangeListener<Competition>() {
190             @Override
191             public void changed(final ObservableValue<? extends Competition> pProperty,
192                                 final Competition pOldValue,
193                                 final Competition pNewValue) {
194                 setCompetition(pNewValue);
195             }
196         });
197 
198         /* Create a fixtureSet spinner */
199         theFixtureSetConfig = new IntegerSpinnerValueFactory(1, 1);
200         Spinner<Integer> mySpinner = new Spinner<Integer>(theFixtureSetConfig);
201         Label myLabel = new Label(WEEKNO_TEXT);
202         mySpinner.setPrefWidth(WIDTH_SPINNER);
203 
204         /* Handle changes of value */
205         theFixtureSetConfig.valueProperty().addListener(new ChangeListener<Integer>() {
206             @Override
207             public void changed(final ObservableValue<? extends Integer> pProperty,
208                                 final Integer pOldValue,
209                                 final Integer pNewValue) {
210                 setFixtureSet(pNewValue);
211             }
212         });
213 
214         /* Create the Spinner HBox */
215         theFixtureSetBox = new HBox();
216         theFixtureSetBox.setAlignment(Pos.CENTER);
217         theFixtureSetBox.setSpacing(2);
218         theFixtureSetBox.getChildren().addAll(myLabel, mySpinner);
219 
220         /* Create the tables */
221         theFixtureTable = new FixtureSetTable();
222         theOutstandingTable = new OutstandingTable();
223         theLeagueTable = new LeagueTable(theOutstandingTable);
224         theResultsTable = new ResultsTable();
225         theOutlookTable = new OutlookTable();
226         theParticipantTable = new ParticipantsTable();
227 
228         /* Create the View selection and populate it */
229         theViewSelect = new ChoiceBox<ViewSelect>();
230         ObservableList<ViewSelect> myItems = theViewSelect.getItems();
231         for (ViewSelect myView : ViewSelect.values()) {
232             myItems.add(myView);
233         }
234         theViewSelect.setValue(ViewSelect.FIXTURES);
235 
236         /* Handle changes of value */
237         theViewSelect.valueProperty().addListener(new ChangeListener<ViewSelect>() {
238             @Override
239             public void changed(final ObservableValue<? extends ViewSelect> pProperty,
240                                 final ViewSelect pOldValue,
241                                 final ViewSelect pNewValue) {
242                 setView(pNewValue);
243             }
244         });
245 
246         /* Create print button */
247         thePrintButton = new Button();
248         thePrintButton.setGraphic(GuiIcons.getButtonIcon(IconId.PRINT));
249         thePrintButton.setTooltip(new Tooltip(PRINT_TEXT));
250         thePrintButton.setOnAction(new EventHandler<ActionEvent>() {
251             @Override
252             public void handle(final ActionEvent e) {
253                 theControl.printNode(theCurView, theViewSelect.getValue());
254             }
255         });
256 
257         /* Create source button */
258         theSourceButton = new Button();
259         theSourceButton.setGraphic(GuiIcons.getButtonIcon(IconId.WEB));
260         theSourceButton.setTooltip(new Tooltip(WEB_TEXT));
261         theSourceButton.setOnAction(new EventHandler<ActionEvent>() {
262             @Override
263             public void handle(final ActionEvent e) {
264                 theControl.createWeb(CompetitionPanel.this, theCompetition);
265             }
266         });
267 
268         /* Create the save button */
269         theSaveButton = new Button();
270         theSaveButton.setGraphic(GuiIcons.getButtonIcon(IconId.SAVE));
271         theSaveButton.setTooltip(new Tooltip(SAVE_TEXT));
272 
273         /* Set save button action */
274         theSaveButton.setOnAction(new EventHandler<ActionEvent>() {
275             @Override
276             public void handle(final ActionEvent e) {
277                 theControl.saveToFile();
278             }
279         });
280 
281         /* Create a small HBox for the right corner */
282         theButtonsView = new HBox();
283         theButtonsView.setSpacing(2);
284         theButtonsView.getChildren().addAll(theViewSelect, thePrintButton, theSourceButton);
285 
286         /* Grow the selection buttons to the size of the print icon */
287         theViewSelect.setMaxHeight(Double.MAX_VALUE);
288         theCompetitionSelect.setMaxHeight(Double.MAX_VALUE);
289 
290         /* Create an options sub-panel */
291         HBox mySelect = new HBox();
292         Region mySpacer1 = new Region();
293         Region mySpacer2 = new Region();
294         HBox.setHgrow(mySpacer1, Priority.ALWAYS);
295         HBox.setHgrow(mySpacer2, Priority.ALWAYS);
296         mySelect.getChildren().addAll(theCompetitionSelect, mySpacer1, theFixtureSetBox, mySpacer2, theButtonsView);
297 
298         /* create panel */
299         VBox.setVgrow(theFixtureTable, Priority.ALWAYS);
300         VBox.setVgrow(theLeagueTable, Priority.ALWAYS);
301         VBox.setVgrow(theResultsTable, Priority.ALWAYS);
302         VBox.setVgrow(theOutlookTable, Priority.ALWAYS);
303         VBox.setVgrow(theOutstandingTable, Priority.ALWAYS);
304         VBox.setVgrow(theParticipantTable, Priority.ALWAYS);
305         getChildren().addAll(mySelect, theFixtureTable);
306 
307         /* Initialise the view */
308         theCurView = theFixtureTable;
309     }
310 
311     /**
312      * Set data.
313      * @param pData the dataSet
314      */
315     protected void setData(final DataSet pData) {
316         /* Store the data */
317         theData = pData;
318 
319         /* Ensure save button is in correct state */
320         final ObservableList<Node> myChildren = theButtonsView.getChildren();
321         myChildren.remove(theSaveButton);
322         if (theData.isUpdated()) {
323             myChildren.add(theSaveButton);
324         }
325 
326         /* Add listener */
327         theData.updatedProperty().addListener(
328                 new ChangeListener<Boolean>() {
329                     public void changed(final ObservableValue<? extends Boolean> pValue,
330                                         final Boolean pOldState,
331                                         final Boolean pNewState) {
332                         if (pNewState) {
333                             myChildren.add(theSaveButton);
334                         } else {
335                             myChildren.remove(theSaveButton);
336                         }
337                     }
338                 });
339 
340         /* Update the dataSet references */
341         theFixtureTable.setData(pData);
342         theLeagueTable.setData(pData);
343         theResultsTable.setData(pData);
344         theOutstandingTable.setData(pData);
345 
346         /* Update the competitions */
347         updateCompetitions();
348     }
349 
350     /**
351      * Update competitions.
352      */
353     protected void updateCompetitions() {
354         /* Access the competition list */
355         CompetitionList myCompList = theData.getCompetitions();
356         List<Competition> myList = myCompList.getCompetitions();
357 
358         /* Obtain selected value */
359         Competition mySelected = theCompetitionSelect.getValue();
360 
361         /* Clear existing values */
362         ObservableList<Competition> myValues = theCompetitionSelect.getItems();
363         myValues.clear();
364 
365         /* Loop through the competitions */
366         Iterator<Competition> myIterator = myCompList.competitionIterator();
367         while (myIterator.hasNext()) {
368             Competition myCompetition = myIterator.next();
369 
370             /* Add the competition to the list */
371             myValues.add(myCompetition);
372         }
373 
374         /* If the selected value is not present in the list */
375         if ((mySelected == null)
376             || !myList.contains(mySelected)) {
377             /* Obtain the first element in the list */
378             mySelected = myList.isEmpty()
379                                           ? null
380                                           : myList.get(0);
381         }
382 
383         /* Select the value */
384         theCompetitionSelect.setValue(mySelected);
385 
386         /* Sort the values */
387         FXCollections.sort(myValues);
388     }
389 
390     /**
391      * Set competition.
392      * @param pCompetition the competition
393      */
394     private void setCompetition(final Competition pCompetition) {
395         /* Store the competition */
396         theCompetition = pCompetition;
397 
398         /* Update fixtures */
399         if (pCompetition != null) {
400             theCompetition.processFixtures();
401         }
402 
403         /* Update the fixtureSet reference */
404         theFixtureTable.setCompetition(pCompetition);
405 
406         /* Check to see whether the fixtureSet will change */
407         Integer mySet = theFixtureSetConfig.getValue();
408         boolean bChange = mySet != 1;
409 
410         /* Set the maximum number of weeks */
411         theFixtureSetConfig.setMax(pCompetition != null
412                                                         ? pCompetition.getNumWeeks()
413                                                         : 1);
414 
415         /* select the first fixture set */
416         theFixtureSetConfig.setValue(1);
417 
418         /* If the fixtureSet was already 1 then we need to manually select */
419         if (!bChange) {
420             setFixtureSet(1);
421         }
422 
423         /* Update the league table */
424         theLeagueTable.setCompetition(pCompetition);
425 
426         /* Update the results table */
427         theResultsTable.setCompetition(pCompetition);
428 
429         /* Update the outlook table */
430         theOutlookTable.setCompetition(pCompetition);
431 
432         /* Update the outstanding table */
433         theOutstandingTable.setCompetition(pCompetition);
434 
435         /* Update the participant table */
436         theParticipantTable.setCompetition(pCompetition);
437     }
438 
439     /**
440      * Set fixtureSet.
441      * @param pFixtureSet the fixtureSet
442      */
443     private void setFixtureSet(final Integer pFixtureSet) {
444         /* Obtain the fixtureSet */
445         theFixtureSet = theCompetition != null
446                                                ? theCompetition.getFixtureSet(pFixtureSet)
447                                                : null;
448 
449         /* Declare the fixtureSet to the table */
450         theFixtureTable.setFixtureSet(theFixtureSet);
451     }
452 
453     /**
454      * Set view.
455      * @param pView the view
456      */
457     private void setView(final ViewSelect pView) {
458         /* Remove existing view */
459         ObservableList<Node> myChildren = getChildren();
460         myChildren.remove(theCurView);
461         WindowAdjustment myAdjust;
462 
463         /* Switch on view */
464         switch (pView) {
465             case FIXTURES:
466                 myAdjust = new WindowAdjustment(theFixtureTable, theCurView);
467                 theCurView = theFixtureTable;
468                 theFixtureSetBox.setVisible(true);
469                 break;
470             case TABLE:
471                 myAdjust = new WindowAdjustment(theLeagueTable, theCurView);
472                 theCurView = theLeagueTable;
473                 theFixtureSetBox.setVisible(false);
474                 break;
475             case RESULTS:
476                 myAdjust = new WindowAdjustment(theResultsTable, theCurView);
477                 theCurView = theResultsTable;
478                 theFixtureSetBox.setVisible(false);
479                 break;
480             case OUTLOOK:
481                 myAdjust = new WindowAdjustment(theOutlookTable, theCurView);
482                 theCurView = theOutlookTable;
483                 theFixtureSetBox.setVisible(false);
484                 break;
485             case OUTSTANDING:
486                 myAdjust = new WindowAdjustment(theOutstandingTable, theCurView);
487                 theCurView = theOutstandingTable;
488                 theFixtureSetBox.setVisible(false);
489                 break;
490             case PARTICIPANTS:
491             default:
492                 myAdjust = new WindowAdjustment(theParticipantTable, theCurView);
493                 theCurView = theParticipantTable;
494                 theFixtureSetBox.setVisible(false);
495                 break;
496         }
497 
498         /* Add the view to the table */
499         myChildren.add(theCurView);
500 
501         /* Adjust the stage */
502         theControl.adjustStage(myAdjust);
503     }
504 
505     /**
506      * Obtain source for view.
507      * @param pView the view
508      * @return the corresponding source
509      */
510     protected TableSource getSource(final ViewSelect pView) {
511         switch (pView) {
512             case FIXTURES:
513                 return theFixtureTable;
514             case TABLE:
515                 return theLeagueTable;
516             case RESULTS:
517                 return theResultsTable;
518             case OUTSTANDING:
519                 return theOutstandingTable;
520             case PARTICIPANTS:
521                 return theParticipantTable;
522             default:
523                 return null;
524         }
525     }
526 
527     /**
528      * View selection.
529      */
530     protected enum ViewSelect {
531         /**
532          * Fixtures.
533          */
534         FIXTURES,
535 
536         /**
537          * Table.
538          */
539         TABLE,
540 
541         /**
542          * Outstanding.
543          */
544         OUTSTANDING,
545 
546         /**
547          * Results.
548          */
549         RESULTS,
550 
551         /**
552          * Outlook.
553          */
554         OUTLOOK,
555 
556         /**
557          * Participants.
558          */
559         PARTICIPANTS;
560 
561         /**
562          * The String name.
563          */
564         private String theName;
565 
566         @Override
567         public String toString() {
568             /* If we have not yet loaded the name */
569             if (theName == null) {
570                 /* Load the name */
571                 theName = GuiResource.getKeyForViewSelect(this).getValue();
572             }
573 
574             /* return the name */
575             return theName;
576         }
577 
578         /**
579          * Determine orientation for printing.
580          * @return the orientation
581          */
582         protected PageOrientation getOrientation() {
583             switch (this) {
584                 case RESULTS:
585                     return PageOrientation.LANDSCAPE;
586                 default:
587                     return PageOrientation.PORTRAIT;
588             }
589         }
590     }
591 }