/* * AbilitiesInfoTab.java * Copyright 2008 Connor Petty <cpmeister@users.sourceforge.net> * * 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 Jul 15, 2008, 6:58:51 PM */ package pcgen.gui2.tabs; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import pcgen.facade.core.AbilityCategoryFacade; import pcgen.facade.core.AbilityFacade; import pcgen.facade.core.CharacterFacade; import pcgen.facade.util.DefaultListFacade; import pcgen.facade.util.ListFacade; import pcgen.facade.util.event.ListEvent; import pcgen.facade.util.event.ListListener; import pcgen.facade.util.MapFacade; import pcgen.gui2.util.SharedTabPane; import pcgen.util.Logging; import pcgen.util.enumeration.Tab; /** * This component is the tabbed pane which contains all of the * AbilityChooserTabs. This component doesn't actually display any character * information, that is the job of the AbilityChooserTab. All this class does is * manage the states of all the AbilityChooserTab. * * @see AbilityChooserTab * @author Connor Petty <cpmeister@users.sourceforge.net> */ @SuppressWarnings("serial") public class AbilitiesInfoTab extends SharedTabPane implements CharacterInfoTab, TodoHandler { private final AbilityChooserTab abilityTab; private final TabTitle tabTitle; public AbilitiesInfoTab() { this.abilityTab = new AbilityChooserTab(); this.tabTitle = new TabTitle(Tab.ABILITIES); setSharedComponent(abilityTab); } @Override public ModelMap createModels(CharacterFacade character) { ModelMap models = new ModelMap(); models.put(AbilityTabsModel.class, new AbilityTabsModel(character)); return models; } @Override public void storeModels(ModelMap models) { models.get(AbilityTabsModel.class).uninstall(); } @Override public void restoreModels(ModelMap models) { models.get(AbilityTabsModel.class).install(); } @Override public TabTitle getTabTitle() { return tabTitle; } private class AbilityTabsModel implements ListListener<AbilityCategoryFacade>, ChangeListener { private final Map<String, TabInfo> typeMap = new HashMap<>(); private final List<TabInfo> tabs = new ArrayList<>(); private final MapFacade<AbilityCategoryFacade, ListFacade<AbilityFacade>> categoryMap; private final CharacterFacade character; private boolean isInstalled = false; private String selectedTitle = null; private ListFacade<AbilityCategoryFacade> activeCategories; public AbilityTabsModel(CharacterFacade character) { this.character = character; this.activeCategories = character.getActiveAbilityCategories(); this.categoryMap = character.getDataSet().getAbilities(); for (AbilityCategoryFacade category : activeCategories) { String type = category.getType(); if (!typeMap.containsKey(type)) { tabs.add(new TabInfo(type, character)); populateFullCategoryList(type, typeMap.get(type)); } typeMap.get(type).categoryList.addElement(category); } selectedTitle = tabs.get(0).title; } /** * Populate the fullCategoryList for a TabInfo object with all * categories of the specified type. * * @param type The type to be scanned for. * @param tabInfo The TabInfo to be populated. */ private void populateFullCategoryList(String type, TabInfo tabInfo) { for (AbilityCategoryFacade category : categoryMap.getKeys()) { if (type.equals(category.getType())) { tabInfo.fullCategoryList.addElement(category); } } } @Override public void elementAdded(ListEvent<AbilityCategoryFacade> e) { AbilityCategoryFacade element = e.getElement(); String type = element.getType(); if (!typeMap.containsKey(type)) { int index = e.getIndex(); if (index > tabs.size()) { Logging.log(Logging.WARNING, "Trying to add " + type + " to " //$NON-NLS-1$ //$NON-NLS-2$ + tabs + " at index " +index //$NON-NLS-1$ + ". Putting at end."); //$NON-NLS-1$ index = tabs.size(); tabs.add(new TabInfo(type, character)); } else { tabs.add(index, new TabInfo(type, character)); } populateFullCategoryList(type, typeMap.get(type)); if (isInstalled) {//Add new tab addTab(type, index); } } typeMap.get(type).categoryList.addElement(element); } @Override public void elementRemoved(ListEvent<AbilityCategoryFacade> e) { AbilityCategoryFacade element = e.getElement(); String type = element.getType(); TabInfo info = typeMap.get(type); info.categoryList.removeElement(element); if (info.categoryList.isEmpty()) { tabs.remove(typeMap.remove(type)); if (isInstalled) {//Remove Tab removeTab(type); } } } @Override public void elementsChanged(ListEvent<AbilityCategoryFacade> e) { Map<String, List<AbilityCategoryFacade>> tempMap; tempMap = new HashMap<>(); for (AbilityCategoryFacade category : categoryMap.getKeys()) { String type = category.getType(); if (!tempMap.containsKey(type)) { tempMap.put(type, new ArrayList<>()); } tempMap.get(type).add(category); } for (String type : tempMap.keySet()) { if (!typeMap.containsKey(type)) { tabs.add(new TabInfo(type, character)); populateFullCategoryList(type, typeMap.get(type)); if (isInstalled) { addTab(type); } } typeMap.get(type).categoryList.updateContents(tempMap.get(type)); } Iterator<String> oldTypes = typeMap.keySet().iterator(); while (oldTypes.hasNext()) { String type = oldTypes.next(); if (!tempMap.containsKey(type)) { tabs.remove(typeMap.get(type)); oldTypes.remove(); if (isInstalled) { removeTab(type); } } } } @Override public void elementModified(ListEvent<AbilityCategoryFacade> e) { //TODO: do something } public void install() { activeCategories.addListListener(this); for (TabInfo tabInfo : tabs) { addTab(tabInfo.title); } setSelectedIndex(indexOfTab(selectedTitle)); abilityTab.restoreState(typeMap.get(selectedTitle).tabData); addChangeListener(this); isInstalled = true; } public void uninstall() { abilityTab.storeState(typeMap.get(selectedTitle).tabData); removeChangeListener(this); removeAll(); activeCategories.removeListListener(this); isInstalled = false; } @Override public void stateChanged(ChangeEvent e) { TabInfo tabInfo = typeMap.get(selectedTitle); if (tabInfo != null) { abilityTab.storeState(tabInfo.tabData); } if (getSelectedIndex() != -1) { selectedTitle = getTitleAt(getSelectedIndex()); if (typeMap.get(selectedTitle) == null) { Logging.errorPrint("Selected tab " + selectedTitle + " at index " + getSelectedIndex() + " but there is no typeMap entry for it."); Logging.reportAllThreads(); } abilityTab.restoreState(typeMap.get(selectedTitle).tabData); } } private class TabInfo { public final String title; public final Hashtable<Object, Object> tabData; public final DefaultListFacade<AbilityCategoryFacade> categoryList; public final DefaultListFacade<AbilityCategoryFacade> fullCategoryList; public TabInfo(String title, CharacterFacade character) { this.title = title; this.categoryList = new DefaultListFacade<>(); this.fullCategoryList = new DefaultListFacade<>(); this.tabData = abilityTab.createState(character, categoryList, fullCategoryList, title); typeMap.put(title, this); } @SuppressWarnings("nls") @Override public String toString() { return "TabInfo [title=" + title + ", categoryList=" + categoryList + "]"; } } @SuppressWarnings("nls") @Override public String toString() { return "AbilityTabsModel [tabs=" + tabs + ", isInstalled=" + isInstalled + ", selectedTitle=" + selectedTitle + "]"; } } @Override public void adviseTodo(String fieldName) { abilityTab.adviseTodo(fieldName); } }