1/*
2 [The "BSD licence"]
3 Copyright (c) 2009 Shaoting Cai
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9 1. Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12    notice, this list of conditions and the following disclaimer in the
13    documentation and/or other materials provided with the distribution.
14 3. The name of the author may not be used to endorse or promote products
15    derived from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29package org.antlr.gunit.swingui;
30
31import java.awt.BorderLayout;
32import java.awt.Color;
33import java.awt.Component;
34import java.awt.Dimension;
35import javax.swing.BorderFactory;
36import javax.swing.BoxLayout;
37import javax.swing.JLabel;
38import javax.swing.JLabel;
39import javax.swing.JPanel;
40import javax.swing.JScrollPane;
41import javax.swing.JTextArea;
42import javax.swing.JTree;
43import javax.swing.event.TreeModelListener;
44import javax.swing.tree.DefaultMutableTreeNode;
45import javax.swing.tree.DefaultTreeModel;
46import javax.swing.tree.TreeCellRenderer;
47import javax.swing.tree.TreeModel;
48import javax.swing.tree.TreePath;
49import org.antlr.gunit.swingui.ImageFactory;
50import org.antlr.gunit.swingui.model.*;
51
52/**
53 *
54 * @author scai
55 */
56public class RunnerController implements IController {
57
58    /* MODEL */
59    //private TestSuite testSuite;
60
61    /* VIEW */
62    private RunnerView view = new RunnerView();
63    public class RunnerView extends JPanel {
64
65        private JTextArea textArea = new JTextArea();
66
67        private JTree tree = new JTree();
68
69        private JScrollPane scroll = new JScrollPane(tree,
70                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
71                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
72
73        public void initComponents() {
74            //textArea.setOpaque(false);
75            tree.setOpaque(false);
76            scroll.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
77            scroll.setOpaque(false);
78            this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
79            this.add(scroll);
80            this.setBorder(BorderFactory.createEmptyBorder());
81            this.setOpaque(false);
82        }
83
84    };
85
86    public RunnerController() {
87    }
88
89    public Object getModel() {
90        return null;
91    }
92
93    public Component getView() {
94        return view;
95    }
96
97    public void update() {
98        view.initComponents();
99    }
100
101    public void OnShowSuiteResult(TestSuite suite) {
102        update();
103        view.tree.setModel(new RunnerTreeModel(suite));
104        view.tree.setCellRenderer(new RunnerTreeRenderer());
105    }
106
107    public void OnShowRuleResult(Rule rule) {
108        update();
109
110
111
112        /*
113        StringBuffer result = new StringBuffer();
114
115        result.append("Testing result for rule: " + rule.getName());
116        result.append("\n--------------------\n\n");
117
118        for(TestCase testCase: rule.getTestCases()){
119            result.append(testCase.isPass() ? "PASS" : "FAIL");
120            result.append("\n");
121        }
122        result.append("\n--------------------\n");
123        view.textArea.setText(result.toString());
124                  */
125    }
126
127
128
129    private class TestSuiteTreeNode extends DefaultMutableTreeNode {
130
131        private TestSuite data ;
132
133        public TestSuiteTreeNode(TestSuite suite) {
134            super(suite.getGrammarName());
135            for(int i=0; i<suite.getRuleCount(); ++i) {
136                final Rule rule = suite.getRule(i);
137                if(rule.getNotEmpty()) this.add(new TestGroupTreeNode(rule));
138            }
139            data = suite;
140        }
141
142        @Override
143        public String toString() {
144            return String.format("%s (%d test groups)",
145                    data.getGrammarName(),
146                    this.getChildCount());
147        }
148
149    } ;
150
151    private class TestGroupTreeNode extends DefaultMutableTreeNode {
152
153        private Rule data;
154        private boolean hasFail = false;
155
156        private TestGroupTreeNode(Rule rule) {
157            super(rule.getName());
158            for(TestCase tc: rule.getTestCases()) {
159                this.add(new TestCaseTreeNode(tc));
160            }
161
162            data = rule;
163         }
164
165        @Override
166        public String toString() {
167            int iPass = 0;
168            int iFail = 0;
169            for(TestCase tc: data.getTestCases()) {
170                if(tc.isPass())
171                    ++iPass;
172                else
173                    ++iFail;
174            }
175
176            hasFail = iFail > 0;
177
178            return String.format("%s (pass %d, fail %d)",
179                data.getName(), iPass, iFail);
180        }
181    } ;
182
183    private class TestCaseTreeNode extends DefaultMutableTreeNode {
184
185        private TestCase data;
186
187        private TestCaseTreeNode(TestCase tc) {
188            super(tc.toString());
189            data = tc;
190        }
191    } ;
192
193    private class RunnerTreeModel extends DefaultTreeModel {
194
195        public RunnerTreeModel(TestSuite testSuite) {
196            super(new TestSuiteTreeNode(testSuite));
197        }
198    }
199
200    private class RunnerTreeRenderer implements TreeCellRenderer {
201
202        public Component getTreeCellRendererComponent(JTree tree, Object value,
203                boolean selected, boolean expanded, boolean leaf, int row,
204                boolean hasFocus) {
205
206            JLabel label = new JLabel();
207
208            if(value instanceof TestSuiteTreeNode) {
209
210                label.setText(value.toString());
211                label.setIcon(ImageFactory.getSingleton().TESTSUITE);
212
213            } else if(value instanceof TestGroupTreeNode) {
214
215                TestGroupTreeNode node = (TestGroupTreeNode) value;
216                label.setText(value.toString());
217                label.setIcon( node.hasFail ?
218                    ImageFactory.getSingleton().TESTGROUPX :
219                    ImageFactory.getSingleton().TESTGROUP);
220
221            } else if(value instanceof TestCaseTreeNode) {
222
223                TestCaseTreeNode node = (TestCaseTreeNode) value;
224                label.setIcon( (node.data.isPass())?
225                    ImageFactory.getSingleton().RUN_PASS :
226                    ImageFactory.getSingleton().RUN_FAIL);
227                label.setText(value.toString());
228
229            } else {
230                throw new IllegalArgumentException(
231                    "Invalide tree node type + " + value.getClass().getName());
232            }
233
234            return label;
235
236        }
237
238    }
239
240}
241