/* * Copyright (c) Thomas Parker, 2013-14. * * This program 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 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 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package pcgen.gui2.coreview; import java.awt.Dimension; import java.awt.Frame; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import org.apache.commons.lang3.StringUtils; import pcgen.cdom.meta.CorePerspective; import pcgen.facade.core.AbilityFacade; import pcgen.facade.core.CharacterFacade; import pcgen.facade.core.CoreViewNodeFacade; import pcgen.facade.util.DefaultListFacade; import pcgen.facade.util.DelegatingListFacade; import pcgen.facade.util.ListFacade; import pcgen.gui2.tools.Utility; import pcgen.gui2.util.JComboBoxEx; import pcgen.gui2.util.JTreeViewTable; import pcgen.gui2.util.treeview.DataView; import pcgen.gui2.util.treeview.DataViewColumn; import pcgen.gui2.util.treeview.DefaultDataViewColumn; import pcgen.gui2.util.treeview.TreeView; import pcgen.gui2.util.treeview.TreeViewModel; import pcgen.gui2.util.treeview.TreeViewPath; import pcgen.system.LanguageBundle; import pcgen.util.Logging; public class CoreViewFrame extends JFrame { private JComboBoxEx perspectiveChooser; private final JTreeViewTable<CoreViewNodeFacade> viewTable; public CoreViewFrame(Frame frame, CharacterFacade character) { viewTable = new JTreeViewTable<>(); perspectiveChooser = new JComboBoxEx(); for (CorePerspective pers : CorePerspective.getAllConstants()) { perspectiveChooser.addItem(pers); } final CoreViewTreeViewModel coreViewTreeViewModel = new CoreViewTreeViewModel(character); PerspectiveActionListener pal = new PerspectiveActionListener(coreViewTreeViewModel); perspectiveChooser.addActionListener(pal); initialize(character); perspectiveChooser.setSelectedItem(perspectiveChooser.getItemAt(0)); } public void initialize(CharacterFacade character) { GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); getContentPane().setLayout(gridbag); c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.NORTHWEST; c.insets = new Insets(2, 2, 2, 2); int col = 0; Utility.buildConstraints(c, col, 0, 1, 1, 100, 20); JLabel label = new JLabel(LanguageBundle.getFormattedString( "in_CoreView_Perspective")); //$NON-NLS-1$ gridbag.setConstraints(label, c); getContentPane().add(label); Utility.buildConstraints(c, col++, 1, 1, 1, 0, 20); gridbag.setConstraints(perspectiveChooser, c); getContentPane().add(perspectiveChooser); Utility.buildConstraints(c, 0, 2, col, 1, 0, 1000); viewTable.setAutoCreateRowSorter(true); JScrollPane pane = new JScrollPane(viewTable); pane.setPreferredSize(new Dimension(500, 300)); gridbag.setConstraints(pane, c); getContentPane().add(pane); setTitle("Core Debug View"); getContentPane().setSize(500, 400); pack(); Utility.centerComponent(this, true); } private final class PerspectiveActionListener implements ActionListener { private final CoreViewTreeViewModel coreViewTreeViewModel; private PerspectiveActionListener( CoreViewTreeViewModel coreViewTreeViewModel) { this.coreViewTreeViewModel = coreViewTreeViewModel; } public void actionPerformed(ActionEvent e) { CorePerspective perspective = (CorePerspective) perspectiveChooser.getSelectedItem(); coreViewTreeViewModel.setPerspective(perspective); viewTable.setTreeViewModel(coreViewTreeViewModel); } } private static class GrantedTreeView implements TreeView<CoreViewNodeFacade> { public GrantedTreeView() { } @Override public String getViewName() { return "Object Tree"; } @Override public List<TreeViewPath<CoreViewNodeFacade>> getPaths(CoreViewNodeFacade pobj) { List<List<CoreViewNodeFacade>> abilityPaths = new ArrayList<>(); addPaths(abilityPaths, pobj.getGrantedByNodes(), new ArrayList<>()); if (Logging.isDebugMode()) { Logging.debugPrint("Converted " + pobj.getGrantedByNodes() + " into " + abilityPaths + " for " + pobj); } if (abilityPaths.isEmpty()) { return Collections.singletonList(new TreeViewPath<>(pobj)); } List<TreeViewPath<CoreViewNodeFacade>> paths = new ArrayList<>(); for (List<CoreViewNodeFacade> path : abilityPaths) { Collections.reverse(path); paths.add(new TreeViewPath<CoreViewNodeFacade>(path.toArray(), pobj)); } return paths; } private void addPaths(List<List<CoreViewNodeFacade>> abilityPaths, List<CoreViewNodeFacade> grantedByNodes, ArrayList<CoreViewNodeFacade> path) { if (path.size() > 20) { Logging.errorPrint("Found probable ability prereq cycle [" + StringUtils.join(path, ",") + "] with prereqs [" + StringUtils.join(grantedByNodes, ",") + "]. Skipping."); return; } for (CoreViewNodeFacade node : grantedByNodes) { @SuppressWarnings("unchecked") ArrayList<CoreViewNodeFacade> pathclone = (ArrayList<CoreViewNodeFacade>) path.clone(); pathclone.add(node); List<CoreViewNodeFacade> preAbilities2 = node.getGrantedByNodes(); // Don't include self references in the path preAbilities2.remove(node); if (preAbilities2.isEmpty()) { abilityPaths.add(pathclone); } else { addPaths(abilityPaths, preAbilities2, pathclone); } } } } private static class CoreViewTreeViewModel extends DelegatingListFacade<AbilityFacade> implements TreeViewModel<CoreViewNodeFacade>, DataView<CoreViewNodeFacade> { private final CharacterFacade character; private DefaultListFacade<CoreViewNodeFacade> coreViewList; private final List<? extends DataViewColumn> dataColumns; public CoreViewTreeViewModel(CharacterFacade character) { this.character = character; dataColumns = Arrays.asList( new DefaultDataViewColumn("Key", String.class), new DefaultDataViewColumn("Node Type", String.class), new DefaultDataViewColumn("Source", String.class), new DefaultDataViewColumn("Requirements", String.class)); } /** * @param language */ public void setPerspective(CorePerspective corePerspective) { List<CoreViewNodeFacade> coreViewNodes = character.getCoreViewTree(corePerspective); coreViewList = new DefaultListFacade<>(coreViewNodes); } @Override public ListFacade<? extends TreeView<CoreViewNodeFacade>> getTreeViews() { DefaultListFacade<TreeView<CoreViewNodeFacade>> views = new DefaultListFacade<>(); views.addElement(new GrantedTreeView()); return views; } @Override public int getDefaultTreeViewIndex() { return 0; } @Override public DataView<CoreViewNodeFacade> getDataView() { return this; } @Override public ListFacade<CoreViewNodeFacade> getDataModel() { return coreViewList; } @Override public Object getData(CoreViewNodeFacade obj, int column) { switch (column) { case 0: return obj.getKey(); case 1: return obj.getNodeType(); case 2: return obj.getSource(); case 3: return obj.getRequirements(); default: return null; } } @Override public void setData(Object value, CoreViewNodeFacade element, int column) { } @Override public List<? extends DataViewColumn> getDataColumns() { return dataColumns; } @Override public String getPrefsKey() { return "CoreDebugView"; } } }