Coverage Report - com.liquidatom.derbyscore.ui.ControlWindowTeamListener
 
Classes in this File Line Coverage Branch Coverage Complexity
ControlWindowTeamListener
0%
0/25
0%
0/2
3.286
ControlWindowTeamListener$UpdateRunnable
0%
0/45
0%
0/30
3.286
 
 1  
 package com.liquidatom.derbyscore.ui;
 2  
 
 3  
 import com.liquidatom.derbyscore.domain.Team;
 4  
 import com.liquidatom.derbyscore.domain.TeamListener;
 5  
 import java.awt.EventQueue;
 6  
 import java.awt.GraphicsConfiguration;
 7  
 import java.awt.GraphicsEnvironment;
 8  
 import java.awt.Transparency;
 9  
 import java.awt.image.BufferedImage;
 10  
 import java.io.Serializable;
 11  
 import java.util.ArrayList;
 12  
 import java.util.Collection;
 13  
 import java.util.List;
 14  
 import javax.annotation.concurrent.Immutable;
 15  
 import javax.annotation.concurrent.ThreadSafe;
 16  
 import javax.swing.ImageIcon;
 17  
 import javax.swing.JButton;
 18  
 import javax.swing.JComponent;
 19  
 import javax.swing.JLabel;
 20  
 import javax.swing.JSpinner;
 21  
 import javax.swing.event.ChangeListener;
 22  
 
 23  
 /**
 24  
  * A listener implementation which will listen for changes to a teams state and update some common user-interface
 25  
  * elements in conjunction with the event.
 26  
  *
 27  
  * @author Russell Francis (russ@metro-six.com)
 28  
  */
 29  
 @Immutable
 30  
 @ThreadSafe
 31  0
 public class ControlWindowTeamListener implements TeamListener, Serializable {
 32  
     static private final long serialVersionUID = 1L;
 33  
     static private final int LOGO_WIDTH = 120;
 34  
     static private final int LOGO_HEIGHT = 120;
 35  
    
 36  
     final private JButton teamButton;
 37  
     final private JLabel teamLabel;
 38  
     final private JSpinner scoreSpinner;
 39  
     final private JSpinner jamSpinner;
 40  
     final private JSpinner timeoutSpinner;
 41  
 
 42  
     /**
 43  
      * Construct a new listener which will update the provided user-interface elements if they are provided.
 44  
      *
 45  
      * @param teamButton The button which representes the team.
 46  
      * @param teamLabel The label containing the team name.
 47  
      * @param scoreSpinner The JSpinner which holds the teams current score.
 48  
      * @param jamSpinner The JSpinner which holds the teams score for the current jam.
 49  
      * @param timeoutSpinner The JSpinner which holds the number of timeouts for the team.
 50  
      */
 51  
     public ControlWindowTeamListener(
 52  
             final JButton teamButton, 
 53  
             final JLabel teamLabel, 
 54  
             final JSpinner scoreSpinner, 
 55  
             final JSpinner jamSpinner, 
 56  
             final JSpinner timeoutSpinner)
 57  
     {
 58  0
         super();
 59  0
         this.teamButton = teamButton;
 60  0
         this.teamLabel = teamLabel;
 61  0
         this.scoreSpinner = scoreSpinner;
 62  0
         this.jamSpinner = jamSpinner;
 63  0
         this.timeoutSpinner = timeoutSpinner;
 64  0
     }
 65  
 
 66  
     /**
 67  
      * Invoked when state on the team has been changed.
 68  
      *
 69  
      * @param team The team whose state has recently changed.
 70  
      */
 71  
     public void onChanged(final Team team) {
 72  0
         if (team != null) {
 73  0
             team.readLock().lock();
 74  
             try {
 75  0
                 UpdateRunnable updater = newUpdateRunnable(team);
 76  0
                 EventQueue.invokeLater(updater);
 77  
             }
 78  
             finally {
 79  0
                 team.readLock().unlock();
 80  0
             }
 81  
         }
 82  0
     }
 83  
 
 84  
     /**
 85  
      * Get the DefaultGraphicsConfiguration.
 86  
      *
 87  
      * @return The GraphicsConfiguration for the default screen.
 88  
      */
 89  
     protected GraphicsConfiguration getDefaultGraphicsConfiguration() {
 90  0
         return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
 91  
     }
 92  
 
 93  
     /**
 94  
      * Construct a new UpdateRunnable instance which is used to update the state of the user-interface components inside
 95  
      * of the AWT event dispatching thread.
 96  
      *
 97  
      * @param team The team whose state has changed.
 98  
      * @return An UpdateRunnable instance which can be used to update the user-interface state based on the recent
 99  
      * changes to the teams state.
 100  
      */
 101  
     protected UpdateRunnable newUpdateRunnable(final Team team) {
 102  
         // In an effort to reduce lock contention, we acquire the readlock and grab all of the state from the
 103  
         // team instance up front.
 104  
         BufferedImage image;
 105  
         String name;
 106  
         int score;
 107  
         int jamPoints;
 108  
         int timeouts;
 109  
 
 110  0
         team.readLock().lock();
 111  
         try {
 112  0
             image = team.getImage();
 113  0
             name = team.getName();
 114  0
             score = team.getScore();
 115  0
             jamPoints = team.getJamPoints();
 116  0
             timeouts = team.getTimeouts();
 117  
         }
 118  
         finally {
 119  0
             team.readLock().unlock();
 120  0
         }
 121  
 
 122  0
         return new UpdateRunnable(image, name, score, jamPoints, timeouts);
 123  
     }
 124  
 
 125  
     /**
 126  
      * Holds the relevent state for the Team which has changed and can be run to update user-interface elements within
 127  
      * the AWT event-dispatch thread.
 128  
      */
 129  
     @Immutable
 130  
     @ThreadSafe
 131  
     protected class UpdateRunnable implements Runnable {
 132  
         final BufferedImage image;
 133  
         final String name;
 134  
         final int score;
 135  
         final int jamPoints;
 136  
         final int timeouts;
 137  
 
 138  
         public UpdateRunnable(
 139  
                 final BufferedImage image,
 140  
                 final String name, 
 141  
                 final int score, 
 142  
                 final int jamPoints, 
 143  
                 final int timeouts)
 144  0
         {
 145  0
             super();
 146  0
             this.image = image;
 147  0
             this.name = name;
 148  0
             this.score = score;
 149  0
             this.jamPoints = jamPoints;
 150  0
             this.timeouts = timeouts;
 151  0
         }
 152  
 
 153  
         protected Collection<ChangeListener> removeChangeListeners(JSpinner c, Class<? extends ChangeListener> listenerKlass) {
 154  0
             List<ChangeListener> listenerList = new ArrayList<ChangeListener>();
 155  0
             ChangeListener[] listeners = c.getChangeListeners();
 156  0
             for (ChangeListener l : listeners) {
 157  0
                 if (listenerKlass.isAssignableFrom(l.getClass())) {
 158  0
                     c.removeChangeListener(l);
 159  0
                     listenerList.add(l);
 160  
                 }
 161  
             }
 162  0
             return listenerList;
 163  
         }
 164  
 
 165  
         public void run() {
 166  0
             if (teamButton != null) {
 167  0
                 GraphicsConfiguration defaultConfiguration = getDefaultGraphicsConfiguration();
 168  0
                 BufferedImage small = defaultConfiguration.createCompatibleImage(LOGO_WIDTH, LOGO_HEIGHT, Transparency.TRANSLUCENT);
 169  0
                 small.getGraphics().drawImage(image, 0, 0, 120, 120, null);
 170  0
                 teamButton.setIcon(new ImageIcon(small));
 171  
             }
 172  
 
 173  0
             if (teamLabel != null) {
 174  0
                 if (name != null && !name.equals(teamLabel.getText())) {
 175  0
                     teamLabel.setText(name);
 176  
                 }
 177  
             }
 178  
 
 179  0
             if (scoreSpinner != null) {
 180  0
                 Integer newValue = Integer.valueOf(score);
 181  0
                 if (!scoreSpinner.getValue().equals(newValue)) {
 182  0
                     Collection<ChangeListener> removeList = removeChangeListeners(scoreSpinner, ScoreChangeListener.class);
 183  0
                     scoreSpinner.setValue(Integer.valueOf(score));
 184  0
                     for (ChangeListener listener : removeList) {
 185  0
                         scoreSpinner.addChangeListener(listener);
 186  
                     }
 187  
                 }
 188  
             }
 189  
 
 190  0
             if (jamSpinner != null) {
 191  0
                 Integer newValue = Integer.valueOf(jamPoints);
 192  0
                 if (!jamSpinner.getValue().equals(newValue)) {
 193  0
                     Collection<ChangeListener> removeList = removeChangeListeners(jamSpinner, JamPointsChangeListener.class);
 194  0
                     jamSpinner.setValue(newValue);
 195  0
                     for (ChangeListener listener : removeList) {
 196  0
                         jamSpinner.addChangeListener(listener);
 197  
                     }
 198  
                 }
 199  
             }
 200  
 
 201  0
             if (timeoutSpinner != null) {
 202  0
                 Integer newValue = Integer.valueOf(timeouts);
 203  0
                 if (!timeoutSpinner.getValue().equals(newValue)) {
 204  0
                     Collection<ChangeListener> removeList = removeChangeListeners(timeoutSpinner, TimeoutChangeListener.class);
 205  0
                     timeoutSpinner.setValue(newValue);
 206  0
                     for (ChangeListener listener : removeList) {
 207  0
                         timeoutSpinner.addChangeListener(listener);
 208  
                     }
 209  
                 }
 210  
             }
 211  0
         }
 212  
     }
 213  
 }