commited a patch provided by Andrei Badea <andrei.badea@movzx.net>:

1. Fixes the bug where if you slide the results window and invoke Run PMD the results window is docked in the output mode again.
2. Adds a Window - PMD Output action which opens the results window.
3. Allows jumping to a problem by pressing Enter in the results window.
4. Fixes the threading of OutputWindow.
5. Some minor cleanup in RunPMDAction.


git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4827 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Radim Kubacki
2006-11-22 19:54:55 +00:00
parent e492530a91
commit 1e819951c2
8 changed files with 193 additions and 31 deletions

View File

@ -25,14 +25,15 @@
# DAMAGE.
#
CTL_ShowOutputWindowAction=PMD Output
LBL_Action=Run PM&D
OpenIDE-Module-Name=PMD
OpenIDE-Module-Display-Category=Java
OpenIDE-Module-Short-Description=Runs the PMD source code scanner tool.
OpenIDE-Module-Long-Description=Runs the PMD source code scanner tool. \
Finds various problems in your code and reports them to you easily. \
Hyperlinked Output Window display.
Finds various problems in your code and reports them to you \
in a tabular output window.
LBL_pmd_annotation=PMD Error

View File

@ -49,8 +49,8 @@ class GotoProblemAction extends AbstractAction {
protected boolean action(){
return next?
!OutputWindow.getInstance().selectNextResult():
!OutputWindow.getInstance().selectPreviousResult();
!OutputWindow.findInstance().selectNextResult():
!OutputWindow.findInstance().selectPreviousResult();
}
public void actionPerformed(ActionEvent e) {

View File

@ -28,28 +28,37 @@
package pmd;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.Serializable;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.openide.ErrorManager;
import org.openide.awt.StatusDisplayer;
import org.openide.cookies.LineCookie;
import org.openide.loaders.DataObject;
import org.openide.text.Line;
import org.openide.text.Line.Set;
import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
/**
*
* @author Tomasz Slota <tomslot@gmail.com>
* @author Andrei Badea <andrei.badea@movzx.net>
*/
public class OutputWindow extends TopComponent {
private static final String PREFERRED_ID = "PMDOutputWindow";
private JTable tblResults = new JTable();
private ViolationsTableModel tblMdlResults = new ViolationsTableModel();
private TableSorter tblSorter = null;
@ -57,6 +66,8 @@ public class OutputWindow extends TopComponent {
/** Creates a new instance of OutputWindow */
private OutputWindow() {
setDisplayName("PMD Output");
setLayout(new BorderLayout());
tblSorter = new TableSorter(tblMdlResults);
@ -80,6 +91,25 @@ public class OutputWindow extends TopComponent {
}
});
initActions();
tblResults.getActionMap().put("selectViolation", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
int row = tblResults.getSelectedRow();
if (row != -1) {
selectResultRow(row);
}
}
});
tblResults.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
"selectViolation");
}
public void requestActive() {
super.requestActive();
if (tblResults != null) {
tblResults.requestFocusInWindow();
}
}
/** Map F12/S-F12 to next/prev error */
@ -126,7 +156,12 @@ public class OutputWindow extends TopComponent {
return true;
}
public static OutputWindow getInstance(){
/**
* Gets default instance. Do not use directly: reserved for *.settings files only,
* i.e. deserialization routines; otherwise you could get a non-deserialized instance.
* To obtain the singleton instance, use {@link findInstance}.
*/
public static synchronized OutputWindow getDefault(){
if (instance == null){
instance = new OutputWindow();
}
@ -134,32 +169,55 @@ public class OutputWindow extends TopComponent {
return instance;
}
public void open() {
Mode m = WindowManager.getDefault().findMode("output");
if (m != null) {
m.dockInto(this);
/**
* Obtain the OutputWindow_Generated instance. Never call {@link #getDefault} directly!
*/
public static synchronized OutputWindow findInstance() {
TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
if (win == null) {
ErrorManager.getDefault().log(ErrorManager.WARNING,
"Cannot find PMDOutputWindow component. It will not be located properly in the window system.");
return getDefault();
}
super.open();
if (win instanceof OutputWindow) {
return (OutputWindow)win;
}
ErrorManager.getDefault().log(ErrorManager.WARNING,
"There seem to be multiple components with the '" + PREFERRED_ID +
"' ID. That is a potential source of errors and unexpected behavior.");
return getDefault();
}
public void promote() {
open();
requestActive();
}
protected String preferredID(){
return "PMDOutput";
return PREFERRED_ID;
}
public int getPersistenceType(){
return PERSISTENCE_NEVER;
return PERSISTENCE_ALWAYS;
}
/**
* Avoids serializing the properties of this top component,
* which is not really necessary. Instead, getDefault() will get called
* when the component (or actually the replacer returned by this method)
* is deserialized.
*/
public Object writeReplace() {
return new ResolvableHelper();
}
public void setViolations(Fault violations[]){
tblMdlResults.setViolations(violations);
if (violations.length > 0){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
selectResultRow(0);
tblResults.getSelectionModel().setSelectionInterval(0, 0);
}
});
selectResultRow(0);
tblResults.getSelectionModel().setSelectionInterval(0, 0);
tblResults.getColumnModel().getSelectionModel().setSelectionInterval(0, 0);
}
}
@ -242,4 +300,13 @@ public class OutputWindow extends TopComponent {
String msg = fault.getMessage();
return msg.substring(msg.indexOf(",") + 1);
}
final static class ResolvableHelper implements Serializable {
private static final long serialVersionUID = 1L;
public Object readResolve() {
return OutputWindow.getDefault();
}
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN" "http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
<settings version="1.0">
<module name="pmd" spec="1.8.1"/>
<instanceof class="org.openide.windows.TopComponent"/>
<instanceof class="pmd.OutputWindow"/>
<instance class="pmd.OutputWindow" method="getDefault"/>
</settings>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tc-ref PUBLIC "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-ref2_0.dtd">
<tc-ref version="2.0" >
<module name="pmd" spec="1.8.1"/>
<tc-id id="PMDOutputWindow"/>
<state opened="false"/>
</tc-ref>

View File

@ -263,7 +263,6 @@ public class RunPMDAction extends CookieAction {
*/
protected void performAction( Node[] node ) {
FaultRegistry.getInstance().clearRegistry();
OutputWriter out = null;
try {
StatusDisplayer.getDefault().setStatusText("PMD checking for rule violations");
List<DataObject> list = getDataObjects(node);
@ -275,23 +274,19 @@ public class RunPMDAction extends CookieAction {
else {
StatusDisplayer.getDefault().setStatusText("PMD found rule violations");
}
final OutputWindow wnd = OutputWindow.getInstance();
wnd.setViolations(violations.toArray(new Fault[violations.size()]));
SwingUtilities.invokeLater(new Runnable(){
public void run(){
OutputWindow wnd = OutputWindow.findInstance();
wnd.setViolations(violations.toArray(new Fault[violations.size()]));
wnd.setDisplayName("PMD Output: found " + violations.size() + " violations");
wnd.open();
wnd.requestActive();
if (violations.size() > 0 ) {
wnd.promote();
}
}
});
} catch(IOException e) {
ErrorManager.getDefault().notify(e);
} finally {
if (out != null) {
out.close();
}
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2002-2006, the pmd-netbeans team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package pmd;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
/**
* @author Andrei Badea <andrei.badea@movzx.net>
*/
public final class ShowOutputWindowAction extends CallableSystemAction {
public void performAction() {
OutputWindow.findInstance().promote();
}
public String getName() {
return NbBundle.getMessage(ShowOutputWindowAction.class, "CTL_ShowOutputWindowAction");
}
protected void initialize() {
super.initialize();
// see org.openide.util.actions.SystemAction.iconResource() javadoc for more details
putValue("noIconInMenu", Boolean.TRUE);
}
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
protected boolean asynchronous() {
return false;
}
}

View File

@ -15,10 +15,22 @@
<attr name="SystemFileSystem.icon" urlvalue="nbresloc:/pmd/resources/PMDOptionsSettingsIcon.gif"/>
</file>
</folder>
<folder name="Menu">
<folder name="Window">
<attr name="ResultWindowOpenAction.shadow/pmd-ShowOutputWindowAction.shadow" boolvalue="true"/>
<file name="pmd-ShowOutputWindowAction.shadow">
<attr name="originalFile" stringvalue="Actions/Window/pmd-ShowOutputWindowAction.instance"/>
</file>
<attr name="pmd-ShowOutputWindowAction.shadow/Debug" boolvalue="true"/>
</folder>
</folder>
<folder name="Actions">
<folder name="Tools">
<file name="pmd-RunPMDAction.instance"/>
</folder>
<folder name="Window">
<file name="pmd-ShowOutputWindowAction.instance"/>
</folder>
</folder>
<folder name="Editors">
<folder name="AnnotationTypes">
@ -30,5 +42,18 @@
<file name="D-O-P.instance">
<attr name="instanceClass" stringvalue="pmd.RunPMDAction"/>
</file>
<file name="DOS-P.shadow">
<attr name="originalFile" stringvalue="Actions/Window/pmd-ShowOutputWindowAction.instance"/>
</file>
</folder>
<folder name="Windows2">
<folder name="Components">
<file name="PMDOutputWindow.settings" url="OutputWindowSettings.xml"/>
</folder>
<folder name="Modes">
<folder name="output">
<file name="PMDOutputWindow.wstcref" url="OutputWindowWstcref.xml"/>
</folder>
</folder>
</folder>
</filesystem>