/** Called when the observers detect change, to see if the game is in a startable state */
 @Override
 public boolean canGameStart() {
   if (m_gameSelectorModel.getGameData() == null) {
     return false;
   }
   final boolean diceServerValid = m_diceServerEditor.isBeanValid();
   final boolean summaryValid = m_forumPosterEditor.isBeanValid();
   final boolean webSiteValid = m_webPosterEditor.isBeanValid();
   final boolean emailValid = m_emailSenderEditor.isBeanValid();
   final boolean pbemReady =
       diceServerValid
           && summaryValid
           && emailValid
           && webSiteValid
           && m_gameSelectorModel.getGameData() != null;
   if (!pbemReady) {
     return false;
   }
   // make sure at least 1 player is enabled
   for (final PBEMLocalPlayerComboBoxSelector player : m_playerTypes) {
     if (player.isPlayerEnabled()) {
       return true;
     }
   }
   return false;
 }
 /** Called when the user hits play */
 @Override
 public ILauncher getLauncher() {
   // update local cache and write to disk before game starts
   final IForumPoster poster = (IForumPoster) m_forumPosterEditor.getBean();
   if (poster != null) {
     LocalBeanCache.INSTANCE.storeSerializable(poster.getClass().getCanonicalName(), poster);
   }
   final IEmailSender sender = (IEmailSender) m_emailSenderEditor.getBean();
   if (sender != null) {
     LocalBeanCache.INSTANCE.storeSerializable(sender.getClass().getCanonicalName(), sender);
   }
   final IWebPoster web = (IWebPoster) m_webPosterEditor.getBean();
   if (web != null) {
     LocalBeanCache.INSTANCE.storeSerializable(web.getClass().getCanonicalName(), web);
   }
   final IRemoteDiceServer server = (IRemoteDiceServer) m_diceServerEditor.getBean();
   LocalBeanCache.INSTANCE.storeSerializable(server.getDisplayName(), server);
   LocalBeanCache.INSTANCE.writeToDisk();
   // create local launcher
   final String gameUUID =
       (String) m_gameSelectorModel.getGameData().getProperties().get(GameData.GAME_UUID);
   final PBEMDiceRoller randomSource =
       new PBEMDiceRoller((IRemoteDiceServer) m_diceServerEditor.getBean(), gameUUID);
   final Map<String, String> playerTypes = new HashMap<>();
   final Map<String, Boolean> playersEnabled = new HashMap<>();
   for (final PBEMLocalPlayerComboBoxSelector player : m_playerTypes) {
     playerTypes.put(player.getPlayerName(), player.getPlayerType());
     playersEnabled.put(player.getPlayerName(), player.isPlayerEnabled());
   }
   // we don't need the playerToNode list, the
   // disable-able players, or the alliances
   // list, for a local game
   final PlayerListing pl =
       new PlayerListing(
           null,
           playersEnabled,
           playerTypes,
           m_gameSelectorModel.getGameData().getGameVersion(),
           m_gameSelectorModel.getGameName(),
           m_gameSelectorModel.getGameRound(),
           null,
           null);
   return new LocalLauncher(m_gameSelectorModel, randomSource, pl);
 }
 private void setupListeners() {
   // register, so we get notified when the game model (GameData) changes (e.g if the user load a
   // save game or selects
   // another game)
   m_gameSelectorModel.addObserver(this);
   // subscribe to editor changes, so we cannotify the MainPanel
   m_diceServerEditor.addPropertyChangeListener(new NotifyingPropertyChangeListener());
   m_forumPosterEditor.addPropertyChangeListener(new NotifyingPropertyChangeListener());
   m_emailSenderEditor.addPropertyChangeListener(new NotifyingPropertyChangeListener());
   m_webPosterEditor.addPropertyChangeListener(new NotifyingPropertyChangeListener());
 }
 /**
  * Creates a new instance
  *
  * @param model the GameSelectionModel, though which changes are obtained when new games are
  *     chosen, or save games loaded
  */
 public PBEMSetupPanel(final GameSelectorModel model) {
   m_gameSelectorModel = model;
   m_diceServerEditor = new SelectAndViewEditor("Dice Server", "");
   m_forumPosterEditor = new SelectAndViewEditor("Post to Forum", "forumPosters.html");
   m_emailSenderEditor = new SelectAndViewEditor("Provider", "emailSenders.html");
   m_webPosterEditor = new SelectAndViewEditor("Send to Website", "websiteSenders.html");
   createComponents();
   layoutComponents();
   setupListeners();
   if (m_gameSelectorModel.getGameData() != null) {
     loadAll();
   }
   setWidgetActivation();
 }
 /**
  * Load the dice rollers from cache, if the game was a save game, the dice roller store is
  * selected
  *
  * @param data the game data
  */
 private void loadDiceServer(final GameData data) {
   final List<IRemoteDiceServer> diceRollers =
       new ArrayList<>(PropertiesDiceRoller.loadFromFile());
   diceRollers.add(new InternalDiceServer());
   for (final IRemoteDiceServer diceRoller : diceRollers) {
     final IRemoteDiceServer cached =
         (IRemoteDiceServer) LocalBeanCache.INSTANCE.getSerializable(diceRoller.getDisplayName());
     if (cached != null) {
       diceRoller.setCcAddress(cached.getCcAddress());
       diceRoller.setToAddress(cached.getToAddress());
       diceRoller.setGameId(cached.getGameId());
     }
   }
   m_diceServerEditor.setBeans(diceRollers);
   if (m_gameSelectorModel.isSavedGame()) {
     // get the dice roller from the save game, if any
     final IRemoteDiceServer roller = (IRemoteDiceServer) data.getProperties().get(DICE_ROLLER);
     if (roller != null) {
       m_diceServerEditor.setSelectedBean(roller);
     }
   }
 }
 @Override
 public void postStartGame() {
   // // store the dice server
   final GameData data = m_gameSelectorModel.getGameData();
   data.getProperties().set(DICE_ROLLER, m_diceServerEditor.getBean());
   // store the Turn Summary Poster
   final IForumPoster poster = (IForumPoster) m_forumPosterEditor.getBean();
   if (poster != null) {
     IForumPoster summaryPoster = poster;
     // clone the poster, the remove sensitive info, and put the clone into the game data
     // this was the sensitive info is not stored in the save game, but the user cache still has
     // the password
     summaryPoster = summaryPoster.doClone();
     summaryPoster.clearSensitiveInfo();
     data.getProperties().set(PBEMMessagePoster.FORUM_POSTER_PROP_NAME, summaryPoster);
   }
   // store the email poster
   IEmailSender sender = (IEmailSender) m_emailSenderEditor.getBean();
   if (sender != null) {
     // create a clone, delete the sensitive information in the clone, and use it in the game
     // the locally cached version still has the password so the user doesn't have to enter it
     // every time
     sender = sender.doClone();
     sender.clearSensitiveInfo();
     data.getProperties().set(PBEMMessagePoster.EMAIL_SENDER_PROP_NAME, sender);
   }
   // store the web site poster
   IWebPoster webPoster = (IWebPoster) m_webPosterEditor.getBean();
   if (webPoster != null) {
     webPoster = webPoster.doClone();
     webPoster.clearSensitiveInfo();
     data.getProperties().set(PBEMMessagePoster.WEB_POSTER_PROP_NAME, webPoster);
   }
   // store whether we are a pbem game or not, whether we are capable of posting a game save
   if (poster != null || sender != null || webPoster != null) {
     data.getProperties().set(PBEMMessagePoster.PBEM_GAME_PROP_NAME, true);
   }
 }
 @Override
 public boolean canGameStart() {
   if (m_gameSelectorModel.getGameData() == null || m_model == null) {
     return false;
   }
   final Map<String, String> players = m_model.getPlayersToNodeListing();
   if (players == null || players.isEmpty()) {
     return false;
   }
   for (final String player : players.keySet()) {
     if (players.get(player) == null) {
       return false;
     }
   }
   // make sure at least 1 player is enabled
   final Map<String, Boolean> someoneEnabled = m_model.getPlayersEnabledListing();
   for (final Boolean bool : someoneEnabled.values()) {
     if (bool) {
       return true;
     }
   }
   return false;
 }
 private void layoutPlayerPanel(final SetupPanel parent) {
   final GameData data = m_gameSelectorModel.getGameData();
   m_localPlayerPanel.removeAll();
   m_playerTypes.clear();
   m_localPlayerPanel.setLayout(new GridBagLayout());
   if (data == null) {
     m_localPlayerPanel.add(new JLabel("No game selected!"));
     return;
   }
   final Collection<String> disableable = data.getPlayerList().getPlayersThatMayBeDisabled();
   final HashMap<String, Boolean> playersEnablementListing =
       data.getPlayerList().getPlayersEnabledListing();
   final Map<String, String> reloadSelections = PlayerID.currentPlayers(data);
   final String[] playerTypes = data.getGameLoader().getServerPlayerTypes();
   final String[] playerNames = data.getPlayerList().getNames();
   // if the xml was created correctly, this list will be in turn order. we want to keep it that
   // way.
   int gridx = 0;
   int gridy = 0;
   if (!disableable.isEmpty() || playersEnablementListing.containsValue(Boolean.FALSE)) {
     final JLabel enableLabel = new JLabel("Use");
     enableLabel.setForeground(Color.black);
     m_localPlayerPanel.add(
         enableLabel,
         new GridBagConstraints(
             gridx++,
             gridy,
             1,
             1,
             0,
             0,
             GridBagConstraints.WEST,
             GridBagConstraints.NONE,
             new Insets(0, 5, 5, 0),
             0,
             0));
   }
   final JLabel nameLabel = new JLabel("Name");
   nameLabel.setForeground(Color.black);
   m_localPlayerPanel.add(
       nameLabel,
       new GridBagConstraints(
           gridx++,
           gridy,
           1,
           1,
           0,
           0,
           GridBagConstraints.WEST,
           GridBagConstraints.NONE,
           new Insets(0, 5, 5, 0),
           0,
           0));
   final JLabel typeLabel = new JLabel("Type");
   typeLabel.setForeground(Color.black);
   m_localPlayerPanel.add(
       typeLabel,
       new GridBagConstraints(
           gridx++,
           gridy,
           1,
           1,
           0,
           0,
           GridBagConstraints.WEST,
           GridBagConstraints.NONE,
           new Insets(0, 5, 5, 0),
           0,
           0));
   final JLabel allianceLabel = new JLabel("Alliance");
   allianceLabel.setForeground(Color.black);
   m_localPlayerPanel.add(
       allianceLabel,
       new GridBagConstraints(
           gridx++,
           gridy,
           1,
           1,
           0,
           0,
           GridBagConstraints.WEST,
           GridBagConstraints.NONE,
           new Insets(0, 7, 5, 5),
           0,
           0));
   for (final String playerName : playerNames) {
     final PBEMLocalPlayerComboBoxSelector selector =
         new PBEMLocalPlayerComboBoxSelector(
             playerName,
             reloadSelections,
             disableable,
             playersEnablementListing,
             data.getAllianceTracker()
                 .getAlliancesPlayerIsIn(data.getPlayerList().getPlayerID(playerName)),
             playerTypes,
             parent);
     m_playerTypes.add(selector);
     selector.layout(++gridy, m_localPlayerPanel);
   }
   m_localPlayerPanel.validate();
   m_localPlayerPanel.invalidate();
 }
 /** Called when the current game changes */
 @Override
 public void cancel() {
   m_gameSelectorModel.deleteObserver(this);
 }
 @Override
 public void shutDown() {
   m_gameSelectorModel.deleteObserver(this);
 }
 private void loadAll() {
   loadDiceServer(m_gameSelectorModel.getGameData());
   loadForumPosters(m_gameSelectorModel.getGameData());
   loadEmailSender(m_gameSelectorModel.getGameData());
   loadWebPosters(m_gameSelectorModel.getGameData());
 }
 @Override
 public void postStartGame() {
   final GameData data = m_gameSelectorModel.getGameData();
   data.getProperties().set(PBEMMessagePoster.PBEM_GAME_PROP_NAME, false);
 }