Coverage report

  %line %branch
org.cb.jset.client.ui.JSetClientUI$GameController
0% 
0% 

 1  
 // START LICENSE
 2  
 // JSet - a Java JSet card board game implementation
 3  
 // Copyright (C) 2004 Jerome Lacoste
 4  
 //
 5  
 // This program is free software; you can redistribute it and/or modify
 6  
 // it under the terms of the GNU General Public License as published by
 7  
 // the Free Software Foundation; either version 2 of the License, or (at
 8  
 // your option) any later version.
 9  
 //
 10  
 // This program is distributed in the hope that it will be useful, but
 11  
 // WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 // General Public License for more details.
 14  
 //
 15  
 // You should have received a copy of the GNU General Public License
 16  
 // along with this program; if not, write to the Free Software
 17  
 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 18  
 // END LICENSE
 19  
 
 20  
 package org.cb.jset.client.ui;
 21  
 
 22  
 import javax.swing.border.Border;
 23  
 import javax.swing.JFrame;
 24  
 import javax.swing.JLabel;
 25  
 import javax.swing.JPanel;
 26  
 import javax.swing.BorderFactory;
 27  
 import javax.swing.JMenuItem;
 28  
 import javax.swing.JMenuBar;
 29  
 import javax.swing.JMenu;
 30  
 import javax.swing.JComponent;
 31  
 import javax.swing.JOptionPane;
 32  
 import java.awt.event.KeyEvent;
 33  
 import java.awt.event.ActionEvent;
 34  
 import java.awt.event.ActionListener;
 35  
 import java.awt.event.WindowAdapter;
 36  
 import java.awt.event.WindowEvent;
 37  
 import java.awt.HeadlessException;
 38  
 import java.awt.BorderLayout;
 39  
 import java.awt.Dimension;
 40  
 import java.awt.FlowLayout;
 41  
 import java.util.Iterator;
 42  
 import java.util.Map;
 43  
 import java.util.HashSet;
 44  
 import java.util.HashMap;
 45  
 import java.rmi.RMISecurityManager;
 46  
 import java.rmi.NotBoundException;
 47  
 import java.rmi.RemoteException;
 48  
 import java.net.MalformedURLException;
 49  
 import java.io.Serializable;
 50  
 
 51  
 import org.apache.log4j.Logger;
 52  
 import org.cb.jset.client.model.JSetClientBoardModel;
 53  
 import org.cb.jset.server.RemoteSetGame;
 54  
 import org.cb.jset.client.model.SetGameClientCardListener;
 55  
 import org.cb.jset.client.model.CardEvent;
 56  
 import org.cb.jset.client.SetGameListener;
 57  
 import org.cb.jset.client.GameEvent;
 58  
 import org.cb.jset.client.LocalGame;
 59  
 import org.cb.jset.client.NetworkGame;
 60  
 import org.cb.jset.client.Client;
 61  
 import org.cb.jset.CardProperties;
 62  
 import org.cb.jset.CardSet;
 63  
 import org.cb.jset.MatchingSetFinder;
 64  
 import org.cb.jset.JSetCard;
 65  
 import org.cb.jset.SetGameBoardListener;
 66  
 import org.cb.jset.MatchingException;
 67  
 import org.cb.jset.JSetBuild;
 68  
 import org.cb.jset.BoardException;
 69  
 import org.cb.cardboard.CardBoardEvent;
 70  
 import org.cb.cardboard.CardBoardModelListener;
 71  
 
 72  
 /**
 73  
  * The main UI for the game.
 74  
  *
 75  
  * @author jerome@coffeebreaks.org - last modified by $LastChangedBy: jerome $
 76  
  * @version $Id: JSetClientUI.java 128 2004-04-15 04:12:04Z jerome $
 77  
  */
 78  
 public class JSetClientUI extends JFrame
 79  
 {
 80  
   final transient Logger _logger = Logger.getLogger("JSetClientUI");
 81  
 
 82  
   private JFrame _frame = this;
 83  
 
 84  
   private JSetBoardComponent _boardPanel;
 85  
   private final JSetClientBoardModel _boardModel = new JSetClientBoardModel();
 86  
   private final java.util.Set _selectedCards = new HashSet();
 87  
   private final Map _mapCardsToComponents = new HashMap();
 88  
 
 89  
   private final BoardController _boardController = new BoardController();
 90  
   private final GameController _gameController = new GameController();
 91  
 //  private CardStack _cardStack;
 92  
   private JLabel _infoLabel;
 93  
 
 94  
   private org.cb.jset.client.SetGame _game;
 95  
 
 96  
   /** Wether we ask to confirm close.
 97  
    * @todo make it configurable
 98  
    */
 99  
   private boolean _askCloseConfirm = true;
 100  
 
 101  
   /**
 102  
    * Constructs an instance of JSetClientUI, given the specified title.
 103  
    * @param title the title to put on the UI.
 104  
    * @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true.
 105  
    */
 106  
   public JSetClientUI(final String title)
 107  
       throws HeadlessException
 108  
   {
 109  
     super(title);
 110  
     init();
 111  
   }
 112  
 
 113  
   // debug code.
 114  
   /**
 115  
   public void paint(final Graphics g)
 116  
   {
 117  
     super.paint(g);    //To change body of overridden methods use File | Settings | File Templates.
 118  
     _logger.debug("painting frame: " +  getSize());
 119  
   }
 120  
 
 121  
   public void paintComponents(final Graphics g)
 122  
   {
 123  
     super.paintComponents(g);    //To change body of overridden methods use File | Settings | File Templates
 124  
     _logger.debug("painting component: " +  getSize());
 125  
   }
 126  
   **/
 127  
 
 128  
   /**
 129  
    * Construct the UI.
 130  
    */
 131  
   private void init()
 132  
   {
 133  
     final JPanel panel = new JPanel(class="keyword">new BorderLayout());
 134  
     _boardPanel = new JSetBoardComponent(_boardModel);
 135  
     final Border etchedBorder = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Card Board");
 136  
     _boardPanel.setSize(new Dimension(800, 600));
 137  
     _boardPanel.setBorder(etchedBorder);
 138  
     _boardPanel.setLayout(new FlowLayout(FlowLayout.LEADING, 20, 20));
 139  
 
 140  
     _boardModel.addBoardDataListener(_boardController);
 141  
 //    _boardPanel.addBoardSelectionListener(_boardController);
 142  
 
 143  
     _infoLabel = new JLabel();
 144  
 
 145  
     final JMenuBar menuBar;
 146  
     JMenu menu;
 147  
     JMenuItem menuItem;
 148  
 
 149  
     menuBar = new JMenuBar();
 150  
     menu = new JMenu("Edit");
 151  
     menu.setMnemonic(KeyEvent.VK_E);
 152  
     menu.getAccessibleContext().setAccessibleDescription("Edit options");
 153  
     menuBar.add(menu);
 154  
 
 155  
     menu = new JMenu("View");
 156  
     menu.setMnemonic(KeyEvent.VK_V);
 157  
     menu.getAccessibleContext().setAccessibleDescription("View");
 158  
     menuBar.add(menu);
 159  
 
 160  
     menu = new JMenu("Game");
 161  
     menu.setMnemonic(KeyEvent.VK_G);
 162  
     menu.getAccessibleContext().setAccessibleDescription("Start games");
 163  
     menuBar.add(menu);
 164  
 
 165  
     menuItem = new JMenuItem("Start Local Game", KeyEvent.VK_L);
 166  
     menuItem.addActionListener(new ActionListener()
 167  
     {
 168  
       public void actionPerformed(final ActionEvent e)
 169  
       {
 170  
         treatStartLocalGameMenuItemClicked(e);
 171  
       }
 172  
     });
 173  
     menu.add(menuItem);
 174  
     menuItem = new JMenuItem("Start Networked Game", KeyEvent.VK_N);
 175  
     menuItem.addActionListener(new ActionListener()
 176  
     {
 177  
       public void actionPerformed(final ActionEvent e)
 178  
       {
 179  
         treatStartNetworkedGameMenuItemClicked(e);
 180  
       }
 181  
     });
 182  
     menu.add(menuItem);
 183  
 
 184  
     menu = new JMenu("Help");
 185  
     menu.setMnemonic(KeyEvent.VK_H);
 186  
     menu.getAccessibleContext().setAccessibleDescription("Help");
 187  
     menuItem = new JMenuItem("Help Topics", KeyEvent.VK_T);
 188  
     menuItem.addActionListener(new ActionListener()
 189  
     {
 190  
       public void actionPerformed(final ActionEvent e)
 191  
       {
 192  
         treatHelpTopicsMenuItemClicked(e);
 193  
       }
 194  
     });
 195  
 
 196  
     menu.add(menuItem);
 197  
     menu.addSeparator();
 198  
     menuItem = new JMenuItem("About", KeyEvent.VK_A);
 199  
     menuItem.addActionListener(new ActionListener()
 200  
     {
 201  
       public void actionPerformed(final ActionEvent e)
 202  
       {
 203  
         treatAboutMenuItemClicked(e);
 204  
       }
 205  
     });
 206  
     menu.add(menuItem);
 207  
 
 208  
     menuBar.add(menu);
 209  
 
 210  
     _frame.setJMenuBar(menuBar);
 211  
 
 212  
     panel.add(_boardPanel, BorderLayout.CENTER);
 213  
     panel.add(_infoLabel, BorderLayout.SOUTH);
 214  
     _frame.getContentPane().add(panel);
 215  
     /// _frame.setContentPane(_boardPanel);
 216  
     _frame.pack();
 217  
     _frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
 218  
     _frame.addWindowListener(new WindowAdapter()
 219  
     {
 220  
       /**
 221  
        * Allow the user to confirm wether he wants to close or not.
 222  
        * @param e
 223  
        */
 224  
       public void windowClosing(WindowEvent e)
 225  
       {
 226  
         _logger.debug("windowClosing()");
 227  
         boolean shouldClose = true;
 228  
         if (_askCloseConfirm)
 229  
         {
 230  
           String confirmQuitMsg = "";
 231  
           if (_game != null)
 232  
           {
 233  
             confirmQuitMsg += "A game is being played. \n";
 234  
           }
 235  
           confirmQuitMsg += "Are you sure you want to quit?";
 236  
           int userChoice =
 237  
               JOptionPane.showConfirmDialog(JSetClientUI.this, confirmQuitMsg,
 238  
                                             "Confirm close", JOptionPane.YES_NO_OPTION);
 239  
           shouldClose = (userChoice == JOptionPane.OK_OPTION);
 240  
         }
 241  
         if (shouldClose)
 242  
         {
 243  
           onWindowClose();
 244  
         }
 245  
       }
 246  
     });
 247  
     _frame.setSize(800, 600);
 248  
     _frame.setBounds(50, 50, 800, 600);
 249  
 
 250  
     _frame.show();
 251  
   }
 252  
 
 253  
   private void onWindowClose()
 254  
   {
 255  
     if (_game != null)
 256  
     {
 257  
       _logger.debug("closing game...");
 258  
       _game.stop();
 259  
     }
 260  
     _logger.debug("Closing.");
 261  
     setVisible(false);
 262  
     dispose();
 263  
     System.exit(0);
 264  
   }
 265  
 
 266  
   private void setGame(final org.cb.jset.client.SetGame game)
 267  
   {
 268  
     if (_game == null)
 269  
     {
 270  
       _game = game;
 271  
       _game.addBoardListener(_gameController);
 272  
       _game.addGameListener(_gameController);
 273  
       _game.start();
 274  
     }
 275  
   }
 276  
 
 277  
   private void addCards(final CardProperties[] cardProperties)
 278  
   {
 279  
     _boardModel.addCards(cardProperties);
 280  
     updateInfoLabel();
 281  
     this.validate();
 282  
   }
 283  
 
 284  
   void updateInfoLabel()
 285  
   {
 286  
     final MatchingSetFinder lFinder = new MatchingSetFinder();
 287  
     final CardSet[] lFoundSets = lFinder.findSets(_boardModel.getElements());
 288  
     for (int i = 0; i < lFoundSets.length; i++)
 289  
     {
 290  
       final CardSet lFoundSet = lFoundSets[i];
 291  
       _logger.debug("foundSet[" + i + "]" + lFoundSet);
 292  
     }
 293  
     _infoLabel.setText("There are " + lFoundSets.length + " set(s) currently on the board");
 294  
   }
 295  
 
 296  
   /**
 297  
    * An object to display empty card space on the board.
 298  
    */
 299  
   private static class EmptyCard extends JPanel
 300  
   {
 301  
     public EmptyCard()
 302  
     {
 303  
       init();
 304  
     }
 305  
 
 306  
     void init()
 307  
     {
 308  
       // FIXME coded shared with JSetCardComponent. parametrize.
 309  
       final int width = 80;
 310  
       final int height = (class="keyword">int) (1.5 * width);
 311  
       setSize(width, height);
 312  
       setPreferredSize(getSize());
 313  
     }
 314  
   }
 315  
 
 316  
 
 317  
   /**
 318  
    * Control events coming from the board.
 319  
    */
 320  
   class BoardController implements CardBoardModelListener, SetGameClientCardListener, Serializable
 321  
   {
 322  
     public void intervalAdded(final CardBoardEvent e)
 323  
     {
 324  
       _logger.debug(e);
 325  
       final CardBoardEvent.IndexInterval interval = (CardBoardEvent.IndexInterval) e.getBoardIndexes();
 326  
       for (int i = class="keyword">interval.getIndex0(); i <= class="keyword">interval.getIndex1(); i++)
 327  
       {
 328  
         final JComponent cardComponent = getCardComponent(i);
 329  
         _boardPanel.add(cardComponent, i);
 330  
       }
 331  
       _boardPanel.validate();
 332  
     }
 333  
 
 334  
     public void intervalRemoved(final CardBoardEvent e)
 335  
     {
 336  
       _logger.debug(e);
 337  
       final CardBoardEvent.IndexInterval interval = (CardBoardEvent.IndexInterval) e.getBoardIndexes();
 338  
       for (int i = class="keyword">interval.getIndex0(); i <= class="keyword">interval.getIndex1(); i++)
 339  
       {
 340  
         final JPanel jPanel = new EmptyCard();
 341  
         replaceCardComponent(i, jPanel);
 342  
       }
 343  
       _boardPanel.validate();
 344  
     }
 345  
 
 346  
     public void contentsChanged(final CardBoardEvent e)
 347  
     {
 348  
       _logger.debug(e);
 349  
       final CardBoardEvent.IndexList indexList = (CardBoardEvent.IndexList) e.getBoardIndexes();
 350  
       for (int i = 0; i < indexList.getIndexesInBoard().size(); i++)
 351  
       {
 352  
         final Integer index = (Integer) indexList.getIndexesInBoard().get(i);
 353  
         final JSetCard card = (JSetCard) _boardModel.getElementAt(index.intValue());
 354  
         final JComponent newCard;
 355  
         if (card == null)
 356  
         {
 357  
           newCard = new EmptyCard();
 358  
         }
 359  
         else
 360  
         {
 361  
           newCard = getCardComponent(index.intValue());
 362  
         }
 363  
         replaceCardComponent(index.intValue(), newCard);
 364  
       }
 365  
       _boardPanel.validate();
 366  
     }
 367  
 
 368  
     public void notifyCardEvent(final CardEvent e)
 369  
     {
 370  
       _logger.debug(e);
 371  
       final int index = _boardModel.getElements().indexOf(e.getSource());
 372  
       final JSetCardComponent cardComponent = getCardComponent(index);
 373  
       cardComponent.updateBorder();
 374  
       if (cardComponent.isSelected())
 375  
       {
 376  
         _selectedCards.add(cardComponent.getCard());
 377  
         _logger.debug("selecting " + cardComponent.getCard() + " still " + _selectedCards.size());
 378  
       }
 379  
       else
 380  
       {
 381  
         _selectedCards.remove(cardComponent.getCard());
 382  
         _logger.debug("deselecting " + cardComponent.getCard() + " still " + _selectedCards.size());
 383  
       }
 384  
 
 385  
       if (_selectedCards.size() == 3)
 386  
       {
 387  
         final CardProperties[] cardProperties = new CardProperties[3];
 388  
         int i = 0;
 389  
         for (Iterator iterator = _selectedCards.iterator(); iterator.hasNext();)
 390  
         {
 391  
           final org.cb.jset.JSetCard card = (JSetCard) iterator.next();
 392  
           cardProperties[i++] = card.getProperties();
 393  
         }
 394  
         tryToMatch(new CardSet(cardProperties));
 395  
       }
 396  
       else if (_selectedCards.size() > 3)
 397  
       {
 398  
         throw new IllegalStateException("More than 3 cards selected");
 399  
       }
 400  
     }
 401  
   }
 402  
 
 403  
   /**
 404  
    * Control events coming from the game instance.
 405  
    *
 406  
    * FIXME we probably need to add multithreading handling on the model.
 407  
    */
 408  0
   class GameController implements SetGameBoardListener, SetGameListener, Serializable
 409  
   {
 410  
     /**
 411  
      * @inheritDoc
 412  
      */
 413  
     public void cardsAdded(final CardProperties[] cards)
 414  
     {
 415  0
       addCards(cards);
 416  0
     }
 417  
 
 418  
     /**
 419  
      * @inheritDoc
 420  
      */
 421  
     public void setRemoved(final CardSet set)
 422  
     {
 423  0
       treatSuccessfulMatching(set);
 424  0
     }
 425  
 
 426  
     /**
 427  
      * @inheritDoc
 428  
      */
 429  
     public void gameChange(final GameEvent event)
 430  
     {
 431  
       // FIXME
 432  0
     }
 433  
   }
 434  
 
 435  
   private void replaceCardComponent(final int i, class="keyword">final JComponent jPanel)
 436  
   {
 437  
     _boardPanel.remove(i);
 438  
     _boardPanel.add(jPanel, i);
 439  
   }
 440  
 
 441  
   private JSetCardComponent getCardComponent(final int i)
 442  
   {
 443  
     final org.cb.jset.JSetCard card = (JSetCard) _boardModel.getElementAt(i);
 444  
     JSetCardComponent cardComponent = (JSetCardComponent) _mapCardsToComponents.get(card);
 445  
     // FIXME was that really necessary ?
 446  
     if (cardComponent == null)
 447  
     {
 448  
       cardComponent = new JSetCardComponent(card);
 449  
       cardComponent.addCardEventListener(_boardController);
 450  
       _mapCardsToComponents.put(card, cardComponent);
 451  
     }
 452  
     // FIXME empty cache
 453  
     return cardComponent;
 454  
   }
 455  
 
 456  
   private void tryToMatch(final CardSet set)
 457  
   {
 458  
     boolean isMatchingSet;
 459  
     try
 460  
     {
 461  
       _game.removeSet(set);
 462  
       isMatchingSet = true;
 463  
     }
 464  
     catch (MatchingException e)
 465  
     {
 466  
       isMatchingSet = false;
 467  
     }
 468  
 
 469  
     if (!isMatchingSet)
 470  
     {
 471  
       treatFailedMatching(set, set.getCards());
 472  
     }
 473  
   }
 474  
 
 475  
   private void treatFailedMatching(final CardSet set, class="keyword">final CardProperties[] cardsToHandle)
 476  
   {
 477  
     _logger.debug("not matching set!!" + set);
 478  
     for (int j = 0; j < cardsToHandle.length; j++)
 479  
     {
 480  
       final JSetCardComponent jSetCardComponent = (JSetCardComponent) _mapCardsToComponents.get(new JSetCard(cardsToHandle[j]));
 481  
       jSetCardComponent.setSelection(false);
 482  
     }
 483  
   }
 484  
 
 485  
   private void treatSuccessfulMatching(final CardSet set)
 486  
   {
 487  
     _logger.debug("matching set!! " + set);
 488  
     // note: we don't replace, but remove then add new ones.
 489  
     try
 490  
     {
 491  
       _boardModel.removeSet(set);
 492  
     }
 493  
     catch (BoardException e)
 494  
     {
 495  
       throw new IllegalStateException("We shouldn't fail here... " + e.getMessage());
 496  
     }
 497  
     updateInfoLabel();
 498  
     // FIXME this shouldn't be there, but is there a clean way to clean cards we've lost track of?
 499  
     _selectedCards.clear();
 500  
 //    if (! _cardStack.empty())
 501  
 //    {
 502  
 //      CardProperties[] lCardProperties = _cardStack.pop(3);
 503  
 //      _boardModel.addCards(lCardProperties);
 504  
 //    }
 505  
   }
 506  
 
 507  
   private void treatAboutMenuItemClicked(final ActionEvent e)
 508  
   {
 509  
     final String aboutMsg = "Implementation of the JSet Card Board game.\n"
 510  
      + "Copyright (C) Jerome Lacoste (jerome@coffeebreaks.org) 2004.\n"
 511  
      + "V. " + JSetBuild.VERSION + " built " + JSetBuild.BUILD_TIME;
 512  
     JOptionPane.showMessageDialog(JSetClientUI.this, aboutMsg);
 513  
   }
 514  
   private void treatHelpTopicsMenuItemClicked(final ActionEvent e)
 515  
   {
 516  
 
 517  
   }
 518  
   private void treatStartLocalGameMenuItemClicked(final ActionEvent e)
 519  
   {
 520  
     setGame(new LocalGame());
 521  
   }
 522  
 
 523  
   private void treatStartNetworkedGameMenuItemClicked(final ActionEvent e)
 524  
   {
 525  
     if (System.getSecurityManager() == null)
 526  
     {
 527  
       System.setSecurityManager(new RMISecurityManager());
 528  
     }
 529  
     try
 530  
     {
 531  
       final String host = "localhost";
 532  
       final String gameName = "TestGame";
 533  
       final RemoteSetGame game = Client.getGame(host, gameName);
 534  
       final NetworkGame networkGame = new NetworkGame("UITestUser");
 535  
       networkGame.setRemoteGame(game);
 536  
       setGame(networkGame);
 537  
     }
 538  
     catch (Exception e1)
 539  
     {
 540  
       new ErrorHandler().handle(e1);
 541  
     }
 542  
   }
 543  
 
 544  
   class ErrorHandler implements Serializable
 545  
   {
 546  
     void handle(final Exception e)
 547  
     {
 548  
       final String msg;
 549  
       if (e instanceof RemoteException)
 550  
       {
 551  
         msg = "Error while trying to connect :" + e.getMessage();
 552  
       }
 553  
       else if (e instanceof NotBoundException)
 554  
       {
 555  
         msg = "Error while trying to connect :" + e.getMessage();
 556  
       }
 557  
       else if (e instanceof MalformedURLException)
 558  
       {
 559  
         msg = "Error while trying to connect :" + e.getMessage();
 560  
       }
 561  
       else
 562  
       {
 563  
         msg = "Unkown error :" + e.getMessage();
 564  
       }
 565  
       JOptionPane.showMessageDialog(JSetClientUI.this, msg);
 566  
     }
 567  
   }
 568  
 
 569  
   public static void main(final String[] args)
 570  
   {
 571  
     org.apache.log4j.PropertyConfigurator.configure("src/conf/log4j.properties");
 572  
     final JSetClientUI lDrawing = new JSetClientUI("JSet - " + JSetBuild.VERSION);
 573  
   }
 574  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.