001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2017 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 */ 054public class MainFrame extends JFrame { 055 056 private static final long serialVersionUID = 7970053543351871890L; 057 058 /** Checkstyle frame model. */ 059 private final transient MainFrameModel model = new MainFrameModel(); 060 /** Reload action. */ 061 private final ReloadAction reloadAction = new ReloadAction(); 062 /** Code text area. */ 063 private JTextArea textArea; 064 /** Tree table. */ 065 private TreeTable treeTable; 066 067 /** Create a new MainFrame. */ 068 public MainFrame() { 069 createContent(); 070 } 071 072 /** Create content of this MainFrame. */ 073 private void createContent() { 074 setLayout(new BorderLayout()); 075 076 textArea = new JTextArea(20, 15); 077 textArea.setEditable(false); 078 final JScrollPane textAreaScrollPane = new JScrollPane(textArea); 079 080 treeTable = new TreeTable(model.getParseTreeTableModel()); 081 treeTable.setEditor(textArea); 082 treeTable.setLinePositionMap(model.getLinesToPosition()); 083 final JScrollPane treeTableScrollPane = new JScrollPane(treeTable); 084 085 final JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, treeTableScrollPane, 086 textAreaScrollPane); 087 add(splitPane, BorderLayout.CENTER); 088 splitPane.setResizeWeight(0.7); 089 090 add(createButtonsPanel(), BorderLayout.PAGE_END); 091 092 pack(); 093 } 094 095 /** 096 * Create buttons panel. 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(e -> { 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 * @param sourceFile the file to open. 140 */ 141 public void openFile(File sourceFile) { 142 try { 143 model.openFile(sourceFile); 144 setTitle(model.getTitle()); 145 reloadAction.setEnabled(model.isReloadActionEnabled()); 146 textArea.setText(model.getText()); 147 treeTable.setLinePositionMap(model.getLinesToPosition()); 148 } 149 catch (final CheckstyleException ex) { 150 JOptionPane.showMessageDialog(this, ex.getMessage()); 151 } 152 } 153 154 /** 155 * Handler for file selection action events. 156 */ 157 private class FileSelectionAction extends AbstractAction { 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 * Handler for reload action events. 176 */ 177 private class ReloadAction extends AbstractAction { 178 private static final long serialVersionUID = -890320994114628011L; 179 180 @Override 181 public void actionPerformed(ActionEvent event) { 182 openFile(model.getCurrentFile()); 183 } 184 } 185 186 /** 187 * Filter for Java files. 188 */ 189 private static class JavaFileFilter extends FileFilter { 190 @Override 191 public boolean accept(File file) { 192 return MainFrameModel.shouldAcceptFile(file); 193 } 194 195 @Override 196 public String getDescription() { 197 return "Java Source File"; 198 } 199 } 200}