/**
* LanguageChooserFacadeImpl.java
* Copyright James Dempsey, 2010
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Created on 15/07/2010 4:08:09 PM
*
* $Id$
*/
package pcgen.gui2.facade;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import pcgen.cdom.base.ChooseDriver;
import pcgen.cdom.base.ChooseInformation;
import pcgen.cdom.content.CNAbility;
import pcgen.cdom.enumeration.ObjectKey;
import pcgen.core.Ability;
import pcgen.core.Globals;
import pcgen.core.Language;
import pcgen.core.PlayerCharacter;
import pcgen.core.RuleConstants;
import pcgen.core.Skill;
import pcgen.core.analysis.SkillRankControl;
import pcgen.core.chooser.ChoiceManagerList;
import pcgen.core.chooser.ChooserUtilities;
import pcgen.core.display.CharacterDisplay;
import pcgen.facade.util.DefaultReferenceFacade;
import pcgen.facade.core.LanguageChooserFacade;
import pcgen.facade.core.LanguageFacade;
import pcgen.facade.util.ReferenceFacade;
import pcgen.facade.util.DefaultListFacade;
import pcgen.facade.util.ListFacade;
/**
* The Class {@code LanguageChooserFacadeImpl} is an implementation of the
* LanguageChooserFacade for the gui2 package. It is responsible for managing
* details of a possible selection of languages.
*
* <br>
*
* @author James Dempsey <jdempsey@users.sourceforge.net>
*/
public final class LanguageChooserFacadeImpl implements LanguageChooserFacade
{
private final PlayerCharacter theCharacter;
private final CharacterDisplay charDisplay;
private ChooseDriver source;
private String name;
private DefaultListFacade<LanguageFacade> availableList;
private DefaultListFacade<LanguageFacade> selectedList;
private DefaultListFacade<LanguageFacade> originalSelectedList;
private DefaultReferenceFacade<Integer> numSelectionsRemain;
private CharacterFacadeImpl pcFacade;
/**
* Create a new LanguageChooserFacadeImpl. This is initially empty but will be
* populated upon the available list being requested. Called commit or rollback
* ends the 'transaction'.
*
* @param pcFacade The character facade managing this chooser facade.
* @param name The name of the chooser
* @param source The source of the languages list, null for racial bionus languages.
*/
public LanguageChooserFacadeImpl(CharacterFacadeImpl pcFacade, String name, ChooseDriver source)
{
this.pcFacade = pcFacade;
this.theCharacter = pcFacade.getTheCharacter();
this.charDisplay = theCharacter.getDisplay();
this.name = name;
this.source = source;
availableList = new DefaultListFacade<>();
selectedList = new DefaultListFacade<>();
originalSelectedList = new DefaultListFacade<>();
numSelectionsRemain = new DefaultReferenceFacade<>(0);
}
/**
* Populate the lists of available and selected languages ready for use by a chooser.
*/
private void buildLanguageList()
{
if (!(source instanceof Skill))
{
buildBonusLangList();
}
else
{
buildObjectLangList();
}
}
/**
* Build up the language lists for a choice of racial bonus languages.
*/
private void buildBonusLangList()
{
CNAbility cna = theCharacter.getBonusLanguageAbility();
Ability a = cna.getAbility();
List<Language> availLangs = new ArrayList<>();
ChooseInformation<Language> chooseInfo =
(ChooseInformation<Language>) a.get(ObjectKey.CHOOSE_INFO);
availLangs.addAll(chooseInfo.getSet(theCharacter));
List<? extends Language> selLangs =
chooseInfo.getChoiceActor().getCurrentlySelected(cna,
theCharacter);
if (selLangs == null)
{
selLangs = Collections.emptyList();
}
availLangs.removeAll(charDisplay.getLanguageSet());
refreshLangListContents(availLangs, availableList);
refreshLangListContents(selLangs, selectedList);
refreshLangListContents(selLangs, originalSelectedList);
boolean allowBonusLangAfterFirst = Globals.checkRule(RuleConstants.INTBONUSLANG);
boolean atFirstLvl = theCharacter.getTotalLevels() <= 1;
if (allowBonusLangAfterFirst || atFirstLvl)
{
int bonusLangMax = theCharacter.getBonusLanguageCount();
numSelectionsRemain.set(bonusLangMax-selLangs.size());
}
else
{
numSelectionsRemain.set(0);
}
}
/**
* Build up the language lists for a choice of languages linked to a rules
* object. e.g. The speak language skill.
*/
private void buildObjectLangList()
{
final List<Language> availLangs = new ArrayList<>();
ChooseInformation<Language> chooseInfo =
(ChooseInformation<Language>) source.getChooseInfo();
availLangs.addAll(chooseInfo.getSet(theCharacter));
List<? extends Language> selLangs =
chooseInfo.getChoiceActor().getCurrentlySelected(source,
theCharacter);
if (selLangs == null)
{
selLangs = new ArrayList<>();
}
Set<Language> languageSet = charDisplay.getLanguageSet();
availLangs.removeAll(languageSet);
refreshLangListContents(availLangs, availableList);
refreshLangListContents(selLangs, selectedList);
refreshLangListContents(selLangs, originalSelectedList);
int numSelections = 0;
if (source instanceof Skill)
{
numSelections =
SkillRankControl.getTotalRank(theCharacter, (Skill) source)
.intValue()
- selectedList.getSize();
}
else
{
ChoiceManagerList<Language> aMan =
ChooserUtilities.getConfiguredController(source,
theCharacter, null, new ArrayList<>());
numSelections =
aMan.getNumEffectiveChoices(selLangs,
new ArrayList<>(), theCharacter);
}
numSelectionsRemain.set(numSelections);
}
/**
* Replace the contents of a list facade with the given languages.
*
* @param langList The source list of languages
* @param langListFacade The list facade to be populated
*/
private void refreshLangListContents(List<? extends Language> langList, DefaultListFacade<LanguageFacade> langListFacade)
{
Collections.sort(langList);
langListFacade.clearContents();
for (Language language : langList)
{
langListFacade.addElement(language);
}
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#addSelected(pcgen.core.facade.LanguageFacade)
*/
@Override
public void addSelected(LanguageFacade language)
{
if (numSelectionsRemain.get() <= 0)
{
return;
}
selectedList.addElement(language);
availableList.removeElement(language);
numSelectionsRemain.set(numSelectionsRemain.get()-1);
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#removeSelected(pcgen.core.facade.LanguageFacade)
*/
@Override
public void removeSelected(LanguageFacade language)
{
selectedList.removeElement(language);
availableList.addElement(language);
numSelectionsRemain.set(numSelectionsRemain.get()+1);
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#getAvailableList()
*/
@Override
public ListFacade<LanguageFacade> getAvailableList()
{
buildLanguageList();
return availableList;
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#getName()
*/
@Override
public String getName()
{
return name;
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#getRemainingSelections()
*/
@Override
public ReferenceFacade<Integer> getRemainingSelections()
{
return numSelectionsRemain;
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#getSelectedList()
*/
@Override
public ListFacade<LanguageFacade> getSelectedList()
{
return selectedList;
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#commit()
*/
@Override
@SuppressWarnings("unchecked")
public void commit()
{
ChoiceManagerList<Language> choiceManager = ChooserUtilities.getChoiceManager(source, theCharacter);
List<Language> selected = new ArrayList<>(selectedList.getSize());
for (LanguageFacade langFacade : selectedList)
{
selected.add((Language) langFacade);
}
choiceManager.applyChoices(theCharacter, selected);
// Update list on character facade
pcFacade.refreshLanguageList();
}
/* (non-Javadoc)
* @see pcgen.core.facade.LanguageChooserFacade#rollback()
*/
@Override
public void rollback()
{
buildLanguageList();
}
}