001/*
002 * Copyright (c) 2005 Jens Schou, Staffan Gustafsson, Bjorn Lanneskog, 
003 * Einar Pehrson and Sebastian Kekkonen
004 *
005 * This file is part of
006 * CleanSheets Extension for Test Cases
007 *
008 * CleanSheets Extension for Test Cases is free software; you can
009 * redistribute it and/or modify it under the terms of the GNU General Public
010 * License as published by the Free Software Foundation; either version 2 of
011 * the License, or (at your option) any later version.
012 *
013 * CleanSheets Extension for Test Cases is distributed in the hope that
014 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
015 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016 * See the GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with CleanSheets Extension for Test Cases; if not, write to the
020 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
021 * Boston, MA  02111-1307  USA
022 */
023package csheets.ext.test.ui;
024
025import java.awt.BorderLayout;
026import java.util.Set;
027
028import javax.swing.JPanel;
029import javax.swing.JScrollPane;
030import javax.swing.event.TableModelEvent;
031import javax.swing.event.TableModelListener;
032import javax.swing.table.DefaultTableModel;
033
034import csheets.core.Cell;
035import csheets.core.Value;
036import csheets.ext.test.TestCase;
037import csheets.ext.test.TestCaseParam;
038import csheets.ext.test.TestExtension;
039import csheets.ext.test.TestableCell;
040import csheets.ext.test.TestableCellListener;
041import csheets.ui.ctrl.SelectionEvent;
042import csheets.ui.ctrl.SelectionListener;
043import csheets.ui.ctrl.UIController;
044
045/**
046 * A panel for displaying test cases and providing editing of their validation
047 * states.
048 * @author Bjorn Lanneskog
049 * @author Einar Pehrson
050 */
051@SuppressWarnings("serial")
052public class TestCasePanel extends JPanel implements SelectionListener,
053                TestableCellListener {
054        
055        /** Array which contains labels of columns in the table.*/
056        public static final String[] columnNames = {"Formula", "Result", "Validation state"};
057                
058        /** The table model for this table.*/
059        private DefaultTableModel tableModel;
060        
061        /** The viewable table. */
062        private TestCaseTable table;
063
064        /** Determines whether the table arranger should respond to events. */
065        private boolean listening = true;
066
067        /**
068         * Creates a new test case panel.
069         * @param uiController the user interface controller
070         */
071        public TestCasePanel(UIController uiController) {
072                // Creates and configures table
073                tableModel = new DefaultTableModel(columnNames, 0);
074                table = new TestCaseTable(tableModel);
075                tableModel.addTableModelListener(new ValidationStateChanger(uiController));
076                
077                // Configures layout and adds components
078                setLayout(new BorderLayout());
079                JScrollPane tableScrollPane = new JScrollPane(table);
080                add(tableScrollPane, BorderLayout.CENTER);
081        }
082
083        /**
084         * Updates the table of precedents when the active cell is changed.
085         * @param event the selection event that was fired
086         */
087        public void selectionChanged(SelectionEvent event) {
088                Cell cell = event.getCell();
089                if (cell != null) {
090                        TestableCell activeCell = (TestableCell)cell.getExtension(TestExtension.NAME);
091                        activeCell.addTestableCellListener(this);
092                        testCasesChanged(activeCell);
093                } else
094                        // Clears the table
095                        tableModel.setRowCount(0);
096
097                // Stops listening to previous active cell
098                if (event.getPreviousCell() != null)
099                        ((TestableCell)event.getPreviousCell().getExtension(TestExtension.NAME))
100                                .removeTestableCellListener(this);
101        }
102
103        /**
104         * Updates the table of test cases when they have changed.
105         * @param cell the cell in which the event occurred
106         */
107        public void testCasesChanged(TestableCell cell) {
108                // Clears the table
109                tableModel.setRowCount(0);
110
111                if (cell.hasTestCases()) {
112                        // Fetches the cell's formula, and displays it in the column header
113                        // String[] colNames = {cell.getFormula().toString(), "Result", "Validation state"};
114                        // tableModel.setColumnIdentifiers(colNames);
115        
116                        // Adds the test cases to the table
117                        Set<TestCase> testCases = cell.getTestCases();
118                        tableModel.setRowCount(testCases.size());
119                        int row = 0;
120                        listening = false;
121                        for (TestCase testCase : testCases) {
122                                tableModel.setValueAt(testCase, row, 0);
123                                tableModel.setValueAt(testCase.evaluate(), row, 1);
124                                tableModel.setValueAt(testCase.getValidationState(), row++, 2);
125                        }
126                        listening = true;
127                } // else
128                        // Clears the table header
129                        // tableModel.setColumnIdentifiers(columnNames);
130                table.packColumns();
131        }
132
133        public void testCaseParametersChanged(TestableCell cell) {}
134
135        /**
136         * A table model listener for setting the validation state of test cases.
137         * @author Einar Pehrson
138         */
139        protected class ValidationStateChanger implements TableModelListener {
140
141                /** The user interface controller */
142                private UIController uiController;
143
144                /**
145                 * Creates a new validation state changer
146                 * @param uiController the user interface controller
147                 */
148                public ValidationStateChanger(UIController uiController) {
149                        this.uiController = uiController;
150                }
151
152                /**
153                 * Sets the validation state of a test case.
154                 * @param e the event that was fired
155                 */
156                public void tableChanged(TableModelEvent e) {
157                        if(listening && e.getType() == TableModelEvent.UPDATE
158                                        && e.getFirstRow() >= 0) {
159                                // Stops listening
160                                listening = false;
161
162                                // Updates test case
163                                TestCase testCase = (TestCase)tableModel.getValueAt(e.getFirstRow(), 0);
164                                TestCase.ValidationState state = (TestCase.ValidationState)
165                                        tableModel.getValueAt(e.getFirstRow(), 2);
166                                if (state != testCase.getValidationState()) {
167                                        testCase.setValidationState(state);
168        
169                                        // Updates resulting param
170                                        TestableCell cell = testCase.getCell();
171                                        Value result = testCase.evaluate();
172                                        switch (state) {
173                                                case VALID:
174                                                        cell.addTestCaseParam(testCase.evaluate(),
175                                                                TestCaseParam.Type.DERIVED);
176                                                        break;
177                                                case PENDING:
178                                                case REJECTED:
179                                                        TestCaseParam resultParam = null;
180                                                        for (TestCaseParam param : cell.getTestCaseParams())
181                                                                if (result.equals(param.getValue()))
182                                                                        resultParam = param;
183                                                        if (resultParam != null)
184                                                                cell.removeTestCaseParam(resultParam,
185                                                                        TestCaseParam.Type.DERIVED);
186                                        }
187                                        uiController.setWorkbookModified(cell.getSpreadsheet().getWorkbook());
188                                }
189
190                                // Resumes
191                                listening = true;
192                        }
193                }
194        }
195}