001    /*
002     * Copyright (c) 2005 Peter Palotas, Fredrik Johansson, Einar Pehrson,
003     * Sebastian Kekkonen, Lars Magnus Lång, 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     */
023    package csheets.ext.assertion.ui;
024    
025    import java.awt.BorderLayout;
026    import java.awt.Color;
027    import java.awt.Component;
028    import java.awt.Dimension;
029    import java.awt.event.ActionEvent;
030    
031    import javax.swing.BorderFactory;
032    import javax.swing.Box;
033    import javax.swing.BoxLayout;
034    import javax.swing.JButton;
035    import javax.swing.JLabel;
036    import javax.swing.JPanel;
037    import javax.swing.JTextArea;
038    import javax.swing.JTextField;
039    import javax.swing.border.TitledBorder;
040    
041    import csheets.core.Cell;
042    import csheets.ext.assertion.AssertableCell;
043    import csheets.ext.assertion.AssertableCellListener;
044    import csheets.ext.assertion.Assertion;
045    import csheets.ext.assertion.AssertionExtension;
046    import csheets.ui.ctrl.FocusOwnerAction;
047    import csheets.ui.ctrl.SelectionEvent;
048    import csheets.ui.ctrl.SelectionListener;
049    import csheets.ui.ctrl.UIController;
050    
051    /**
052     * A panel for adding or editing an assertion for a cell
053     * @author Björn Lanneskog
054     * @author Einar Pehrson
055     */
056    @SuppressWarnings("serial")
057    public 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    }