/* * 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.solverview; import java.awt.Dimension; 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.Collection; import java.util.Collections; import java.util.List; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.AbstractTableModel; import pcgen.base.calculation.PCGenModifier; import pcgen.base.formula.base.LegalScope; import pcgen.base.formula.base.ScopeInstance; import pcgen.base.formula.base.VarScoped; import pcgen.base.formula.base.VariableID; import pcgen.base.solver.ProcessStep; import pcgen.base.solver.SplitFormulaSetup; import pcgen.cdom.enumeration.CharID; import pcgen.cdom.facet.FacetLibrary; import pcgen.cdom.facet.FormulaSetupFacet; import pcgen.cdom.facet.ScopeFacet; import pcgen.cdom.facet.SolverManagerFacet; import pcgen.cdom.facet.VariableLibraryFacet; import pcgen.facade.core.CharacterFacade; import pcgen.gui2.tools.Utility; import pcgen.gui2.util.JComboBoxEx; import pcgen.system.CharacterManager; import pcgen.system.LanguageBundle; public class SolverViewFrame extends JFrame { private static final ScopeFacet scopeFacet = FacetLibrary .getFacet(ScopeFacet.class); private static final VariableLibraryFacet variableLibraryFacet = FacetLibrary.getFacet(VariableLibraryFacet.class); private static final SolverManagerFacet solverManagerFacet = FacetLibrary .getFacet(SolverManagerFacet.class); private static final FormulaSetupFacet formulaSetupFacet = FacetLibrary .getFacet(FormulaSetupFacet.class); private JComboBoxEx scopeChooser; private LegalScope selectedScope; private JTextField varName; private String varNameText = " "; private JComboBoxEx objectChooser; private VarScoped activeObject; private JComboBoxEx identifierChooser; private CharID activeIdentifier; private JTable viewTable; private SolverTableModel tableModel; public SolverViewFrame() { identifierChooser = new JComboBoxEx(); for (CharacterFacade pcf : CharacterManager.getCharacters()) { String pcname = pcf.getNameRef().get(); CharID id = pcf.getCharID(); identifierChooser.addItem(new PCRef(pcname, id)); } identifierChooser.addActionListener(new IdentifierActionListener()); objectChooser = new JComboBoxEx(); objectChooser.addActionListener(new ObjectActionListener()); scopeChooser = new JComboBoxEx(); scopeChooser.addActionListener(new ScopeActionListener()); identifierChooser.setSelectedItem(identifierChooser.getItemAt(0)); scopeChooser.setSelectedItem(scopeChooser.getItemAt(0)); varName = new JTextField(); varName.setText(varNameText); varName.getDocument().addDocumentListener(new VarNameListener()); initialize(); objectChooser.setSelectedItem(objectChooser.getItemAt(0)); } private void update() { updateObjects(); ScopeInstance scope = scopeFacet.get(activeIdentifier, selectedScope.getName(), activeObject); if (variableLibraryFacet .isLegalVariableName(activeIdentifier.getDatasetID(), scope.getLegalScope(), varNameText)) { displayInfo(scope); } else { //TODO Update a status bar System.err.println(selectedScope.getName() + " does not have a variable: " + varNameText); } } private void displayInfo(ScopeInstance scope) { VariableID<?> varID = variableLibraryFacet.getVariableID( activeIdentifier.getDatasetID(), scope, varNameText); setSteps(varID); } private <T> void setSteps(VariableID<T> varID) { List<ProcessStep<T>> steps = solverManagerFacet.diagnose(activeIdentifier, varID); tableModel.setSteps(steps); } private class ScopeActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { LegalScopeWrapper wrap = (LegalScopeWrapper) scopeChooser.getSelectedItem(); selectedScope = wrap.getLegalScope(); update(); } } private class ObjectActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { ObjectNameDisplayer displayer = (ObjectNameDisplayer) objectChooser.getSelectedItem(); if (displayer == null) { activeObject = null; tableModel.setSteps(Collections.emptyList()); } else { activeObject = displayer.getObject(); update(); } } } private class VarNameListener implements DocumentListener { @Override public void insertUpdate(DocumentEvent e) { varNameText = varName.getText().trim(); update(); } @Override public void removeUpdate(DocumentEvent e) { varNameText = varName.getText().trim(); update(); } @Override public void changedUpdate(DocumentEvent e) { varNameText = varName.getText().trim(); update(); } } private class IdentifierActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { Object item = identifierChooser.getSelectedItem(); activeIdentifier = ((PCRef) item).id; SplitFormulaSetup formulaSetup = formulaSetupFacet.get(activeIdentifier.getDatasetID()); for (LegalScope lvs : formulaSetup.getLegalScopeLibrary().getLegalScopes()) { scopeChooser.addItem(new LegalScopeWrapper(lvs)); } update(); } } private void updateObjects() { if (activeIdentifier != null) { Collection<VarScoped> objects = scopeFacet.getObjectsWithVariables(activeIdentifier); objectChooser.removeAllItems(); String scopeName = selectedScope.getName(); for (VarScoped cdo : objects) { if (cdo.getLocalScopeName().equals(scopeName)) { if (scopeFacet.get(activeIdentifier, selectedScope.getName(), cdo) != null) { objectChooser.addItem(new ObjectNameDisplayer(cdo)); } } } if (objectChooser.getItemCount() != 0) { objectChooser.setSelectedIndex(0); } } } public void initialize() { 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_SolverView_Perspective")); //$NON-NLS-1$ gridbag.setConstraints(label, c); getContentPane().add(label); Utility.buildConstraints(c, col++, 1, 1, 1, 0, 20); gridbag.setConstraints(identifierChooser, c); getContentPane().add(identifierChooser); Utility.buildConstraints(c, col++, 1, 1, 1, 0, 20); gridbag.setConstraints(scopeChooser, c); getContentPane().add(scopeChooser); Utility.buildConstraints(c, col++, 1, 1, 1, 0, 20); gridbag.setConstraints(objectChooser, c); getContentPane().add(objectChooser); Utility.buildConstraints(c, col++, 1, 1, 1, 0, 20); label = new JLabel( LanguageBundle.getFormattedString("in_SolverView_VarName") //$NON-NLS-1$ ); gridbag.setConstraints(label, c); getContentPane().add(label); Utility.buildConstraints(c, col++, 1, 1, 1, 0, 20); gridbag.setConstraints(varName, c); getContentPane().add(varName); tableModel = new SolverTableModel(); viewTable = new JTable(tableModel); viewTable.getColumnModel().getColumn(0).setPreferredWidth(25); viewTable.getColumnModel().getColumn(1).setPreferredWidth(50); viewTable.getColumnModel().getColumn(2).setPreferredWidth(25); viewTable.getColumnModel().getColumn(3).setPreferredWidth(50); Utility.buildConstraints(c, 0, 2, col, 1, 0, 1000); JScrollPane pane = new JScrollPane(viewTable); viewTable.setFillsViewportHeight(true); pane.setPreferredSize(new Dimension(500, 300)); gridbag.setConstraints(pane, c); getContentPane().add(pane); setTitle("Core Variable Debug View"); getContentPane().setSize(500, 400); pack(); Utility.centerComponent(this, true); } private static class SolverTableModel<T> extends AbstractTableModel { private String[] columnNames = {"Modification Type", "Modification", "Resulting Value", "Priority", "Source"}; private List<ProcessStep<T>> steps = Collections.emptyList(); @Override public String getColumnName(int column) { return columnNames[column]; } @Override public int getRowCount() { return steps.size(); } @Override public int getColumnCount() { return columnNames.length; } @Override public Object getValueAt(int rowIndex, int columnIndex) { ProcessStep<T> ps = steps.get(rowIndex); switch (columnIndex) { case 0: return ps.getModifier().getIdentification(); case 1: return ps.getModifier().getInstructions(); case 2: return ps.getResult(); case 3: return ((PCGenModifier<?>) ps.getModifier()).getUserPriority(); case 4: return ps.getSourceInfo(); default: return ""; } } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } public void setSteps(List<ProcessStep<T>> steps) { this.steps = steps; fireTableDataChanged(); } } private static final class PCRef { public String name; public CharID id; private PCRef(String pcname, CharID id) { this.name = pcname; this.id = id; } @Override public String toString() { return name; } } }