1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.gui;
21  
22  import java.awt.BorderLayout;
23  import java.awt.GridLayout;
24  import java.awt.event.ActionEvent;
25  import java.awt.event.KeyEvent;
26  import java.io.File;
27  
28  import javax.swing.AbstractAction;
29  import javax.swing.BorderFactory;
30  import javax.swing.JButton;
31  import javax.swing.JComboBox;
32  import javax.swing.JFileChooser;
33  import javax.swing.JFrame;
34  import javax.swing.JLabel;
35  import javax.swing.JOptionPane;
36  import javax.swing.JPanel;
37  import javax.swing.JScrollPane;
38  import javax.swing.JSplitPane;
39  import javax.swing.JTextArea;
40  import javax.swing.SwingConstants;
41  import javax.swing.filechooser.FileFilter;
42  
43  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
44  import com.puppycrawl.tools.checkstyle.gui.MainFrameModel.ParseMode;
45  
46  /**
47   * Displays information about a parse tree.
48   * The user can change the file that is parsed and displayed
49   * using a JFileChooser.
50   *
51   * @noinspection MagicNumber
52   */
53  public class MainFrame extends JFrame {
54  
55      private static final long serialVersionUID = 7970053543351871890L;
56  
57      /** Checkstyle frame model. */
58      private final transient MainFrameModel model = new MainFrameModel();
59      /** Reload action. */
60      private final ReloadAction reloadAction = new ReloadAction();
61      /** Code text area. */
62      private JTextArea textArea;
63      /** Tree table. */
64      private TreeTable treeTable;
65  
66      /** Create a new MainFrame. */
67      public MainFrame() {
68          createContent();
69      }
70  
71      /** Create content of this MainFrame. */
72      private void createContent() {
73          setLayout(new BorderLayout());
74  
75          textArea = new JTextArea(20, 15);
76          textArea.setEditable(false);
77          final JScrollPane textAreaScrollPane = new JScrollPane(textArea);
78  
79          treeTable = new TreeTable(model.getParseTreeTableModel());
80          treeTable.setEditor(textArea);
81          treeTable.setLinePositionMap(model.getLinesToPosition());
82          final JScrollPane treeTableScrollPane = new JScrollPane(treeTable);
83  
84          final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, treeTableScrollPane,
85              textAreaScrollPane);
86          add(splitPane, BorderLayout.CENTER);
87          splitPane.setResizeWeight(0.7);
88  
89          add(createButtonsPanel(), BorderLayout.PAGE_END);
90  
91          pack();
92      }
93  
94      /**
95       * Create buttons panel.
96       * @return buttons panel.
97       */
98      private JPanel createButtonsPanel() {
99          final JButton openFileButton = new JButton(new FileSelectionAction());
100         openFileButton.setMnemonic(KeyEvent.VK_S);
101         openFileButton.setText("Open File");
102 
103         reloadAction.setEnabled(false);
104         final JButton reloadFileButton = new JButton(reloadAction);
105         reloadFileButton.setMnemonic(KeyEvent.VK_R);
106         reloadFileButton.setText("Reload File");
107 
108         final JComboBox<ParseMode> modesCombobox = new JComboBox<>(ParseMode.values());
109         modesCombobox.setSelectedIndex(0);
110         modesCombobox.addActionListener(event -> {
111             model.setParseMode((ParseMode) modesCombobox.getSelectedItem());
112             reloadAction.actionPerformed(null);
113         });
114 
115         final JLabel modesLabel = new JLabel("Modes:", SwingConstants.RIGHT);
116         final int leftIndentation = 10;
117         modesLabel.setBorder(BorderFactory.createEmptyBorder(0, leftIndentation, 0, 0));
118 
119         final JPanel buttonPanel = new JPanel();
120         buttonPanel.setLayout(new GridLayout(1, 2));
121         buttonPanel.add(openFileButton);
122         buttonPanel.add(reloadFileButton);
123 
124         final JPanel modesPanel = new JPanel();
125         modesPanel.add(modesLabel);
126         modesPanel.add(modesCombobox);
127 
128         final JPanel mainPanel = new JPanel();
129         mainPanel.setLayout(new BorderLayout());
130         mainPanel.add(buttonPanel);
131         mainPanel.add(modesPanel, BorderLayout.LINE_END);
132 
133         return mainPanel;
134     }
135 
136     /**
137      * Open file and load it.
138      * @param sourceFile the file to open.
139      */
140     public void openFile(File sourceFile) {
141         try {
142             model.openFile(sourceFile);
143             setTitle(model.getTitle());
144             reloadAction.setEnabled(model.isReloadActionEnabled());
145             textArea.setText(model.getText());
146             treeTable.setLinePositionMap(model.getLinesToPosition());
147         }
148         catch (final CheckstyleException ex) {
149             JOptionPane.showMessageDialog(this, ex.getMessage());
150         }
151     }
152 
153     /**
154      * Handler for file selection action events.
155      */
156     private class FileSelectionAction extends AbstractAction {
157 
158         private static final long serialVersionUID = 1762396148873280589L;
159 
160         @Override
161         public void actionPerformed(ActionEvent event) {
162             final JFileChooser fileChooser = new JFileChooser(model.getLastDirectory());
163             final FileFilter filter = new JavaFileFilter();
164             fileChooser.setFileFilter(filter);
165 
166             final int returnCode = fileChooser.showOpenDialog(MainFrame.this);
167             if (returnCode == JFileChooser.APPROVE_OPTION) {
168                 final File file = fileChooser.getSelectedFile();
169                 openFile(file);
170             }
171         }
172 
173     }
174 
175     /**
176      * Handler for reload action events.
177      */
178     private class ReloadAction extends AbstractAction {
179 
180         private static final long serialVersionUID = -890320994114628011L;
181 
182         @Override
183         public void actionPerformed(ActionEvent event) {
184             openFile(model.getCurrentFile());
185         }
186 
187     }
188 
189     /**
190      * Filter for Java files.
191      */
192     private static class JavaFileFilter extends FileFilter {
193 
194         @Override
195         public boolean accept(File file) {
196             return MainFrameModel.shouldAcceptFile(file);
197         }
198 
199         @Override
200         public String getDescription() {
201             return "Java Source File";
202         }
203 
204     }
205 
206 }