001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2019 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 * @noinspection MagicNumber 052 */ 053public class MainFrame extends JFrame { 054 055 private static final long serialVersionUID = 7970053543351871890L; 056 057 /** Checkstyle frame model. */ 058 private final transient MainFrameModel model = new MainFrameModel(); 059 /** Reload action. */ 060 private final ReloadAction reloadAction = new ReloadAction(); 061 /** Code text area. */ 062 private JTextArea textArea; 063 /** Tree table. */ 064 private TreeTable treeTable; 065 066 /** Create a new MainFrame. */ 067 public MainFrame() { 068 createContent(); 069 } 070 071 /** Create content of this MainFrame. */ 072 private void createContent() { 073 setLayout(new BorderLayout()); 074 075 textArea = new JTextArea(20, 15); 076 textArea.setEditable(false); 077 final JScrollPane textAreaScrollPane = new JScrollPane(textArea); 078 079 treeTable = new TreeTable(model.getParseTreeTableModel()); 080 treeTable.setEditor(textArea); 081 treeTable.setLinePositionMap(model.getLinesToPosition()); 082 final JScrollPane treeTableScrollPane = new JScrollPane(treeTable); 083 084 final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, treeTableScrollPane, 085 textAreaScrollPane); 086 add(splitPane, BorderLayout.CENTER); 087 splitPane.setResizeWeight(0.7); 088 089 add(createButtonsPanel(), BorderLayout.PAGE_END); 090 091 pack(); 092 } 093 094 /** 095 * Create buttons panel. 096 * @return buttons panel. 097 */ 098 private JPanel createButtonsPanel() { 099 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}