From 602bb17578adb03f5d4a1924768fb49f51b4579b Mon Sep 17 00:00:00 2001 From: Don Leckie Date: Sat, 5 Oct 2002 20:11:31 +0000 Subject: [PATCH] GUI 10/5/2002 git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@1073 51baf565-9d33-0410-a72c-fc3788e3496d --- pmd/src/net/sourceforge/pmd/AbstractRule.java | 19 +- pmd/src/net/sourceforge/pmd/Rule.java | 4 +- .../net/sourceforge/pmd/RuleSetReader.java | 22 +- .../net/sourceforge/pmd/RuleSetWriter.java | 13 +- .../pmd/swingui/ComponentFactory.java | 2 + .../pmd/swingui/IRulesEditingData.java | 14 + .../pmd/swingui/NameChangeEvent.java | 51 --- .../pmd/swingui/NameChangeListener.java | 20 - .../pmd/swingui/PMDLookAndFeel.java | 6 +- .../sourceforge/pmd/swingui/PMDViewer.java | 26 ++ .../pmd/swingui/RuleAllEditingPanel.java | 54 ++- .../pmd/swingui/RuleEditingPanel.java | 93 ++++- .../pmd/swingui/RuleEditingTabbedPane.java | 187 +++++++-- .../pmd/swingui/RulePropertyEditingPanel.java | 364 +++++++++++++++++- .../pmd/swingui/RuleSetEditingPanel.java | 78 +++- .../sourceforge/pmd/swingui/RulesEditor.java | 40 +- .../sourceforge/pmd/swingui/RulesTree.java | 160 +++++++- .../pmd/swingui/RulesTreeNode.java | 30 +- 18 files changed, 1005 insertions(+), 178 deletions(-) delete mode 100644 pmd/src/net/sourceforge/pmd/swingui/NameChangeEvent.java delete mode 100644 pmd/src/net/sourceforge/pmd/swingui/NameChangeListener.java diff --git a/pmd/src/net/sourceforge/pmd/AbstractRule.java b/pmd/src/net/sourceforge/pmd/AbstractRule.java index 2bd47a80dd..f13aebcd30 100644 --- a/pmd/src/net/sourceforge/pmd/AbstractRule.java +++ b/pmd/src/net/sourceforge/pmd/AbstractRule.java @@ -10,7 +10,8 @@ import net.sourceforge.pmd.ast.ASTCompilationUnit; import java.util.List; import java.util.Iterator; -import java.util.Properties; +import java.util.Map; +import java.io.File; public abstract class AbstractRule extends JavaParserVisitorAdapter @@ -18,7 +19,7 @@ public abstract class AbstractRule { private String name = getClass().getName(); - private Properties properties = new Properties(); + private RuleProperties properties = new RuleProperties(); private String message; private String description; private String example; @@ -44,24 +45,24 @@ public abstract class AbstractRule return properties.containsKey( name ); } - public void addProperty(String name, String value) { - properties.put(name, value); + public void addProperty(String name, String property) { + properties.setProperty(name, property); } public double getDoubleProperty(String name) { - return Double.parseDouble(properties.getProperty(name)); + return properties.getDoubleValue(name); } public int getIntProperty(String name) { - return Integer.parseInt(properties.getProperty(name)); + return properties.getIntegerValue(name); } public boolean getBooleanProperty(String name) { - return Boolean.valueOf(properties.getProperty(name)).booleanValue(); + return properties.getBooleanValue(name); } public String getStringProperty(String name) { - return properties.getProperty(name); + return properties.getValue(name); } public String getName() { @@ -115,7 +116,7 @@ public abstract class AbstractRule * * @return An enumeration of property names */ - public Properties getProperties() + public RuleProperties getProperties() { return properties; } diff --git a/pmd/src/net/sourceforge/pmd/Rule.java b/pmd/src/net/sourceforge/pmd/Rule.java index b7442da840..e996cd471e 100644 --- a/pmd/src/net/sourceforge/pmd/Rule.java +++ b/pmd/src/net/sourceforge/pmd/Rule.java @@ -13,12 +13,12 @@ public interface Rule { public void setExample(String example); public void apply(List astCompilationUnits, RuleContext ctx); public boolean hasProperty(String name); - public void addProperty(String name, String value); + public void addProperty(String name, String property); public int getIntProperty(String name); public boolean getBooleanProperty(String name); public String getStringProperty(String name); public double getDoubleProperty(String name); - public Properties getProperties(); + public RuleProperties getProperties(); public boolean include(); public void setInclude(boolean include); } diff --git a/pmd/src/net/sourceforge/pmd/RuleSetReader.java b/pmd/src/net/sourceforge/pmd/RuleSetReader.java index 8508da1699..1dfb49879b 100644 --- a/pmd/src/net/sourceforge/pmd/RuleSetReader.java +++ b/pmd/src/net/sourceforge/pmd/RuleSetReader.java @@ -27,6 +27,7 @@ public class RuleSetReader // Constants private final String REJECT_NOT_INCLUDED = "Reject not included"; + private final String EMPTY_STRING = ""; /** ***************************************************************************** @@ -196,8 +197,8 @@ public class RuleSetReader className = attributes.getValue("class"); includeText = attributes.getValue("include"); ruleName = (ruleName == null) ? "Unknown" : ruleName.trim(); - message = (message == null) ? "" : message.trim(); - className = (className == null) ? "" : className.trim(); + message = (message == null) ? EMPTY_STRING : message.trim(); + className = (className == null) ? EMPTY_STRING : className.trim(); includeText = (includeText == null) ? "true" : includeText.trim(); include = includeText.equalsIgnoreCase("true"); @@ -213,7 +214,7 @@ public class RuleSetReader Object[] args = {ruleName, m_ruleSet.getName()}; String msg = MessageFormat.format(template, args); PMDException pmdException = new PMDException(msg); - SAXException saxException = new SAXException("", pmdException); + SAXException saxException = new SAXException(EMPTY_STRING, pmdException); pmdException.fillInStackTrace(); throw saxException; } @@ -231,7 +232,7 @@ public class RuleSetReader Object[] args = {className}; String msg = MessageFormat.format(template, args); PMDException pmdException = new PMDException(msg, exception); - SAXException saxException = new SAXException("", pmdException); + SAXException saxException = new SAXException(EMPTY_STRING, pmdException); pmdException.fillInStackTrace(); throw saxException; } @@ -241,7 +242,7 @@ public class RuleSetReader Object[] args = {className, ruleName, m_ruleSet.getName()}; String msg = MessageFormat.format(template, args); PMDException pmdException = new PMDException(msg, exception); - SAXException saxException = new SAXException("", pmdException); + SAXException saxException = new SAXException(EMPTY_STRING, pmdException); pmdException.fillInStackTrace(); throw saxException; } @@ -251,7 +252,7 @@ public class RuleSetReader Object[] args = {className, ruleName, m_ruleSet.getName()}; String msg = MessageFormat.format(template, args); PMDException pmdException = new PMDException(msg, exception); - SAXException saxException = new SAXException("", pmdException); + SAXException saxException = new SAXException(EMPTY_STRING, pmdException); pmdException.fillInStackTrace(); throw saxException; } @@ -265,13 +266,16 @@ public class RuleSetReader { String name = attributes.getValue("name"); String value = attributes.getValue("value"); + String type = attributes.getValue("type"); - name = (name == null) ? "" : name.trim(); - value = (value == null) ? "" : value; + name = (name == null) ? EMPTY_STRING : name.trim(); + value = (value == null) ? EMPTY_STRING : value; + type = (type == null) ? EMPTY_STRING : type; if (name.length() > 0) { - m_rule.addProperty(name, value); + m_rule.getProperties().setValue(name, value); + m_rule.getProperties().setValueType(name, type); } } } diff --git a/pmd/src/net/sourceforge/pmd/RuleSetWriter.java b/pmd/src/net/sourceforge/pmd/RuleSetWriter.java index 1ddf58a986..530ac6b01c 100644 --- a/pmd/src/net/sourceforge/pmd/RuleSetWriter.java +++ b/pmd/src/net/sourceforge/pmd/RuleSetWriter.java @@ -221,20 +221,23 @@ public class RuleSetWriter outputLine(); indent(); - Properties properties = rule.getProperties(); + RuleProperties properties = rule.getProperties(); Enumeration keys = properties.keys(); while (keys.hasMoreElements()) { - String propertyName = (String) keys.nextElement(); - String propertyValue = properties.getProperty(propertyName); + String name = (String) keys.nextElement(); + String value = properties.getValue(name); + String valueType = properties.getValueType(name); // setupNewLine(); m_line.append(""); outputLine(); } diff --git a/pmd/src/net/sourceforge/pmd/swingui/ComponentFactory.java b/pmd/src/net/sourceforge/pmd/swingui/ComponentFactory.java index cbe5115148..6dbf5c7eca 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/ComponentFactory.java +++ b/pmd/src/net/sourceforge/pmd/swingui/ComponentFactory.java @@ -70,6 +70,7 @@ class ComponentFactory button.setFont(UIManager.getFont("buttonFont")); button.setSize(size); button.setPreferredSize(size); + button.setOpaque(true); return button; } @@ -184,6 +185,7 @@ class ComponentFactory textArea.setLineWrap(true); textArea.setWrapStyleWord(true); textArea.setBorder(compoundBorder); + textArea.setOpaque(true); return textArea; } diff --git a/pmd/src/net/sourceforge/pmd/swingui/IRulesEditingData.java b/pmd/src/net/sourceforge/pmd/swingui/IRulesEditingData.java index d64c85b144..e0ca42a149 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/IRulesEditingData.java +++ b/pmd/src/net/sourceforge/pmd/swingui/IRulesEditingData.java @@ -65,6 +65,13 @@ public interface IRulesEditingData */ public String getPropertyValue(); + /** + ******************************************************************************* + * + * @return + */ + public String getPropertyValueType(); + /** ******************************************************************************* * @@ -142,6 +149,13 @@ public interface IRulesEditingData */ public void setPropertyValue(String value); + /** + ******************************************************************************* + * + * @return + */ + public void setPropertyValueType(String value); + /** ******************************************************************************* * diff --git a/pmd/src/net/sourceforge/pmd/swingui/NameChangeEvent.java b/pmd/src/net/sourceforge/pmd/swingui/NameChangeEvent.java deleted file mode 100644 index a64de82fe1..0000000000 --- a/pmd/src/net/sourceforge/pmd/swingui/NameChangeEvent.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.sourceforge.pmd.swingui; - -import java.util.EventObject; - -/** - * - * @author Donald A. Leckie - * @since September 27, 2002 - * @version $Revision$, $Date$ - */ -class NameChangeEvent extends EventObject -{ - - private String m_oldName; - private String m_newName; - - /** - ********************************************************************************* - * - * @param source - * @param oldName - * @param newName - */ - protected NameChangeEvent(Object source, String oldName, String newName) - { - super(source); - - m_oldName = oldName; - m_newName = newName; - } - - /** - ********************************************************************************* - * - * @return - */ - protected String getOldName() - { - return m_oldName; - } - - /** - ********************************************************************************* - * - * @return - */ - protected String getNewName() - { - return m_newName; - } -} \ No newline at end of file diff --git a/pmd/src/net/sourceforge/pmd/swingui/NameChangeListener.java b/pmd/src/net/sourceforge/pmd/swingui/NameChangeListener.java deleted file mode 100644 index aa836b63f9..0000000000 --- a/pmd/src/net/sourceforge/pmd/swingui/NameChangeListener.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.sourceforge.pmd.swingui; - -import java.util.EventListener; - -/** - * - * @author Donald A. Leckie - * @since September 27, 2002 - * @version $Revision$, $Date$ - */ -public interface NameChangeListener extends EventListener -{ - - /** - ****************************************************************************** - * - * @param event - */ - public void nameChanged(NameChangeEvent event); -} \ No newline at end of file diff --git a/pmd/src/net/sourceforge/pmd/swingui/PMDLookAndFeel.java b/pmd/src/net/sourceforge/pmd/swingui/PMDLookAndFeel.java index ffa6c55a17..88215847b8 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/PMDLookAndFeel.java +++ b/pmd/src/net/sourceforge/pmd/swingui/PMDLookAndFeel.java @@ -195,7 +195,11 @@ public class PMDLookAndFeel extends WindowsLookAndFeel try { InputStream inputStream = getClass().getResourceAsStream("pmdViewer.properties"); - properties.load(inputStream); + + if (inputStream != null) + { + properties.load(inputStream); + } } catch (IOException exception) { diff --git a/pmd/src/net/sourceforge/pmd/swingui/PMDViewer.java b/pmd/src/net/sourceforge/pmd/swingui/PMDViewer.java index c0f289e717..705aca084e 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/PMDViewer.java +++ b/pmd/src/net/sourceforge/pmd/swingui/PMDViewer.java @@ -3,6 +3,7 @@ package net.sourceforge.pmd.swingui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Cursor; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.StringSelection; @@ -45,6 +46,7 @@ import javax.swing.JTree; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.KeyStroke; +import javax.swing.MenuElement; import javax.swing.SwingUtilities; import javax.swing.UIManager; @@ -364,9 +366,21 @@ public class PMDViewer extends JFrame implements JobThreadListener if (m_disabledCounter == 0) { Component glassPane = getGlassPane(); + JMenuBar menuBar = getJMenuBar(); + MenuElement[] menuElements = menuBar.getSubElements(); glassPane.setVisible(false); glassPane.removeMouseListener(m_glassPaneMouseListener); + glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + menuBar.setEnabled(true); + + for (int n = 0; n < menuElements.length; n++) + { + if (menuElements[n] instanceof JMenu) + { + ((JMenu) menuElements[n]).setEnabled(true); + } + } } } else @@ -374,9 +388,21 @@ public class PMDViewer extends JFrame implements JobThreadListener if (m_disabledCounter == 0) { Component glassPane = getGlassPane(); + JMenuBar menuBar = getJMenuBar(); + MenuElement[] menuElements = menuBar.getSubElements(); glassPane.setVisible(true); glassPane.addMouseListener(m_glassPaneMouseListener); + glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + menuBar.setEnabled(false); + + for (int n = 0; n < menuElements.length; n++) + { + if (menuElements[n] instanceof JMenu) + { + ((JMenu) menuElements[n]).setEnabled(false); + } + } } m_disabledCounter++; diff --git a/pmd/src/net/sourceforge/pmd/swingui/RuleAllEditingPanel.java b/pmd/src/net/sourceforge/pmd/swingui/RuleAllEditingPanel.java index 36105d32c6..b0fd2c1733 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RuleAllEditingPanel.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RuleAllEditingPanel.java @@ -82,7 +82,17 @@ public class RuleAllEditingPanel extends JPanel /** ******************************************************************************* * - * @param data + * @return + */ + protected boolean isEditing() + { + return m_isEditing; + } + + /** + ******************************************************************************* + * + * @param isEditing */ protected void setIsEditing(boolean isEditing) { @@ -92,6 +102,48 @@ public class RuleAllEditingPanel extends JPanel m_rulePropertyPanel.setIsEditing(isEditing); } + /** + ******************************************************************************* + * + * @return + */ + public IRulesEditingData[] getData() + { + IRulesEditingData ruleSetData; + IRulesEditingData ruleData; + IRulesEditingData propertyData; + IRulesEditingData[] data; + + ruleSetData = m_ruleSetPanel.getData(); + ruleData = m_rulePanel.getData(); + propertyData = m_rulePropertyPanel.getData(); + + if (propertyData != null) + { + data = new IRulesEditingData[3]; + data[0] = ruleSetData; + data[1] = ruleData; + data[2] = propertyData; + } + else if (ruleData != null) + { + data = new IRulesEditingData[2]; + data[0] = ruleSetData; + data[1] = ruleData; + } + else if (ruleSetData != null) + { + data = new IRulesEditingData[1]; + data[0] = ruleSetData; + } + else + { + data = new IRulesEditingData[0]; + } + + return data; + } + /** ******************************************************************************* * diff --git a/pmd/src/net/sourceforge/pmd/swingui/RuleEditingPanel.java b/pmd/src/net/sourceforge/pmd/swingui/RuleEditingPanel.java index bb5b9fb5fb..a33d456bca 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RuleEditingPanel.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RuleEditingPanel.java @@ -13,6 +13,8 @@ import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Window; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; @@ -57,6 +59,7 @@ public class RuleEditingPanel extends JPanel private IRulesEditingData m_currentData; private boolean m_isEditing; private String m_originalName; + private FocusListener m_focusListener = new RuleNameFocusListener(); /** ******************************************************************************* @@ -84,17 +87,22 @@ public class RuleEditingPanel extends JPanel m_nameLabel = new JLabel("Name"); m_nameLabel.setFont(UIManager.getFont("labelFont")); m_nameLabel.setHorizontalAlignment(JLabel.RIGHT); + m_nameLabel.setOpaque(true); panel.add(m_nameLabel); // Rule Name Text m_name = new JTextField(); m_name.setFont(UIManager.getFont("dataFont")); + m_name.addFocusListener(m_focusListener); + m_name.setRequestFocusEnabled(true); + m_name.setOpaque(true); panel.add(m_name); // Rule Class Name Label m_classNameLabel = new JLabel("Class Name"); m_classNameLabel.setFont(UIManager.getFont("labelFont")); m_classNameLabel.setHorizontalAlignment(JLabel.RIGHT); + m_classNameLabel.setOpaque(true); panel.add(m_classNameLabel); // Rule Class Name Text @@ -103,14 +111,17 @@ public class RuleEditingPanel extends JPanel m_className.setBackground(UIManager.getColor("disabledTextBackground")); m_className.setForeground(Color.black); m_className.setSelectedTextColor(Color.black); + m_className.setDisabledTextColor(Color.black); m_className.setEditable(false); m_className.setEnabled(false); + m_className.setOpaque(true); panel.add(m_className); // Rule Message Label m_messageLabel = new JLabel("Message"); m_messageLabel.setFont(UIManager.getFont("labelFont")); m_messageLabel.setHorizontalAlignment(JLabel.RIGHT); + m_messageLabel.setOpaque(true); panel.add(m_messageLabel); // Rule Message Text @@ -168,25 +179,86 @@ public class RuleEditingPanel extends JPanel { if (m_isEditing && (m_currentData != null)) { - m_currentData.setName(m_name.getText()); + String ruleName = m_name.getText(); + + if (ruleName.length() == 0) + { + String message = "The rule name is missing. The change will not be applied."; + boolean hasFocus = m_name.hasFocus(); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + if (hasFocus) + { + m_name.requestFocus(); + } + + ruleName = m_originalName; + } + else if (ruleName.equalsIgnoreCase(m_originalName) == false) + { + if (m_currentData.getSibling(ruleName) != null) + { + String template = "Another rule already has the name \"{0}\". The change will not be applied."; + String[] args = {ruleName}; + String message = MessageFormat.format(template, args); + boolean hasFocus = m_name.hasFocus(); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + if (hasFocus) + { + m_name.requestFocus(); + } + + ruleName = m_originalName; + } + } + + m_currentData.setName(ruleName); m_currentData.setClassName(m_className.getText()); m_currentData.setMessage(m_message.getText()); m_currentData.setDescription(m_description.getText()); m_currentData.setExample(m_example.getText()); m_currentData.setInclude(m_include.isSelected()); + enableData(false); } } /** ******************************************************************************* * - * @param data + * @param isEditing */ protected void setIsEditing(boolean isEditing) { m_isEditing = isEditing; } + /** + ******************************************************************************* + * + * @return + */ + protected boolean isEditing() + { + return m_isEditing; + } + + /** + ******************************************************************************* + * + * @return + */ + public IRulesEditingData getData() + { + return m_currentData; + } + /** ******************************************************************************* * @@ -194,7 +266,11 @@ public class RuleEditingPanel extends JPanel */ public void setData(IRulesEditingData data) { - if (data.isRuleSet()) + if (data == null) + { + enableData(false); + } + else if (data.isRuleSet()) { enableData(false); } @@ -245,6 +321,9 @@ public class RuleEditingPanel extends JPanel { if (enable) { + // Just to be sure the focus listener isn't already set. + m_name.removeFocusListener(m_focusListener); + m_name.addFocusListener(m_focusListener); m_name.setEnabled(true); m_name.setBackground(Color.white); m_message.setEnabled(true); @@ -257,6 +336,8 @@ public class RuleEditingPanel extends JPanel } else { + m_name.removeFocusListener(m_focusListener); + Color background = UIManager.getColor("disabledTextBackground"); m_name.setText(""); @@ -711,7 +792,7 @@ public class RuleEditingPanel extends JPanel ************************************************************************************ */ - private class RuleSetNameFocusListener implements FocusListener + private class RuleNameFocusListener implements FocusListener { /** @@ -735,7 +816,9 @@ public class RuleEditingPanel extends JPanel if (ruleName.length() == 0) { String message = "The rule name is missing."; + m_name.removeFocusListener(this); MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(this); m_name.requestFocus(); } else if (ruleName.equalsIgnoreCase(m_originalName) == false) @@ -745,7 +828,9 @@ public class RuleEditingPanel extends JPanel String template = "Another rule already has the name \"{0}\"."; String[] args = {ruleName}; String message = MessageFormat.format(template, args); + m_name.removeFocusListener(this); MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(this); m_name.requestFocus(); } } diff --git a/pmd/src/net/sourceforge/pmd/swingui/RuleEditingTabbedPane.java b/pmd/src/net/sourceforge/pmd/swingui/RuleEditingTabbedPane.java index 58ad02a349..1fee6d9a9c 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RuleEditingTabbedPane.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RuleEditingTabbedPane.java @@ -5,6 +5,7 @@ import javax.swing.event.ChangeListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; import javax.swing.tree.TreePath; import javax.swing.UIManager; @@ -14,7 +15,7 @@ import javax.swing.UIManager; * @since August 29, 2002 * @version $Revision$, $Date$ */ -public class RuleEditingTabbedPane extends JTabbedPane implements TreeSelectionListener, ChangeListener +public class RuleEditingTabbedPane extends JTabbedPane { private RulesTree m_rulesTree; @@ -22,6 +23,8 @@ public class RuleEditingTabbedPane extends JTabbedPane implements TreeSelectionL private RuleEditingPanel m_rulePanel; private RulePropertyEditingPanel m_rulePropertyPanel; private RuleAllEditingPanel m_ruleAllPanel; + private boolean m_changeListenerIsEnabled; + private boolean m_selectionListenerIsEnabled; /** ******************************************************************************* @@ -37,6 +40,8 @@ public class RuleEditingTabbedPane extends JTabbedPane implements TreeSelectionL m_ruleSetPanel = new RuleSetEditingPanel(); m_rulePanel = new RuleEditingPanel(); m_rulePropertyPanel = new RulePropertyEditingPanel(); + m_changeListenerIsEnabled = true; + m_selectionListenerIsEnabled = true; addTab("All", m_ruleAllPanel); addTab("Rule Set", m_ruleSetPanel); @@ -45,8 +50,9 @@ public class RuleEditingTabbedPane extends JTabbedPane implements TreeSelectionL setFont(UIManager.getFont("tabFont")); m_ruleAllPanel.setIsEditing(true); - rulesTree.addTreeSelectionListener(this); - addChangeListener(this); + + rulesTree.addTreeSelectionListener(new RulesTreeSelectionListener()); + addChangeListener(new RulesTreeChangeListener()); } /** @@ -86,52 +92,165 @@ public class RuleEditingTabbedPane extends JTabbedPane implements TreeSelectionL /** ******************************************************************************* * - * @param event + * @return */ - public void stateChanged(ChangeEvent event) + private IRulesEditingData[] getData() { - saveData(); - Object selectedComponent = getSelectedComponent(); - m_ruleAllPanel.setIsEditing(selectedComponent == m_ruleAllPanel); - m_ruleSetPanel.setIsEditing(selectedComponent == m_ruleSetPanel); - m_rulePanel.setIsEditing(selectedComponent == m_rulePanel); - m_rulePropertyPanel.setIsEditing(selectedComponent == m_rulePropertyPanel); - setData(getSelectedTreeNode()); + IRulesEditingData[] data; + + if (m_ruleAllPanel.isEditing()) + { + data = m_ruleAllPanel.getData(); + } + else if (m_ruleSetPanel.isEditing()) + { + data = new IRulesEditingData[1]; + data[0] = m_ruleSetPanel.getData(); + } + else if (m_rulePanel.isEditing()) + { + data = new IRulesEditingData[1]; + data[0] = m_rulePanel.getData(); + } + else if (m_rulePropertyPanel.isEditing()) + { + data = new IRulesEditingData[1]; + data[0] = m_rulePropertyPanel.getData(); + } + else + { + data = new IRulesEditingData[0]; + } + + return data; } /** ******************************************************************************* - * - * @param event + ******************************************************************************* + ******************************************************************************* */ - public void valueChanged(TreeSelectionEvent event) + private class RulesTreeChangeListener implements ChangeListener { - TreePath treePath = event.getPath(); - Object component = treePath.getLastPathComponent(); - if (component instanceof RulesTreeNode) + /** + ******************************************************************************* + * + * @param event + */ + public void stateChanged(ChangeEvent event) { - RulesTreeNode treeNode = (RulesTreeNode) component; - - saveData(); - - if (getSelectedComponent() != m_ruleAllPanel) + if (m_changeListenerIsEnabled) { - if (treeNode.isRuleSet()) + IRulesEditingData[] currentData = getData(); + + saveData(); + + Object selectedComponent = getSelectedComponent(); + m_ruleAllPanel.setIsEditing(selectedComponent == m_ruleAllPanel); + m_ruleSetPanel.setIsEditing(selectedComponent == m_ruleSetPanel); + m_rulePanel.setIsEditing(selectedComponent == m_rulePanel); + m_rulePropertyPanel.setIsEditing(selectedComponent == m_rulePropertyPanel); + setData(getSelectedTreeNode()); + SwingUtilities.invokeLater(new SortChildren(currentData)); + } + } + } + + /** + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + */ + private class RulesTreeSelectionListener implements TreeSelectionListener + { + + /** + ******************************************************************************* + * + * @param event + */ + public void valueChanged(TreeSelectionEvent event) + { + if (m_selectionListenerIsEnabled) + { + TreePath treePath = event.getPath(); + Object component = treePath.getLastPathComponent(); + + if (component instanceof RulesTreeNode) { - setSelectedComponent(m_ruleSetPanel); - } - else if (treeNode.isRule()) - { - setSelectedComponent(m_rulePanel); - } - else if (treeNode.isProperty()) - { - setSelectedComponent(m_rulePropertyPanel); + IRulesEditingData[] currentData = getData(); + + saveData(); + + RulesTreeNode treeNode = (RulesTreeNode) component; + + if (getSelectedComponent() != m_ruleAllPanel) + { + if (treeNode.isRuleSet()) + { + setSelectedComponent(m_ruleSetPanel); + } + else if (treeNode.isRule()) + { + setSelectedComponent(m_rulePanel); + } + else if (treeNode.isProperty()) + { + setSelectedComponent(m_rulePropertyPanel); + } + } + + setData(treeNode); + SwingUtilities.invokeLater(new SortChildren(currentData)); } } + } + } - setData(treeNode); + /** + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + */ + private class SortChildren implements Runnable + { + + private IRulesEditingData[] m_childData; + + /** + *************************************************************************** + * + * @param currentData + */ + private SortChildren(IRulesEditingData[] childData) + { + m_childData = childData; + } + + /** + *************************************************************************** + * + */ + public void run() + { + if (m_childData != null) + { + TreePath selectedPath = m_rulesTree.getSelectionPath(); + m_changeListenerIsEnabled = false; + m_selectionListenerIsEnabled = false; + m_rulesTree.removeSelectionPath(selectedPath); + + for (int n = 0; n < m_childData.length; n++) + { + RulesTreeNode childNode = (RulesTreeNode) m_childData[n]; + m_rulesTree.sortChildren((RulesTreeNode) childNode.getParent()); + } + + m_rulesTree.setSelectionPath(selectedPath); + m_changeListenerIsEnabled = true; + m_selectionListenerIsEnabled = true; + } } } } \ No newline at end of file diff --git a/pmd/src/net/sourceforge/pmd/swingui/RulePropertyEditingPanel.java b/pmd/src/net/sourceforge/pmd/swingui/RulePropertyEditingPanel.java index 02803c6132..7bdcf49407 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RulePropertyEditingPanel.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RulePropertyEditingPanel.java @@ -5,15 +5,24 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Insets; import java.awt.LayoutManager; +import java.awt.Window; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.border.TitledBorder; import javax.swing.JComponent; +import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; @@ -32,9 +41,20 @@ public class RulePropertyEditingPanel extends JPanel private JTextField m_name; private JLabel m_valueLabel; private JTextField m_value; + private JLabel m_valueTypeLabel; + private JComboBox m_valueType; private boolean m_enabled; private IRulesEditingData m_currentData; private boolean m_isEditing; + private String m_originalName; + private String m_originalValue; + private FocusListener m_focusListener = new PropertyNameFocusListener(); + + // Constants + private final String BOOLEAN = "Boolean"; + private final String DECIMAL_NUMBER = "Decimal Number"; + private final String INTEGER = "Integer"; + private final String STRING = "String"; /** ******************************************************************************* @@ -62,24 +82,44 @@ public class RulePropertyEditingPanel extends JPanel m_nameLabel = new JLabel("Name"); m_nameLabel.setFont(UIManager.getFont("labelFont")); m_nameLabel.setHorizontalAlignment(JLabel.RIGHT); + m_nameLabel.setOpaque(true); panel.add(m_nameLabel); // Property Name Text m_name = new JTextField(); m_name.setFont(UIManager.getFont("dataFont")); + m_name.addFocusListener(m_focusListener); + m_name.setRequestFocusEnabled(true); + m_name.setOpaque(true); panel.add(m_name); // Property Value Label m_valueLabel = new JLabel("Value"); m_valueLabel.setFont(UIManager.getFont("labelFont")); m_valueLabel.setHorizontalAlignment(JLabel.RIGHT); + m_valueLabel.setOpaque(true); panel.add(m_valueLabel); // Property Value Text m_value = new JTextField(); m_value.setFont(UIManager.getFont("dataFont")); + m_value.setOpaque(true); panel.add(m_value); + // Property Value Type Label + m_valueTypeLabel = new JLabel("Type"); + m_valueTypeLabel.setFont(UIManager.getFont("labelFont")); + m_valueTypeLabel.setHorizontalAlignment(JLabel.RIGHT); + m_valueTypeLabel.setOpaque(true); + panel.add(m_valueTypeLabel); + + // Property Value Type + String[] items = {STRING, BOOLEAN, DECIMAL_NUMBER, INTEGER}; + m_valueType = new JComboBox(items); + m_valueType.setEditable(false); + m_valueType.setOpaque(true); + panel.add(m_valueType); + enableData(false); } @@ -91,21 +131,208 @@ public class RulePropertyEditingPanel extends JPanel { if (m_isEditing && (m_currentData != null)) { - m_currentData.setName(m_name.getText()); - m_currentData.setPropertyValue(m_value.getText()); + // Test for valid property name. + String propertyName = m_name.getText(); + + if (propertyName.equalsIgnoreCase(m_originalName) == false) + { + if (m_currentData.getSibling(propertyName) != null) + { + String template = "Another property already has the name \"{0}\". The change will not be applied."; + String[] args = {propertyName}; + String message = MessageFormat.format(template, args); + boolean hasFocus = m_name.hasFocus(); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + if (hasFocus) + { + m_name.requestFocus(); + } + + propertyName = m_originalName; + } + } + + // Test for valid value. + String valueText = m_value.getText(); + String selectedItem = (String) m_valueType.getSelectedItem(); + + if (selectedItem.equalsIgnoreCase(BOOLEAN)) + { + valueText = saveBoolean(valueText); + } + else if (selectedItem.equalsIgnoreCase(DECIMAL_NUMBER)) + { + valueText = saveDecimalNumber(valueText); + } + else if (selectedItem.equalsIgnoreCase(INTEGER)) + { + valueText = saveInteger(valueText); + } + + m_currentData.setName(propertyName); + m_currentData.setPropertyValue(valueText); + m_currentData.setPropertyValueType(selectedItem); + enableData(false); } } /** ******************************************************************************* * - * @param data + * @param valueText + */ + private String saveBoolean(String valueText) + { + boolean originalValue; + boolean newValue; + + try + { + originalValue = Boolean.getBoolean(m_originalValue); + } + catch (NumberFormatException exception) + { + originalValue = true; + } + + try + { + newValue = Boolean.getBoolean(valueText); + valueText = String.valueOf(newValue); + } + catch (NumberFormatException exception) + { + String template = "New property of \"{0}\" is not a boolean. The change will not be applied."; + String[] args = {valueText}; + String message = MessageFormat.format(template, args); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + newValue = originalValue; + valueText = m_originalValue; + } + + return valueText; + } + + /** + ******************************************************************************* + * + * @param valueText + */ + private String saveDecimalNumber(String valueText) + { + double originalValue; + double newValue; + + try + { + originalValue = Double.parseDouble(m_originalValue); + } + catch (NumberFormatException exception) + { + originalValue = 0.0; + } + + try + { + newValue = Double.parseDouble(valueText); + valueText = String.valueOf(newValue); + } + catch (NumberFormatException exception) + { + String template = "New property of \"{0}\" is not a decimal number. The change will not be applied."; + String[] args = {valueText}; + String message = MessageFormat.format(template, args); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + newValue = originalValue; + valueText = m_originalValue; + } + + return valueText; + } + + /** + ******************************************************************************* + * + * @param valueText + */ + private String saveInteger(String valueText) + { + int originalValue; + int newValue; + + try + { + originalValue = Integer.parseInt(m_originalValue); + } + catch (NumberFormatException exception) + { + originalValue = 0; + } + + try + { + newValue = Integer.parseInt(valueText); + valueText = String.valueOf(newValue); + } + catch (NumberFormatException exception) + { + String template = "New property of \"{0}\" is not an integer. The change will not be applied."; + String[] args = {valueText}; + String message = MessageFormat.format(template, args); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + newValue = originalValue; + valueText = m_originalValue; + } + + return valueText; + } + + /** + ******************************************************************************* + * + * @param isEditing */ protected void setIsEditing(boolean isEditing) { m_isEditing = isEditing; } + /** + ******************************************************************************* + * + * @return + */ + protected boolean isEditing() + { + return m_isEditing; + } + + /** + ******************************************************************************* + * + * @return + */ + public IRulesEditingData getData() + { + return m_currentData; + } + /** ******************************************************************************* * @@ -113,7 +340,11 @@ public class RulePropertyEditingPanel extends JPanel */ public void setData(IRulesEditingData data) { - if (data.isRuleSet()) + if (data == null) + { + enableData(false); + } + else if (data.isRuleSet()) { enableData(false); } @@ -145,9 +376,15 @@ public class RulePropertyEditingPanel extends JPanel enableData(true); } - m_name.setText(data.getName()); - m_value.setText(data.getPropertyValue()); + String name = data.getName(); + String valueType = data.getPropertyValueType(); + m_name.setText(name); + m_value.setText(data.getPropertyValue()); + m_valueType.setSelectedItem(valueType); + + m_originalName = name; + m_originalValue = valueType; m_currentData = data; } } @@ -160,13 +397,20 @@ public class RulePropertyEditingPanel extends JPanel { if (enable) { + // Just to be sure the focus listener isn't set. + m_name.removeFocusListener(m_focusListener); + m_name.addFocusListener(m_focusListener); m_name.setEnabled(true); m_name.setBackground(Color.white); m_value.setEnabled(true); m_value.setBackground(Color.white); + m_valueType.setEnabled(true); + m_valueType.setBackground(Color.white); } else { + m_name.removeFocusListener(m_focusListener); + Color background = UIManager.getColor("disabledTextBackground"); m_name.setText(""); @@ -177,12 +421,33 @@ public class RulePropertyEditingPanel extends JPanel m_value.setEnabled(false); m_value.setBackground(background); + m_valueType.setSelectedIndex(0); + m_valueType.setEnabled(false); + m_valueType.setBackground(background); + m_currentData = null; } m_enabled = enable; } + /** + ******************************************************************************* + * + * @return + */ + private Window getParentWindow() + { + Component component = getParent(); + + while ((component != null) && ((component instanceof Window) == false)) + { + component = component.getParent(); + } + + return (Window) component; + } + /** ******************************************************************************* ******************************************************************************* @@ -320,6 +585,15 @@ public class RulePropertyEditingPanel extends JPanel valueLabelWidth = fontMetrics.stringWidth(m_valueLabel.getText()); valueLabelHeight = fontMetrics.getHeight(); + // Calculate Value Type Label + int valueTypeLabelWidth; + int valueTypeLabelHeight; + + font = m_valueTypeLabel.getFont(); + fontMetrics = m_valueTypeLabel.getFontMetrics(font); + valueTypeLabelWidth = fontMetrics.stringWidth(m_valueTypeLabel.getText()); + valueTypeLabelHeight = fontMetrics.getHeight(); + // Calculate first column width. int firstColumnWidth = nameLabelWidth; @@ -328,6 +602,11 @@ public class RulePropertyEditingPanel extends JPanel firstColumnWidth = valueLabelWidth; } + if (valueTypeLabelWidth > firstColumnWidth) + { + firstColumnWidth = valueTypeLabelWidth; + } + // // Set the margin between label and data. // @@ -359,6 +638,16 @@ public class RulePropertyEditingPanel extends JPanel valueWidth = insets.left + insets.right; valueHeight = fontMetrics.getHeight() + insets.top + insets.bottom; + // Calculate Value Type Popup Menu + int valueTypeWidth; + int valueTypeHeight; + + font = m_value.getFont(); + fontMetrics = m_valueType.getFontMetrics(font); + insets = m_valueType.getBorder().getBorderInsets(m_valueType); + valueTypeWidth = insets.left + insets.right; + valueTypeHeight = 20; + // Calculate second column width. int secondColumnWidth = containerSize.width - containerInsets.left @@ -369,6 +658,7 @@ public class RulePropertyEditingPanel extends JPanel // Calculate Line Heights int firstLineHeight = (nameHeight > nameLabelHeight) ? nameHeight : nameLabelHeight; int secondLineHeight = (valueHeight > valueLabelHeight) ? valueHeight : valueLabelHeight; + int thirdLineHeight = (valueTypeHeight > valueTypeLabelHeight) ? valueTypeHeight : valueTypeLabelHeight; if (computePanelSize) { @@ -381,6 +671,8 @@ public class RulePropertyEditingPanel extends JPanel + firstLineHeight + lineSpacing + secondLineHeight + + lineSpacing + + thirdLineHeight + containerInsets.bottom; return new Dimension(panelWidth, panelHeight); @@ -413,7 +705,67 @@ public class RulePropertyEditingPanel extends JPanel y = containerInsets.top + firstLineHeight + lineSpacing; m_value.setBounds(x, y, secondColumnWidth, valueHeight); + // Layout Value Type Label + x = containerInsets.left; + y = containerInsets.top + firstLineHeight + lineSpacing + secondLineHeight + lineSpacing; + m_valueTypeLabel.setBounds(x, y, firstColumnWidth, valueTypeLabelHeight); + + // Layout Value Type Popup Menu + x = containerInsets.left + firstColumnWidth + columnSpacing; + y = containerInsets.top + firstLineHeight + lineSpacing + secondLineHeight + lineSpacing; + m_valueType.setBounds(x, y, secondColumnWidth, valueTypeHeight); + return null; } } + + /** + ************************************************************************************ + ************************************************************************************ + ************************************************************************************ + */ + private class PropertyNameFocusListener implements FocusListener + { + + /** + ************************************************************************** + * + * @param event + */ + public void focusGained(FocusEvent event) + { + } + + /** + ************************************************************************** + * + * @param event + */ + public void focusLost(FocusEvent event) + { + String propertyName = m_name.getText().trim(); + + if (propertyName.length() == 0) + { + String message = "The property name is missing."; + m_name.removeFocusListener(this); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(this); + m_name.requestFocus(); + } + else if (propertyName.equalsIgnoreCase(m_originalName) == false) + { + if (m_currentData.getSibling(propertyName) != null) + { + String template = "Another property already has the name \"{0}\"."; + String[] args = {propertyName}; + String message = MessageFormat.format(template, args); + m_name.removeFocusListener(this); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(this); + m_name.requestFocus(); + } + } + } + } } \ No newline at end of file diff --git a/pmd/src/net/sourceforge/pmd/swingui/RuleSetEditingPanel.java b/pmd/src/net/sourceforge/pmd/swingui/RuleSetEditingPanel.java index eeb33c3856..ce1d877793 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RuleSetEditingPanel.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RuleSetEditingPanel.java @@ -13,6 +13,8 @@ import java.awt.Insets; import java.awt.LayoutManager; import java.awt.Window; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; @@ -49,6 +51,7 @@ public class RuleSetEditingPanel extends JPanel private IRulesEditingData m_currentData; private boolean m_isEditing; private String m_originalName; + private FocusListener m_focusListener = new RuleSetNameFocusListener(); /** ******************************************************************************* @@ -72,19 +75,22 @@ public class RuleSetEditingPanel extends JPanel m_nameLabel = new JLabel("Name"); m_nameLabel.setFont(UIManager.getFont("labelFont")); m_nameLabel.setHorizontalAlignment(JLabel.RIGHT); + m_nameLabel.setOpaque(true); panel.add(m_nameLabel); // Rule Set Name Text m_name = new JTextField(); m_name.setFont(UIManager.getFont("dataFont")); - m_name.addFocusListener(new RuleSetNameFocusListener()); + m_name.addFocusListener(m_focusListener); m_name.setRequestFocusEnabled(true); + m_name.setOpaque(true); panel.add(m_name); // Rule Set Description Label m_descriptionLabel = new JLabel("Description"); m_descriptionLabel.setFont(UIManager.getFont("labelFont")); m_descriptionLabel.setHorizontalAlignment(JLabel.RIGHT); + m_descriptionLabel.setOpaque(true); panel.add(m_descriptionLabel); // Rule Set Description Text @@ -98,10 +104,12 @@ public class RuleSetEditingPanel extends JPanel m_includeLabel = new JLabel("Include"); m_includeLabel.setFont(UIManager.getFont("labelFont")); m_includeLabel.setHorizontalAlignment(JLabel.RIGHT); + m_includeLabel.setOpaque(true); panel.add(m_includeLabel); // Rule Set Active m_include = new JCheckBox(""); + m_include.setOpaque(true); panel.add(m_include); enableData(false); @@ -117,32 +125,81 @@ public class RuleSetEditingPanel extends JPanel { String ruleSetName = m_name.getText(); - if (ruleSetName.equalsIgnoreCase(m_originalName) == false) + if (ruleSetName.length() == 0) + { + String message = "The rule set name is missing. The change will not be applied."; + boolean hasFocus = m_name.hasFocus(); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + if (hasFocus) + { + m_name.requestFocus(); + } + + ruleSetName = m_originalName; + } + else if (ruleSetName.equalsIgnoreCase(m_originalName) == false) { if (m_currentData.getSibling(ruleSetName) != null) { + String template = "Another rule set already has the name \"{0}\". The change will not be applied."; + String[] args = {ruleSetName}; + String message = MessageFormat.format(template, args); + boolean hasFocus = m_name.hasFocus(); + + m_name.removeFocusListener(m_focusListener); + MessageDialog.show(getParentWindow(), message); + m_name.addFocusListener(m_focusListener); + + if (hasFocus) + { + m_name.requestFocus(); + } + ruleSetName = m_originalName; } - -// ((RulesEditor) getParentWindow()).validateTree(); } m_currentData.setName(ruleSetName); m_currentData.setDescription(m_description.getText()); m_currentData.setInclude(m_include.isSelected()); + enableData(false); } } /** ******************************************************************************* * - * @param data + * @param isEditing */ protected void setIsEditing(boolean isEditing) { m_isEditing = isEditing; } + /** + ******************************************************************************* + * + * @return + */ + protected boolean isEditing() + { + return m_isEditing; + } + + /** + ******************************************************************************* + * + * @return + */ + public IRulesEditingData getData() + { + return m_currentData; + } + /** ******************************************************************************* * @@ -150,7 +207,11 @@ public class RuleSetEditingPanel extends JPanel */ public void setData(IRulesEditingData data) { - if (data.isRuleSet()) + if (data == null) + { + enableData(false); + } + else if (data.isRuleSet()) { setData_(data); } @@ -198,6 +259,9 @@ public class RuleSetEditingPanel extends JPanel { if (enable) { + // Just to be sure the focus listener isn't set. + m_name.removeFocusListener(m_focusListener); + m_name.addFocusListener(m_focusListener); m_name.setEnabled(true); m_name.setBackground(Color.white); m_description.setEnabled(true); @@ -206,6 +270,8 @@ public class RuleSetEditingPanel extends JPanel } else { + m_name.removeFocusListener(m_focusListener); + Color background = UIManager.getColor("disabledTextBackground"); m_name.setText(""); diff --git a/pmd/src/net/sourceforge/pmd/swingui/RulesEditor.java b/pmd/src/net/sourceforge/pmd/swingui/RulesEditor.java index 55f44976f7..2ddcba997e 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RulesEditor.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RulesEditor.java @@ -30,6 +30,7 @@ import javax.swing.UIManager; import net.sourceforge.pmd.PMDDirectory; import net.sourceforge.pmd.PMDException; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleProperties; import net.sourceforge.pmd.RuleSet; /** @@ -106,7 +107,7 @@ class RulesEditor extends JDialog RulesTreeNode rootNode; ruleSets = loadRuleSets(); - m_tree = new RulesTree(); + m_tree = new RulesTree(this); rootNode = (RulesTreeNode) m_tree.getModel().getRoot(); for (int n1 = 0; n1 < ruleSets.length; n1++) @@ -179,7 +180,7 @@ class RulesEditor extends JDialog private void loadProperties(RulesTreeNode ruleNode) { Rule rule; - Properties properties; + RuleProperties properties; String[] propertyNames; Enumeration keys; int index; @@ -202,11 +203,13 @@ class RulesEditor extends JDialog { String propertyName; String propertyValue; + String propertyValueType; RulesTreeNode propertyNode; propertyName = propertyNames[n]; - propertyValue = (String) properties.getProperty(propertyName); - propertyNode = new RulesTreeNode(ruleNode, propertyName, propertyValue); + propertyValue = properties.getValue(propertyName); + propertyValueType = properties.getValueType(propertyName); + propertyNode = new RulesTreeNode(ruleNode, propertyName, propertyValue, propertyValueType); ruleNode.add(propertyNode); @@ -270,6 +273,16 @@ class RulesEditor extends JDialog return m_pmdViewer; } + /** + ******************************************************************************* + * + * @return + */ + protected RuleEditingTabbedPane getEditingTabbedPane() + { + return m_editingTabbedPane; + } + /** ******************************************************************************* @@ -436,23 +449,4 @@ class RulesEditor extends JDialog RulesEditor.this.setVisible(false); } } - - /** - ******************************************************************************* - ******************************************************************************* - ******************************************************************************* - */ - private class TreeNodeMenuPopup extends JPopupMenu - { - // Add rule set - // Remove rule set - // Activate Rule Set - // Deactivate Rule Set - // Add rule - // Activate Rule - // Deactivate Rule - // Remove Rule - // Add property - // Remove property - } } \ No newline at end of file diff --git a/pmd/src/net/sourceforge/pmd/swingui/RulesTree.java b/pmd/src/net/sourceforge/pmd/swingui/RulesTree.java index 8b779db981..d8330772e4 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RulesTree.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RulesTree.java @@ -8,6 +8,8 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.Point; import java.io.File; +import java.util.Arrays; +import java.util.Comparator; import java.util.Enumeration; import java.util.EventObject; @@ -24,6 +26,9 @@ import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import javax.swing.UIManager; +import net.sourceforge.pmd.RuleSet; + + /** * * @author Donald A. Leckie @@ -33,14 +38,19 @@ import javax.swing.UIManager; class RulesTree extends JTree { + private RulesEditor m_rulesEditor; + /** *************************************************************************** * + * @param rulesEditor */ - protected RulesTree() + protected RulesTree(RulesEditor rulesEditor) { super(new DefaultTreeModel(RulesTreeNode.createRootNode())); + m_rulesEditor = rulesEditor; + setRootVisible(true); setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED)); setCellRenderer(new TreeNodeRenderer()); @@ -73,6 +83,92 @@ class RulesTree extends JTree return (treePath == null) ? null : (RulesTreeNode) treePath.getLastPathComponent(); } + /** + *************************************************************************** + * + * @param event + */ + protected void sortChildren(RulesTreeNode parentNode) + { + if (parentNode != null) + { + int childCount = parentNode.getChildCount(); + RulesTreeNode[] treeNodes = new RulesTreeNode[childCount]; + boolean needToSort = false; + + for (int n = 0; n < childCount; n++) + { + treeNodes[n] = (RulesTreeNode) parentNode.getChildAt(n); + + if ((n > 0) && (needToSort == false)) + { + String previousNodeName = treeNodes[n - 1].getName(); + String currentNodeName = treeNodes[n].getName(); + + if (currentNodeName.compareToIgnoreCase(previousNodeName) < 0) + { + needToSort = true; + } + } + } + + if (needToSort) + { + Arrays.sort(treeNodes, new SortComparator()); + parentNode.removeAllChildren(); + + for (int n = 0; n < treeNodes.length; n++) + { + parentNode.add(treeNodes[n]); + } + + ((DefaultTreeModel) getModel()).reload(parentNode); + } + + for (int n = 0; n < treeNodes.length; n++) + { + treeNodes[n] = null; + } + } + } + + /** + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + */ + private class SortComparator implements Comparator + { + + /** + *************************************************************************** + * + * @param object1 + * @param object2 + * + * @return + */ + public int compare(Object object1, Object object2) + { + String name1 = ((RulesTreeNode) object1).getName(); + String name2 = ((RulesTreeNode) object2).getName(); + + return name1.compareToIgnoreCase(name2); + } + + /** + *************************************************************************** + * + * @param object + * + * @return + */ + public boolean equals(Object object) + { + return object == this; + } + } + /** ******************************************************************************* ******************************************************************************* @@ -81,7 +177,9 @@ class RulesTree extends JTree private class RulesTreeMouseListener extends MouseAdapter { + private JMenuItem m_addRuleSetMenuItem; private JMenuItem m_deleteRuleSetMenuItem; + private JMenuItem m_addRuleMenuItem; private JMenuItem m_deleteRuleMenuItem; private JMenuItem m_addPropertyMenuItem; private JMenuItem m_deletePropertyMenuItem; @@ -95,8 +193,15 @@ class RulesTree extends JTree { if (event.isPopupTrigger()) { - RulesTreeNode treeNode = RulesTree.this.getSelectedNode(); - JPopupMenu popupMenu = null; + Point location; + TreePath treePath; + RulesTreeNode treeNode; + JPopupMenu popupMenu; + + location = event.getPoint(); + treePath = RulesTree.this.getPathForLocation(location.x, location.y); + treeNode = (RulesTreeNode) treePath.getLastPathComponent(); + popupMenu = null; if (treeNode.isRoot()) { @@ -110,10 +215,13 @@ class RulesTree extends JTree { popupMenu = createRulePopupMenu(); } + else if (treeNode.isProperty()) + { + popupMenu = createPropertyPopupMenu(); + } if (popupMenu != null) { - Point location = event.getPoint(); popupMenu.show(RulesTree.this, location.x, location.y); } } @@ -128,7 +236,9 @@ class RulesTree extends JTree { JPopupMenu popupMenu = createPopupMenu(); + m_addRuleSetMenuItem.setEnabled(true); m_deleteRuleSetMenuItem.setEnabled(false); + m_addRuleMenuItem.setEnabled(false); m_deleteRuleMenuItem.setEnabled(false); m_addPropertyMenuItem.setEnabled(false); m_deletePropertyMenuItem.setEnabled(false); @@ -145,7 +255,9 @@ class RulesTree extends JTree { JPopupMenu popupMenu = createPopupMenu(); + m_addRuleSetMenuItem.setEnabled(false); m_deleteRuleSetMenuItem.setEnabled(true); + m_addRuleMenuItem.setEnabled(true); m_deleteRuleMenuItem.setEnabled(false); m_addPropertyMenuItem.setEnabled(false); m_deletePropertyMenuItem.setEnabled(false); @@ -162,7 +274,9 @@ class RulesTree extends JTree { JPopupMenu popupMenu = createPopupMenu(); + m_addRuleSetMenuItem.setEnabled(false); m_deleteRuleSetMenuItem.setEnabled(false); + m_addRuleMenuItem.setEnabled(false); m_deleteRuleMenuItem.setEnabled(true); m_addPropertyMenuItem.setEnabled(true); m_deletePropertyMenuItem.setEnabled(false); @@ -179,9 +293,11 @@ class RulesTree extends JTree { JPopupMenu popupMenu = createPopupMenu(); + m_addRuleSetMenuItem.setEnabled(false); m_deleteRuleSetMenuItem.setEnabled(false); + m_addRuleMenuItem.setEnabled(false); m_deleteRuleMenuItem.setEnabled(false); - m_addPropertyMenuItem.setEnabled(true); + m_addPropertyMenuItem.setEnabled(false); m_deletePropertyMenuItem.setEnabled(true); return popupMenu; @@ -196,12 +312,20 @@ class RulesTree extends JTree { JPopupMenu popupMenu = new JPopupMenu(); + m_addRuleSetMenuItem = new JMenuItem("Add Rule Set"); + m_addRuleSetMenuItem.addActionListener(new AddRuleSetActionListener()); + popupMenu.add(m_addRuleSetMenuItem); + m_deleteRuleSetMenuItem = new JMenuItem("Delete Rule Set"); m_deleteRuleSetMenuItem.addActionListener(new DeleteRuleSetActionListener()); popupMenu.add(m_deleteRuleSetMenuItem); popupMenu.add(new JSeparator()); + m_addRuleMenuItem = new JMenuItem("Add Rule"); + m_addRuleMenuItem.addActionListener(new AddRuleActionListener()); + popupMenu.add(m_addRuleMenuItem); + m_deleteRuleMenuItem = new JMenuItem("Delete Rule"); m_deleteRuleMenuItem.addActionListener(new DeleteRuleActionListener()); popupMenu.add(m_deleteRuleMenuItem); @@ -220,6 +344,19 @@ class RulesTree extends JTree } } + /** + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + */ + private class AddRuleSetActionListener implements ActionListener + { + + public void actionPerformed(ActionEvent event) + { + } + } + /** ******************************************************************************* ******************************************************************************* @@ -233,6 +370,19 @@ class RulesTree extends JTree } } + /** + ******************************************************************************* + ******************************************************************************* + ******************************************************************************* + */ + private class AddRuleActionListener implements ActionListener + { + + public void actionPerformed(ActionEvent event) + { + } + } + /** ******************************************************************************* ******************************************************************************* diff --git a/pmd/src/net/sourceforge/pmd/swingui/RulesTreeNode.java b/pmd/src/net/sourceforge/pmd/swingui/RulesTreeNode.java index 2ee5efcde5..f8aac546f7 100644 --- a/pmd/src/net/sourceforge/pmd/swingui/RulesTreeNode.java +++ b/pmd/src/net/sourceforge/pmd/swingui/RulesTreeNode.java @@ -23,6 +23,7 @@ class RulesTreeNode extends DefaultMutableTreeNode implements IRulesEditingData private String m_description; private String m_example; private String m_propertyValue; + private String m_propertyValueType; private byte m_flags; // Constant @@ -124,12 +125,16 @@ class RulesTreeNode extends DefaultMutableTreeNode implements IRulesEditingData * * @param name */ - protected RulesTreeNode(RulesTreeNode ruleNode, String propertyName, String propertyValue) + protected RulesTreeNode(RulesTreeNode ruleNode, + String propertyName, + String propertyValue, + String propertyValueType) { super(); m_name = trim(propertyName); m_propertyValue = trim(propertyValue); + m_propertyValueType = trim(propertyValueType); m_flags |= IS_PROPERTY; m_rule = ruleNode.getRule(); m_ruleSet = ((RulesTreeNode) ruleNode.getParent()).getRuleSet(); @@ -256,6 +261,16 @@ class RulesTreeNode extends DefaultMutableTreeNode implements IRulesEditingData return m_propertyValue; } + /** + *************************************************************************** + * + * @return + */ + public String getPropertyValueType() + { + return m_propertyValueType; + } + /** ******************************************************************************* * @@ -417,6 +432,16 @@ class RulesTreeNode extends DefaultMutableTreeNode implements IRulesEditingData setDisplayName(); } + /** + ************************************************************************** + * + * @param newName + */ + public void setPropertyValueType(String newValue) + { + m_propertyValueType = trim(newValue); + } + /** ************************************************************************** * @@ -466,7 +491,8 @@ class RulesTreeNode extends DefaultMutableTreeNode implements IRulesEditingData } else if (isProperty()) { - m_rule.addProperty(m_name, m_propertyValue); + m_rule.getProperties().setValue(m_name, m_propertyValue); + m_rule.getProperties().setValueType(m_name, m_propertyValueType); } }