001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2020 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 * 097 * @return buttons panel. 098 */ 099 private JPanel createButtonsPanel() { 100 final JButton openFileButton = new JButton(new FileSelectionAction()); 101 openFileButton.setMnemonic(KeyEvent.VK_S); 102 openFileButton.setText("Open File"); 103 104 reloadAction.setEnabled(false); 105 final JButton reloadFileButton = new JButton(reloadAction); 106 reloadFileButton.setMnemonic(KeyEvent.VK_R); 107 reloadFileButton.setText("Reload File"); 108 109 final JComboBox<ParseMode> modesCombobox = new JComboBox<>(ParseMode.values()); 110 modesCombobox.setSelectedIndex(0); 111 modesCombobox.addActionListener(event -> { 112 model.setParseMode((ParseMode) modesCombobox.getSelectedItem()); 113 reloadAction.actionPerformed(null); 114 }); 115 116 final JLabel modesLabel = new JLabel("Modes:", SwingConstants.RIGHT); 117 final int leftIndentation = 10; 118 modesLabel.setBorder(BorderFactory.createEmptyBorder(0, leftIndentation, 0, 0)); 119 120 final JPanel buttonPanel = new JPanel(); 121 buttonPanel.setLayout(new GridLayout(1, 2)); 122 buttonPanel.add(openFileButton); 123 buttonPanel.add(reloadFileButton); 124 125 final JPanel modesPanel = new JPanel(); 126 modesPanel.add(modesLabel); 127 modesPanel.add(modesCombobox); 128 129 final JPanel mainPanel = new JPanel(); 130 mainPanel.setLayout(new BorderLayout()); 131 mainPanel.add(buttonPanel); 132 mainPanel.add(modesPanel, BorderLayout.LINE_END); 133 134 return mainPanel; 135 } 136 137 /** 138 * Open file and load it. 139 * 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}