Package org.cspoker.client.gui.swt.control

Source Code of org.cspoker.client.gui.swt.control.ClientGUI$Resources

/**
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version. This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.cspoker.client.gui.swt.control;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.prefs.Preferences;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;

import org.apache.log4j.Logger;
import org.cspoker.client.User;
import org.cspoker.client.gui.swt.window.GameWindow;
import org.cspoker.client.gui.swt.window.LobbyWindow;
import org.cspoker.client.gui.swt.window.LoginDialog;
import org.cspoker.common.api.shared.exception.IllegalActionException;
import org.cspoker.common.elements.cards.Card;
import org.cspoker.common.elements.table.DetailedHoldemTable;
import org.cspoker.common.elements.table.TableId;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;

/**
* SWT Client GUI Provides access to all <code>GameWindow</code>s and manages
* Display preference constants
*
* @author Cedric, Stephan
*/
public class ClientGUI {
 
  /**
   * Encapsulates File resources accessed by the GUI (images, sound files
   * etc.)
   *
   * @author Stephan
   */
  public static class Resources {
   
    public static final boolean ADDITIONAL_RESOURCES = true;
   
    private static final String IMAGE_DIR = "images/";
   
    /** Icon to be used for Shell images */
    public static final String CS_POKER_ICON = Resources.IMAGE_DIR + "csicon.png";
   
    private static final String CHIP_DIR = IMAGE_DIR + "chips/";
   
    /**
     * Contains PokerStars chip images. May not be available in open-source
     * version
     */
    public final static String STARS_CHIP_IMG_DIR = Resources.CHIP_DIR + "stars/";
   
    /**
     * Contains EPT chip images. May not be available in open-source version
     */
    public final static String EPT_CHIP_IMG_DIR = Resources.CHIP_DIR + "ept/";
   
    /** Contains Chip images from PokerWikia (free!) */
    public static final String FREE_CHIPS = Resources.CHIP_DIR + "pokerWikia/";
   
    /**
     * Chip resource currently in use (that's where the images are retrieved
     * from during play)
     */
    public static String ACTIVE_CHIP_DIR;
   
    private final static String THEMES_IMG_DIR = Resources.IMAGE_DIR + "themes/";
    private final static String CARDS_IMG_DIR = Resources.IMAGE_DIR + "cards/";
    /**
     * Contains FTP card images. May not be available in open-source version
     */
    public static final String FTP_DECK_IMG_FILE = CARDS_IMG_DIR + "Deck_FTP.png";
   
    /**
     * UNO-style cards
     */
    public static final String UNO_DECK_IMG_FILE = CARDS_IMG_DIR + "Deck_Uno.png";
    /**
     * Contains PokerStars card images. May not be available in open-source
     * version
     */
    public static final String FOUR_COLOR_DECK_IMG_FILE = CARDS_IMG_DIR + "Deck_Free_2.png";
    /**
     * Card image resource currently in use (that's where the images are
     * retrieved from during play). Initialized to use free Four color
     * deck-style cards
     */
    public static String ACTIVE_DECK_IMG_FILE;
   
    public static final List<String> VALID_DECK_FILES = Collections.unmodifiableList(Arrays.asList(FTP_DECK_IMG_FILE,
        FOUR_COLOR_DECK_IMG_FILE, UNO_DECK_IMG_FILE));
   
    public static final List<String> VALID_CHIP_FILES = Collections.unmodifiableList(Arrays.asList(FTP_DECK_IMG_FILE,
        EPT_CHIP_IMG_DIR, STARS_CHIP_IMG_DIR, FREE_CHIPS));
   
    /** Default table background image */
    public static final String TABLE_IMAGE = THEMES_IMG_DIR + "table1.jpg";
   
    private static final String SOUND_DIR = "Snd/";
    /** Plays a <i>Check</i> sound */
    public static final String SOUND_FILE_CHECK = SOUND_DIR + "snd4.wav";
    /** Plays a <i>Fold</i> sound */
    public static final String SOUND_FILE_FOLD = SOUND_DIR + "snd6.wav";
    /** Plays a <i>Chip clink</i> sound */
    public static final String SOUND_FILE_BETRAISE = SOUND_DIR + "snd5.wav";
    /** Plays a <i>Chip sliding</i> sound */
    public static final String SOUND_FILE_SLIDE_CHIPS = SOUND_DIR + "snd3.wav";
   
  }
 
  private final Display display;
  private final ClientCore clientCore;
  private LobbyWindow lobby;
  public static boolean SOUND_ON = true;
  private final static Logger logger = Logger.getLogger(ClientGUI.class);
  // TODO Better way of storing/retrieving the open GameWindows?
  private Hashtable<TableId, GameWindow> gameWindows;
 
  /**
   * @return The UI {@link Display} used throughout. All windows created by
   *         the client should use this display.
   */
  public Display getDisplay() {
    assert (!display.isDisposed()) : "The requested display has been disposed";
    return display;
  }
 
  /**
   * @return The list with all {@link GameWindow}s currently opened
   */
  public Collection<GameWindow> getGameWindows() {
    return gameWindows.values();
  }
 
  /** Preferred width at which a card is best displayed */
  public final static int PREFERRED_CARD_WIDTH = 50;
 
  /** What do you think this is? */
  public final static int MINIMUM_CARD_WIDTH = 30;
  /** What do you think this is? */
  public final static int MINIMUM_CARD_HEIGHT = (int) Math.round(MINIMUM_CARD_WIDTH * 1.5);
 
  /**
   * Preferred height at which a card is best displayed. Set to
   * <code>1.5 * PREFERRED_CARD_WIDTH</code>
   */
  public final static int PREFERRED_CARD_HEIGHT = (int) Math.round(PREFERRED_CARD_WIDTH * 1.5);
 
  /**
   * Final reference for an unknown card (i.e. the image is the back of the
   * card)
   */
  public final static Card UNKNOWN_CARD = null;
 
  /**
   * During development, set this to SWT.BORDER so we better see where the
   * composites are
   */
  public static final int COMPOSITE_BORDER_STYLE = SWT.NONE;
 
  /**
   * A {@link NumberFormat} to use when converting from a bare
   * <code>int</code> chip value to a human-readable representation and
   * vice-versa
   */
  private final static NumberFormat betFormatter = NumberFormat.getNumberInstance();
 
  /***************************************************************************
   * Constructor
   **************************************************************************/
  /**
   * Creates a new clientGui with a given clientCore
   *
   * @param clientCore the given clientCore
   */
  public ClientGUI(ClientCore clientCore) {
    display = Display.getDefault();
    this.clientCore = clientCore;
    gameWindows = new Hashtable<TableId, GameWindow>();
    betFormatter.setMinimumFractionDigits(0);
    betFormatter.setMaximumFractionDigits(2);
    betFormatter.setGroupingUsed(false);
    verifyAndInitResources();
   
  }
 
  /**
   *
   */
  private void verifyAndInitResources() {
    String cardFile = Preferences.userRoot().get(User.Prefs.CARDS,
        Resources.FOUR_COLOR_DECK_IMG_FILE);
    String chipFile = Preferences.userRoot().get(User.Prefs.CHIPS, Resources.FREE_CHIPS);
    if (!Resources.VALID_DECK_FILES.contains(cardFile)) {
      cardFile = Resources.FOUR_COLOR_DECK_IMG_FILE;
    }
    if (!Resources.VALID_CHIP_FILES.contains(chipFile)) {
      chipFile = Resources.FREE_CHIPS;
    }
    try {
      setActiveCardDeck(cardFile);
      setActiveChipsStyle(chipFile);
      SOUND_ON = Boolean.parseBoolean(Preferences.userRoot().get(User.Prefs.SOUND, Boolean.toString(true)));
    } catch (FileNotFoundException e) {
      logger.warn("File initialization failed, removing from preferences: ", e);
      Preferences.userRoot().remove(User.Prefs.CHIPS);
      Preferences.userRoot().remove(User.Prefs.CARDS);
    }
   
  }
 
  /**
   * Formatting bets by hand since {@link NumberFormat#getCurrencyInstance()}s
   * from Java sucks
   *
   * @param bet The bet in the lowest denominator currency unit (cents)
   * @return A String representing the bet amount
   * @see #parseBet(String)
   */
  public static String formatBet(int bet) {
    int dollar = bet / 100;
    int cent = bet % 100;
    String result = "$ " + Integer.toString(dollar);
   
    if (cent != 0) {
      result = result + ".";
      if (cent / 10 == 0) {
        result = result + "0";
      }
      result = result + Integer.toString(cent);
    }
    return result;
  }
 
  public static int roundToBlind(double bet, double blind) {
    return (int) (blind * Math.round(bet/blind));
  }
 
  /**
   * Formatting bets by hand since {@link NumberFormat#getCurrencyInstance()}s
   * from Java sucks
   *
   * @param bet The bet as a string
   * @return The bet in cents
   * @throws NumberFormatException if the bet does not contain a parsable
   *             double
   * @see #formatBet(int)
   */
  public static int parseBet(String bet) {
    bet = bet.replaceAll("[^0-9.,]", "");
    double result = Double.parseDouble(bet);
    return (int) Math.round(result * 100);
  }
 
  /***************************************************************************
   * Window & shell
   **************************************************************************/
 
  /**
   * Disposes the current shell
   */
  public void disposeCurrentShell() {
    try {
      display.getActiveShell().dispose();
    } catch (NullPointerException e) {}
  }
 
  /***************************************************************************
   * LOGIN
   **************************************************************************/
  /**
   * Starts the new gui by creating and opening new login screen
   *
   * @return A new {@link LoginDialog}
   */
  public LoginDialog createNewLoginDialog() {
    disposeCurrentShell();
    return new LoginDialog(new Shell(display, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL), SWT.NONE, clientCore);
  }
 
  /**
   * Displays a fresh {@link MessageBox} with the given error message
   *
   * @param e the given error message
   * @return {@link MessageBox#open()}
   */
  public static int displayException(Exception e) {
    logger.error("Unexpected error during client execution", e);
   
    StringBuffer sb = new StringBuffer(e.getMessage() + "\n\n");
   
    for (StackTraceElement ste : e.getStackTrace()) {
      sb.append(ste.toString() + "\n");
    }
    return displayMessage("Unexpected exception, everything was reset", sb.toString(), SWT.ICON_ERROR);
  }
 
  /**
   * Displays a fresh {@link MessageBox} with the given message
   *
   * @param message The message to display
   * @param style The desired style bits (see {@link MessageBox} style bit
   *            info)
   * @return {@link MessageBox#open()}
   */
  public static int displayMessage(String title, String message, int style) {
    logger.info(message);
    MessageBox infoBox = new MessageBox(new Shell(Display.getCurrent()), style | SWT.OK);
    infoBox.setText(title);
    infoBox.setMessage(message);
    return infoBox.open();
  }
 
  /**
   * @param file Plays the given audio file
   */
  public static void playAudio(String file) {
    if (SOUND_ON == false) {
      return;
    }
    AudioInputStream stream = null;
    Clip clip = null;
    try {
      stream = AudioSystem.getAudioInputStream(ClientGUI.getResource(file));
      DataLine.Info info = new DataLine.Info(Clip.class, stream.getFormat());
      clip = (Clip) AudioSystem.getLine(info);
      clip.open(stream);
      clip.start();
      clip.addLineListener(new LineListener() {
       
        public void update(LineEvent event) {
          if (event.getType() == LineEvent.Type.STOP)
            event.getLine().close();
        }
      });
    } catch (Exception e) {
      // Commented out because it seems not to work on ubuntu and spams
      // the stack trace
      // logger.warn("Could not play sound", e);
    } finally {
      if (stream != null) {
        try {
          stream.close();
        } catch (IOException ignored) {
          // Do nothing
        }
      }
    }
   
  }
 
  /**
   * Sets the visual cards to be used in all {@link GameWindow}s.
   * <p>
   * This method disposes of all image resources so that no images cached by
   * the {@link SWTResourceManager} can be reused.
   *
   * @param cardFileResource The file system resource where the cards can be
   *            found. May either be a directory containing single images or a
   *            single image file containing all images.
   * @throws FileNotFoundException If the file resource does not exist
   */
  public static void setActiveCardDeck(String cardFileResource)
      throws FileNotFoundException {
    //TODO reintroduce check for correct directory
//    if (getResource(cardFileResource)==null) {
//      throw new FileNotFoundException(cardFileResource);
//    }
    Preferences.userRoot().put(User.Prefs.CARDS, cardFileResource);
    SWTResourceManager.dispose();
    Resources.ACTIVE_DECK_IMG_FILE = cardFileResource;
   
  }

  public static InputStream getResource(String path) {
    return ClientGUI.class.getClassLoader().getResourceAsStream(path);
  }
 
  /**
   * Sets the visual type of chips used in all {@link GameWindow}s.
   * <p>
   * This method disposes of all image resources so that no images cached by
   * the {@link SWTResourceManager} can be reused.
   *
   * @param chipFileResource The file system resource where the cards can be
   *            found. May either be a directory containing single images or a
   *            single image file containing all images.
   * @throws FileNotFoundException If the file resource does not exist
   */
  public static void setActiveChipsStyle(String chipFileResource)
      throws FileNotFoundException {
    //TODO reintroduce check for correct directory
//    if (getResource(chipFileResource)==null) {
//      throw new FileNotFoundException(chipFileResource);
//    }
    Preferences.userRoot().put(User.Prefs.CHIPS, chipFileResource);
    SWTResourceManager.dispose();
    Resources.ACTIVE_CHIP_DIR = chipFileResource;
   
  }
 
  /**
   * @param lobby the lobby to set
   */
  public void setLobby(LobbyWindow lobby) {
    if (getLobby() != null) {
      display.syncExec(new Runnable() {
       
        public void run() {
          getLobby().dispose();
        }
      });
    }
    this.lobby = lobby;
  }
 
  /**
   * @return the lobby
   */
  public LobbyWindow getLobby() {
    return lobby;
  }
 
  /**
   * Searches for the given {@link GameWindow}.
   *
   * @param tableId The table id
   * @param createNew if <code>true</code>, a new {@link GameWindow} will be
   *            created if it doesn't exist, otherwise the existing GameWindow
   *            is returned
   * @return The {@link GameWindow} for the given id. If it doesn't exist, it
   *         is created when <code>createNew</code> is <code>true</code>,
   *         otherwise <code>null</code> is returned
   */
  public GameWindow getGameWindow(TableId tableId, boolean createNew) {
    GameWindow w = gameWindows.get(tableId);
    if (w == null && createNew) {
      // No Game Window for this table yet
     
      DetailedHoldemTable table;
      try {
        table = getLobby().getContext().getHoldemTableInformation(tableId);
        w = new GameWindow(getLobby(), table);
      } catch (RemoteException e) {
        throw new IllegalStateException("Could not retrieve remote table information", e);
      } catch (IllegalActionException exception) {
        logger.error("This should not happen", exception);
      }
    }
    gameWindows.put(tableId, w);
   
    return w;
  }
}
TOP

Related Classes of org.cspoker.client.gui.swt.control.ClientGUI$Resources

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.