001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2018 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.gui; 021 022import java.awt.BorderLayout; 023import java.awt.GridLayout; 024import java.awt.event.ActionEvent; 025import java.awt.event.KeyEvent; 026import java.io.File; 027 028import javax.swing.AbstractAction; 029import javax.swing.BorderFactory; 030import javax.swing.JButton; 031import javax.swing.JComboBox; 032import javax.swing.JFileChooser; 033import javax.swing.JFrame; 034import javax.swing.JLabel; 035import javax.swing.JOptionPane; 036import javax.swing.JPanel; 037import javax.swing.JScrollPane; 038import javax.swing.JSplitPane; 039import javax.swing.JTextArea; 040import javax.swing.SwingConstants; 041import javax.swing.filechooser.FileFilter; 042 043import com.puppycrawl.tools.checkstyle.api.CheckstyleException; 044import com.puppycrawl.tools.checkstyle.gui.MainFrameModel.ParseMode; 045 046/** 047 * Displays information about a parse tree. 048 * The user can change the file that is parsed and displayed 049 * using a JFileChooser. 050 * 051 * @author Lars Kühne 052 * @author Vladislav Lisetskiy 053 * @noinspection MagicNumber 054 */ 055public class MainFrame extends JFrame { 056 057 private static final long serialVersionUID = 7970053543351871890L; 058 059 /** Checkstyle frame model. */ 060 private final transient MainFrameModel model = new MainFrameModel(); 061 /** Reload action. */ 062 private final ReloadAction reloadAction = new ReloadAction(); 063 /** Code text area. */ 064 private JTextArea textArea; 065 /** Tree table. */ 066 private TreeTable treeTable; 067 068 /** Create a new MainFrame. */ 069 public MainFrame() { 070 createContent(); 071 } 072 073 /** Create content of this MainFrame. */ 074 private void createContent() { 075 setLayout(new BorderLayout()); 076 077 textArea = new JTextArea(20, 15); 078 textArea.setEditable(false); 079 final JScrollPane textAreaScrollPane = new JScrollPane(textArea); 080 081 treeTable = new TreeTable(model.getParseTreeTableModel()); 082 treeTable.setEditor(textArea); 083 treeTable.setLinePositionMap(model.getLinesToPosition()); 084 final JScrollPane treeTableScrollPane = new JScrollPane(treeTable); 085 086 final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, treeTableScrollPane, 087 textAreaScrollPane); 088 add(splitPane, BorderLayout.CENTER); 089 splitPane.setResizeWeight(0.7); 090 091 add(createButtonsPanel(), BorderLayout.PAGE_END); 092 093 pack(); 094 } 095 096 /** 097 * Create buttons panel. 098 * @return buttons panel. 099 */ 100 private JPanel createButtonsPanel() { 101 final JButton openFileButton = new JButton(new FileSelectionAction()); 102 openFileButton.setMnemonic(KeyEvent.VK_S); 103 openFileButton.setText("Open File"); 104 105 reloadAction.setEnabled(false); 106 final JButton reloadFileButton = new JButton(reloadAction); 107 reloadFileButton.setMnemonic(KeyEvent.VK_R); 108 reloadFileButton.setText("Reload File"); 109 110 final JComboBox<ParseMode> modesCombobox = new JComboBox<>(ParseMode.values()); 111 modesCombobox.setSelectedIndex(0); 112 modesCombobox.addActionListener(e -> { 113 model.setParseMode((ParseMode) modesCombobox.getSelectedItem()); 114 reloadAction.actionPerformed(null); 115 }); 116 117 final JLabel modesLabel = new JLabel("Modes:", SwingConstants.RIGHT); 118 final int leftIndentation = 10; 119 modesLabel.setBorder(BorderFactory.createEmptyBorder(0, leftIndentation, 0, 0)); 120 121 final JPanel buttonPanel = new JPanel(); 122 buttonPanel.setLayout(new GridLayout(1, 2)); 123 buttonPanel.add(openFileButton); 124 buttonPanel.add(reloadFileButton); 125 126 final JPanel modesPanel = new JPanel(); 127 modesPanel.add(modesLabel); 128 modesPanel.add(modesCombobox); 129 130 final JPanel mainPanel = new JPanel(); 131 mainPanel.setLayout(new BorderLayout()); 132 mainPanel.add(buttonPanel); 133 mainPanel.add(modesPanel, BorderLayout.LINE_END); 134 135 return mainPanel; 136 } 137 138 /** 139 * Open file and load it. 140 * @param sourceFile the file to open. 141 */ 142 public void openFile(File sourceFile) { 143 try { 144 model.openFile(sourceFile); 145 setTitle(model.getTitle()); 146 reloadAction.setEnabled(model.isReloadActionEnabled()); 147 textArea.setText(model.getText()); 148 treeTable.setLinePositionMap(model.getLinesToPosition()); 149 } 150 catch (final CheckstyleException ex) { 151 JOptionPane.showMessageDialog(this, ex.getMessage()); 152 } 153 } 154 155 /** 156 * Handler for file selection action events. 157 */ 158 private class FileSelectionAction extends AbstractAction { 159 160 private static final long serialVersionUID = 1762396148873280589L; 161 162 @Override 163 public void actionPerformed(ActionEvent event) { 164 final JFileChooser fileChooser = new JFileChooser(model.getLastDirectory()); 165 final FileFilter filter = new JavaFileFilter(); 166 fileChooser.setFileFilter(filter); 167 168 final int returnCode = fileChooser.showOpenDialog(MainFrame.this); 169 if (returnCode == JFileChooser.APPROVE_OPTION) { 170 final File file = fileChooser.getSelectedFile(); 171 openFile(file); 172 } 173 } 174 175 } 176 177 /** 178 * Handler for reload action events. 179 */ 180 private class ReloadAction extends AbstractAction { 181 182 private static final long serialVersionUID = -890320994114628011L; 183 184 @Override 185 public void actionPerformed(ActionEvent event) { 186 openFile(model.getCurrentFile()); 187 } 188 189 } 190 191 /** 192 * Filter for Java files. 193 */ 194 private static class JavaFileFilter extends FileFilter { 195 196 @Override 197 public boolean accept(File file) { 198 return MainFrameModel.shouldAcceptFile(file); 199 } 200 201 @Override 202 public String getDescription() { 203 return "Java Source File"; 204 } 205 206 } 207 208}