001/*
002 * Copyright (c) 2005 Peter Palotas, Fredrik Johansson, Einar Pehrson,
003 * Sebastian Kekkonen, Lars Magnus Lang, Malin Johansson and Sofia Nilsson
004 *
005 * This file is part of
006 * CleanSheets Extension for Assertions
007 *
008 * CleanSheets Extension for Assertions 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 Assertions 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 Assertions; 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.assertion.ui;
024
025import java.awt.BorderLayout;
026import java.awt.Color;
027import java.awt.Component;
028import java.awt.Dimension;
029import java.awt.event.ActionEvent;
030
031import javax.swing.BorderFactory;
032import javax.swing.Box;
033import javax.swing.BoxLayout;
034import javax.swing.JButton;
035import javax.swing.JLabel;
036import javax.swing.JPanel;
037import javax.swing.JTextArea;
038import javax.swing.JTextField;
039import javax.swing.border.TitledBorder;
040
041import csheets.core.Cell;
042import csheets.ext.assertion.AssertableCell;
043import csheets.ext.assertion.AssertableCellListener;
044import csheets.ext.assertion.Assertion;
045import csheets.ext.assertion.AssertionExtension;
046import csheets.ui.ctrl.FocusOwnerAction;
047import csheets.ui.ctrl.SelectionEvent;
048import csheets.ui.ctrl.SelectionListener;
049import csheets.ui.ctrl.UIController;
050
051/**
052 * A panel for adding or editing an assertion for a cell
053 * @author Bjorn Lanneskog
054 * @author Einar Pehrson
055 */
056@SuppressWarnings("serial")
057public class AssertionPanel extends JPanel implements SelectionListener,
058                AssertableCellListener {
059
060        /** The assertion controller */
061        private AssertionController controller;
062
063        /** The assertable cell currently being displayed in the panel */
064        private AssertableCell cell;
065
066        /** The label on which the status of the assertion is displayed */
067        private JLabel statusLabel = new JLabel();
068
069        /** The text field in which the assertion of the cell is displayed.*/
070        private JTextField usField = new JTextField();
071
072        /**A label showing the system-generated assertion*/
073        private JLabel sgLabel = new JLabel();
074
075        /**
076         * Creates a new assertion panel.
077         * @param uiController the user interface controller
078         */
079        public AssertionPanel(UIController uiController) {
080                // Configures panel
081                super(new BorderLayout());
082                setName(AssertionExtension.NAME);
083
084                // Creates controller
085                controller = new AssertionController(uiController);
086                uiController.addSelectionListener(this);
087
088                // Creates system-generated assertion components
089                JPanel sgPanel = new JPanel();
090                sgPanel.setPreferredSize(new Dimension(130, 60));
091                sgPanel.add(sgLabel);
092
093                // Creates user-specified assertion components
094                ApplyAction applyAction = new ApplyAction();
095                JButton applyButton = new JButton(applyAction);
096                usField.setPreferredSize(new Dimension(120, 24));
097                usField.setMaximumSize(new Dimension(1000, 24));
098                usField.addActionListener(applyAction);
099                usField.setAlignmentX(Component.CENTER_ALIGNMENT);
100                applyButton.setAlignmentX(Component.CENTER_ALIGNMENT);
101                statusLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
102
103                // Lays out user-specified assertion components
104                JPanel usPanel = new JPanel();
105                usPanel.setLayout(new BoxLayout(usPanel, BoxLayout.PAGE_AXIS));
106                usPanel.setPreferredSize(new Dimension(130, 120));
107                usPanel.add(usField);
108                usPanel.add(Box.createRigidArea(new Dimension(120, 4)));
109                usPanel.add(applyButton);
110                usPanel.add(Box.createRigidArea(new Dimension(120, 12)));
111                usPanel.add(statusLabel);
112                usPanel.add(Box.createRigidArea(new Dimension(120, 12)));
113
114                // Creates assertion syntax components
115                JPanel syntaxPanel = new JPanel();
116                JTextArea syntaxArea = new JTextArea("");
117                        // "Operators: > < >= <=\nOR\nEXCEPT\nINTEGER"
118                syntaxArea.setPreferredSize(new Dimension(120, 100));
119                syntaxArea.setLineWrap(true);
120                syntaxArea.setEditable(false);
121                syntaxArea.setBackground(getBackground());
122                syntaxPanel.add(syntaxArea);
123
124                // Adds borders
125                TitledBorder border = BorderFactory.createTitledBorder("System-generated");
126                border.setTitleJustification(TitledBorder.CENTER);
127                sgPanel.setBorder(border);
128                border = BorderFactory.createTitledBorder("User-specified");
129                border.setTitleJustification(TitledBorder.CENTER);
130                usPanel.setBorder(border);
131                border = BorderFactory.createTitledBorder("Syntax");
132                border.setTitleJustification(TitledBorder.CENTER);
133                // syntaxPanel.setBorder(border);
134
135                // Adds panels
136                JPanel northPanel = new JPanel(new BorderLayout());
137                northPanel.add(sgPanel, BorderLayout.NORTH);
138                northPanel.add(usPanel, BorderLayout.SOUTH);
139                add(northPanel, BorderLayout.NORTH);
140                add(syntaxPanel, BorderLayout.CENTER);
141        }
142
143        /**
144         * Updates the assertion field and status label when the active cell of
145         * the application is changed.
146         * @param event the selection event that was fired
147         */
148        public void selectionChanged(SelectionEvent event) {
149                Cell cell = event.getCell();
150                if (cell != null) {
151                        AssertableCell activeCell
152                                = (AssertableCell)cell.getExtension(AssertionExtension.NAME);
153                        activeCell.addAssertableCellListener(this);
154                        assertionsChanged(activeCell);
155                } else {
156                        usField.setText("");
157                        statusLabel.setText("");
158                        sgLabel.setText("");
159                }
160
161                // Stops listening to previous active cell
162                if (event.getPreviousCell() != null)
163                        ((AssertableCell)event.getPreviousCell().getExtension(AssertionExtension.NAME))
164                                .removeAssertableCellListener(this);
165        }
166
167        /**
168         * Updates the assertion field and status label when the assertion of the
169         * active cell is changed.
170         * @param cell the cell whose assertion changed
171         */
172        public void assertionsChanged(AssertableCell cell) {
173                // Stores the cell for use when applying assertion
174                this.cell = cell;
175
176                // Initializes colors and text
177                Color usColor = Color.BLACK;
178                Color sgColor = Color.BLACK;
179                String usStatus = "";
180
181                // Updates system-generated assertion label
182                if (cell.isSGAsserted()) {
183                        sgLabel.setText(cell.getSGAssertion().toString());
184                        sgColor = AssertionController.getAssertionResultColor(cell.assertSG());
185                } else
186                        sgLabel.setText("No assertion");
187
188                // Updates the text field and validates the assertion, if any
189                if (cell.isUSAsserted()) {
190                        usField.setText(cell.getUSAssertion().toString());
191                        Assertion.Result result = cell.assertUS();
192        
193                        // Determines the status message
194                        usColor = AssertionController.getAssertionResultColor(result);
195                        switch (result) {
196                                case OK:
197                                        usStatus += "Valid";
198                                        break;
199                                case NAN:
200                                        usStatus += "Non-numeric value";
201                                        break;
202                                case FAILED:
203                                        usStatus += "Illegal value";
204                                        break;
205                                case NO_DATA:
206                                        usStatus += "No value";
207                                        break;
208                        }
209
210                        // Compares assertions
211                        Assertion.ComparisonResult compResult = cell.assertAssertions();
212                        switch (compResult) {
213                                case NON_EQUAL:
214                                        usColor =  new Color(0.7f, 0.0f, 0f);
215                                        usStatus = "Conflicting assertions";
216                                         break;
217                                case ILLEGAL_INTERVAL:
218                                        sgLabel.setText(compResult.getErrorMsg());
219                                        break;
220                        }
221                } else {
222                        usField.setText("");
223                        usStatus = "No assertion";
224                }
225
226                // Updates the label
227                sgLabel.setForeground(sgColor);
228                statusLabel.setForeground(usColor);
229                statusLabel.setText(usStatus);
230        }
231
232        /**
233         * An action used to apply changes made in the assertion field.
234         */
235        protected class ApplyAction extends FocusOwnerAction {
236
237                /**
238                 * Creates a new apply action.
239                 */
240                public ApplyAction() {}
241
242                protected String getName() {
243                        return "Apply";
244                }
245
246                public void actionPerformed(ActionEvent e) {
247                        if (cell != null)
248                                if (controller.setAssertion(cell, usField.getText().trim()))
249                                        focusOwner.repaint();
250                }
251        }
252}