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.util.logging.Level;
32import java.util.logging.Logger;
33import org.antlr.gunit.swingui.runner.gUnitAdapter;
34import java.awt.*;
35import java.io.IOException;
36import org.antlr.gunit.swingui.model.*;
37import org.antlr.gunit.swingui.ImageFactory;
38import java.awt.event.*;
39import java.io.File;
40import javax.swing.*;
41import javax.swing.event.*;
42import javax.swing.filechooser.FileFilter;
43
44/**
45 *
46 * @author scai
47 */
48public class WorkSpaceController implements IController{
49
50    /* MODEL */
51    private TestSuite currentTestSuite;
52    private String testSuiteFileName = null;    // path + file
53
54    /* VIEW */
55    private final WorkSpaceView view = new WorkSpaceView();
56
57    /* SUB-CONTROL */
58    private final RunnerController runner = new RunnerController();
59
60    public WorkSpaceController() {
61        view.resultPane = (JPanel) runner.getView();
62        view.initComponents();
63        this.initEventHandlers();
64        this.initToolbar();
65    }
66
67    public void show() {
68        this.view.setTitle("gUnitEditor");
69        this.view.setVisible(true);
70        this.view.pack();
71    }
72
73    public Component getEmbeddedView() {
74        return view.paneEditor.getView();
75    }
76
77    private void initEventHandlers() {
78        this.view.tabEditors.addChangeListener(new TabChangeListener());
79        this.view.listRules.setListSelectionListener(new RuleListSelectionListener());
80        this.view.paneEditor.onTestCaseNumberChange = new ActionListener() {
81            public void actionPerformed(ActionEvent e) {
82                view.listRules.getView().updateUI();
83            }
84        };
85    }
86
87    private void OnCreateTest() {
88        JFileChooser jfc = new JFileChooser();
89        jfc.setDialogTitle("Create test suite from grammar");
90        jfc.setDialogType(JFileChooser.OPEN_DIALOG);
91        jfc.setFileFilter(new FileFilter() {
92            @Override
93            public boolean accept(File f) {
94                return f.isDirectory() || f.getName().toLowerCase().endsWith(TestSuiteFactory.GRAMMAR_EXT);
95            }
96
97            @Override
98            public String getDescription() {
99                return "ANTLR grammar file (*.g)";
100            }
101        });
102        if( jfc.showOpenDialog(view) != JFileChooser.APPROVE_OPTION ) return;
103
104        view.paneStatus.setProgressIndetermined(true);
105        final File grammarFile = jfc.getSelectedFile();
106
107        currentTestSuite = TestSuiteFactory.createTestSuite(grammarFile);
108
109        view.listRules.initialize(currentTestSuite);
110        view.tabEditors.setSelectedIndex(0);
111        view.paneStatus.setText("Grammar: " + currentTestSuite.getGrammarName());
112        view.paneStatus.setProgressIndetermined(false);
113
114        testSuiteFileName = null;
115    }
116
117    private void OnSaveTest() {
118        TestSuiteFactory.saveTestSuite(currentTestSuite);
119        JOptionPane.showMessageDialog(view, "Testsuite saved to:\n" + currentTestSuite.getTestSuiteFile().getAbsolutePath());
120    }
121
122    private void OnOpenTest()  {
123
124        JFileChooser jfc = new JFileChooser();
125        jfc.setDialogTitle("Open existing gUnit test suite");
126        jfc.setDialogType(JFileChooser.OPEN_DIALOG);
127        jfc.setFileFilter(new FileFilter() {
128
129            @Override
130            public boolean accept(File f) {
131                return f.isDirectory() || f.getName().toLowerCase().endsWith(TestSuiteFactory.TEST_SUITE_EXT);
132            }
133
134            @Override
135            public String getDescription() {
136                return "ANTLR unit test file (*.gunit)";
137            }
138        });
139        if( jfc.showOpenDialog(view) != JFileChooser.APPROVE_OPTION ) return;
140
141        final File testSuiteFile = jfc.getSelectedFile();
142        try {
143            testSuiteFileName = testSuiteFile.getCanonicalPath();
144        } catch (IOException e) {
145            throw new RuntimeException(e);
146        }
147
148        view.paneStatus.setProgressIndetermined(true);
149
150        currentTestSuite = TestSuiteFactory.loadTestSuite(testSuiteFile);
151        view.listRules.initialize(currentTestSuite);
152        view.paneStatus.setText(currentTestSuite.getGrammarName());
153        view.tabEditors.setSelectedIndex(0);
154
155        view.paneStatus.setProgressIndetermined(false);
156    }
157
158    private void OnSelectRule(Rule rule) {
159        if(rule == null) throw new IllegalArgumentException("Null");
160        this.view.paneEditor.OnLoadRule(rule);
161        this.view.paneStatus.setRule(rule.getName());
162
163        // run result
164        this.runner.OnShowRuleResult(rule);
165    }
166
167    private void OnSelectTextPane() {
168        Thread worker = new Thread () {
169            @Override
170            public void run() {
171                view.paneStatus.setProgressIndetermined(true);
172                view.txtEditor.setText(
173                    TestSuiteFactory.getScript(currentTestSuite));
174                view.paneStatus.setProgressIndetermined(false);
175            }
176        };
177
178        worker.start();
179    }
180
181    private void OnRunTest() {
182        // save before run
183        TestSuiteFactory.saveTestSuite(currentTestSuite);
184
185        // run
186        try {
187            final gUnitAdapter adapter = new gUnitAdapter(currentTestSuite);
188            if(currentTestSuite == null) return;
189            adapter.run();
190
191            runner.OnShowSuiteResult(currentTestSuite);
192            view.tabEditors.addTab("Test Result", ImageFactory.getSingleton().FILE16, runner.getView());
193            view.tabEditors.setSelectedComponent(runner.getView());
194        } catch (Exception ex) {
195            JOptionPane.showMessageDialog(view, "Fail to run test:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
196        }
197
198    }
199
200    private void initToolbar() {
201        view.toolbar.add(new JButton(new CreateAction()));
202        view.toolbar.add(new JButton(new OpenAction()));
203        view.toolbar.add(new JButton(new SaveAction()));
204        view.toolbar.add(new JButton(new RunAction()));
205
206    }
207
208    public Object getModel() {
209        throw new UnsupportedOperationException("Not supported yet.");
210    }
211
212    public Component getView() {
213        return view;
214    }
215
216
217    /** Event handler for rule list selection. */
218    private class RuleListSelectionListener implements ListSelectionListener {
219        public void valueChanged(ListSelectionEvent event) {
220            if(event.getValueIsAdjusting()) return;
221            final JList list = (JList) event.getSource();
222            final Rule rule = (Rule) list.getSelectedValue();
223            if(rule != null) OnSelectRule(rule);
224        }
225    }
226
227
228    /** Event handler for switching between editor view and script view. */
229    public class TabChangeListener implements ChangeListener {
230        public void stateChanged(ChangeEvent evt) {
231            if(view.tabEditors.getSelectedIndex() == 1) {
232                OnSelectTextPane();
233            }
234        }
235
236    }
237
238
239    /** Create test suite action. */
240    private class CreateAction extends AbstractAction {
241        public CreateAction() {
242            super("Create", ImageFactory.getSingleton().ADDFILE);
243            putValue(SHORT_DESCRIPTION, "Create a test suite from an ANTLR grammar");
244        }
245        public void actionPerformed(ActionEvent e) {
246            OnCreateTest();
247        }
248    }
249
250
251    /** Save test suite action. */
252    private class SaveAction extends AbstractAction {
253        public SaveAction() {
254            super("Save", ImageFactory.getSingleton().SAVE);
255            putValue(SHORT_DESCRIPTION, "Save the test suite");
256        }
257        public void actionPerformed(ActionEvent e) {
258            OnSaveTest();
259        }
260    }
261
262
263    /** Open test suite action. */
264    private class OpenAction extends AbstractAction {
265        public OpenAction() {
266            super("Open", ImageFactory.getSingleton().OPEN);
267            putValue(SHORT_DESCRIPTION, "Open an existing test suite");
268            putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(
269                    KeyEvent.VK_O, InputEvent.CTRL_MASK));
270        }
271        public void actionPerformed(ActionEvent e) {
272            OnOpenTest();
273        }
274    }
275
276    /** Run test suite action. */
277    private class RunAction extends AbstractAction {
278        public RunAction() {
279            super("Run", ImageFactory.getSingleton().NEXT);
280            putValue(SHORT_DESCRIPTION, "Run the current test suite");
281            putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(
282                    KeyEvent.VK_R, InputEvent.CTRL_MASK));
283        }
284        public void actionPerformed(ActionEvent e) {
285            OnRunTest();
286        }
287    }
288}
289