/** * DescriptionInfoTab.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 29/09/2010 7:16:42 PM * * $Id: DescriptionInfoTab.java 13208 2010-09-29 12:59:43Z jdempsey $ */ package pcgen.gui2.tabs; import java.awt.CardLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Box; import javax.swing.DefaultListModel; import javax.swing.DefaultListSelectionModel; import javax.swing.JButton; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListModel; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import pcgen.facade.core.CharacterFacade; import pcgen.facade.core.NoteFacade; import pcgen.facade.util.event.ListEvent; import pcgen.facade.util.event.ListListener; import pcgen.facade.util.ListFacade; import pcgen.gui2.tabs.bio.BiographyInfoPane; import pcgen.gui2.tabs.bio.CampaignHistoryInfoPane; import pcgen.gui2.tabs.bio.NoteInfoPane; import pcgen.gui2.tabs.bio.PortraitInfoPane; import pcgen.gui2.tools.FlippingSplitPane; import pcgen.system.LanguageBundle; import pcgen.util.enumeration.Tab; /** * The Class {@code DescriptionInfoTab} is a placeholder for the yet to be * implemented description tab. * * <br> * -0700 (Wed, 29 Sep 2010) $ * * @author James Dempsey <jdempsey@users.sourceforge.net> */ @SuppressWarnings("serial") public class DescriptionInfoTab extends FlippingSplitPane implements CharacterInfoTab { private final TabTitle tabTitle = new TabTitle(Tab.DESCRIPTION); private final PortraitInfoPane portraitPane; private final BiographyInfoPane bioPane; private final CampaignHistoryInfoPane histPane; private final JList pageList; private final JButton addButton; private final JPanel pagePanel; /** * Create a new instance of DescriptionInfoTab */ public DescriptionInfoTab() { super("Desc"); //$NON-NLS-1$ this.portraitPane = new PortraitInfoPane(); this.bioPane = new BiographyInfoPane(); this.histPane = new CampaignHistoryInfoPane(); this.pageList = new JList(); this.addButton = new JButton(); this.pagePanel = new JPanel(); initComponents(); } private void initComponents() { addButton.setAlignmentX((float) 0.5); Box box = Box.createVerticalBox(); box.add(new JScrollPane(pageList)); box.add(Box.createVerticalStrut(5)); { Box hbox = Box.createHorizontalBox(); hbox.add(Box.createRigidArea(new Dimension(8, 0))); hbox.add(addButton); hbox.add(Box.createRigidArea(new Dimension(8, 0))); box.add(hbox); } box.add(Box.createVerticalStrut(4)); setLeftComponent(box); CardLayout pages = new CardLayout(); pagePanel.setLayout(pages); addPage(bioPane); addPage(portraitPane); addPage(histPane); setRightComponent(pagePanel); setResizeWeight(0); } private <T extends Component & CharacterInfoTab> void addPage(T page) { pagePanel.add(page, page.getTabTitle().getValue(TabTitle.TITLE)); } /** * @param noteInfoPane */ private <T extends Component & CharacterInfoTab> void removePage(T page) { pagePanel.remove(page); } @Override public ModelMap createModels(CharacterFacade character) { ModelMap models = new ModelMap(); DefaultListModel listModel = new DefaultListModel(); List<NoteInfoPane> notePaneList = new ArrayList<>(); PageItem firstPage = new PageItem(character, LanguageBundle.getString("in_descBiography"), bioPane); //$NON-NLS-1$ listModel.addElement(firstPage); listModel.addElement(new PageItem(character, LanguageBundle.getString("in_portrait"), portraitPane)); //$NON-NLS-1$ listModel.addElement(new PageItem(character, LanguageBundle.getString("in_descCampHist"), histPane)); //$NON-NLS-1$ models.put(ListModel.class, listModel); models.put(List.class, notePaneList); models.put(NoteListHandler.class, new NoteListHandler(character, listModel, notePaneList)); ListSelectionModel model = new DefaultListSelectionModel(); model.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); model.setSelectionInterval(0, 0); models.put(ListSelectionModel.class, model); models.put(PageHandler.class, new PageHandler(model, firstPage)); models.put(AddAction.class, new AddAction(character)); return models; } @Override public void restoreModels(ModelMap models) { pageList.setModel(models.get(ListModel.class)); pageList.setSelectionModel(models.get(ListSelectionModel.class)); models.get(NoteListHandler.class).install(); models.get(PageHandler.class).install(); addButton.setAction(models.get(AddAction.class)); } @Override public void storeModels(ModelMap models) { pageList.setSelectionModel(new DefaultListSelectionModel()); models.get(PageHandler.class).uninstall(); models.get(NoteListHandler.class).uninstall(); } @Override public TabTitle getTabTitle() { return tabTitle; } private class NoteListHandler implements ListListener<NoteFacade> { private static final int NUM_NON_NOTE_NODES = 3; private ListFacade<NoteFacade> notes; private final DefaultListModel listModel; private final List<NoteInfoPane> notePaneList; private final CharacterFacade character; public NoteListHandler(CharacterFacade character, DefaultListModel listModel, List<NoteInfoPane> notePaneList) { this.character = character; this.listModel = listModel; this.notePaneList = notePaneList; this.notes = character.getDescriptionFacade().getNotes(); for (NoteFacade note : notes) { createNotePane(note, character, listModel, notePaneList, -1); } } private NoteInfoPane createNotePane(NoteFacade note, CharacterFacade character, DefaultListModel listModel, List<NoteInfoPane> notePaneList, int pos) { NoteInfoPane notePane = new NoteInfoPane(note); PageItem pageItem = new PageItem(character, note, notePane); if (pos >= 0 && pos < notePaneList.size()) { // List model also has the portrait etc tabs, so we have to skip over those. listModel.insertElementAt(pageItem, pos + NUM_NON_NOTE_NODES); notePaneList.add(pos, notePane); } else { listModel.addElement(pageItem); notePaneList.add(notePane); } return notePane; } public void install() { notes.addListListener(this); for (NoteInfoPane noteInfoPane : notePaneList) { addPage(noteInfoPane); } } public void uninstall() { notes.removeListListener(this); for (NoteInfoPane noteInfoPane : notePaneList) { removePage(noteInfoPane); } } @Override public void elementAdded(ListEvent<NoteFacade> e) { NoteFacade note = e.getElement(); NoteInfoPane notePane = createNotePane(note, character, listModel, notePaneList, e.getIndex()); addPage(notePane); } @Override public void elementRemoved(ListEvent<NoteFacade> e) { NoteFacade note = e.getElement(); if (note == null) { return; } removeNote(note); // Select the next node int index = e.getIndex() + NUM_NON_NOTE_NODES; if (index >= pageList.getModel().getSize()) { index = pageList.getModel().getSize() - 1; } pageList.setSelectedIndex(index); } private void removeNote(NoteFacade note) { for (Iterator<NoteInfoPane> iterator = notePaneList.iterator(); iterator.hasNext();) { NoteInfoPane pane = iterator.next(); if (pane.getNote().equals(note)) { iterator.remove(); break; } } for (int i = 0; i < listModel.getSize(); i++) { PageItem item = (PageItem) listModel.elementAt(i); if (note == item.note) { listModel.removeElement(item); break; } } } @Override public void elementsChanged(ListEvent<NoteFacade> e) { for (NoteInfoPane pane : notePaneList) { listModel.removeElement(pane); } notePaneList.clear(); for (NoteFacade note : notes) { createNotePane(note, character, listModel, notePaneList, -1); } } @Override public void elementModified(ListEvent<NoteFacade> e) { NoteFacade note = e.getElement(); if (note == null) { return; } int noteIndex = e.getIndex(); listModel.set(noteIndex, listModel.getElementAt(noteIndex)); } } private static class PageItem { private NoteFacade note; private String name; private String id; private CharacterInfoTab page; private ModelMap data; /** * Create a new instance of PageItem to represent a Note. * * @param character The character being displayed. * @param note The note being represented. * @param page The page to display the note. */ public PageItem(CharacterFacade character, NoteFacade note, CharacterInfoTab page) { this.note = note; this.name = ""; //$NON-NLS-1$ this.id = (String) page.getTabTitle().getValue(TabTitle.TITLE); this.page = page; this.data = page.createModels(character); } /** * Create a new instance of PageItem to represent a pre-defined panel. * * @param character The character being displayed. * @param name The name of the page. * @param page The pre-defined page.. */ public PageItem(CharacterFacade character, String name, CharacterInfoTab page) { this.note = null; this.name = name; this.id = (String) page.getTabTitle().getValue(TabTitle.TITLE); this.page = page; this.data = page.createModels(character); } @Override public String toString() { return note == null ? name : note.getName(); } public void storeModels() { page.storeModels(data); } public void restoreModels() { page.restoreModels(data); } } private class PageHandler implements ListSelectionListener { private final ListSelectionModel selectionModel; private PageItem currentPage; public PageHandler(ListSelectionModel selectionModel, PageItem currentPage) { this.selectionModel = selectionModel; this.currentPage = currentPage; } @Override public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } PageItem item = (PageItem) pageList.getSelectedValue(); if (item == null) { return; } currentPage.storeModels(); currentPage = item; currentPage.restoreModels(); CardLayout pages = (CardLayout) pagePanel.getLayout(); pages.show(pagePanel, currentPage.id); } public void install() { selectionModel.addListSelectionListener(this); currentPage.restoreModels(); CardLayout pages = (CardLayout) pagePanel.getLayout(); pages.show(pagePanel, currentPage.id); } public void uninstall() { selectionModel.removeListSelectionListener(this); currentPage.storeModels(); } } /** * The Class {@code AddAction} acts on a user pressing the Add Note * button. */ private class AddAction extends AbstractAction { private final CharacterFacade character; public AddAction(CharacterFacade character) { super(LanguageBundle.getString("in_descAddPage")); //$NON-NLS-1$ this.character = character; } @Override public void actionPerformed(ActionEvent e) { character.getDescriptionFacade().addNewNote(); } } }