package net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers; import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertySource; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.eclipse.ui.preferences.br.EditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.br.RuleSelection; import net.sourceforge.pmd.eclipse.ui.preferences.br.SizeChangeListener; import net.sourceforge.pmd.eclipse.ui.preferences.br.ValueChangeListener; import net.sourceforge.pmd.eclipse.ui.preferences.editors.BooleanEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.CharacterEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.DoubleEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.EnumerationEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.FileEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.FloatEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.IntegerEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MethodEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MultiEnumerationEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MultiIntegerEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MultiMethodEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MultiStringEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.MultiTypeEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.StringEditorFactory; import net.sourceforge.pmd.eclipse.ui.preferences.editors.TypeEditorFactory; import net.sourceforge.pmd.lang.rule.XPathRule; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; /** * * @author Brian Remedios */ public class PerRulePropertyPanelManager extends AbstractRulePanelManager implements SizeChangeListener { private FormArranger formArranger; private Composite composite; private ScrolledComposite sComposite; private int widgetRowCount; private List<String> unreferencedVariables; private static final int MaxWidgetHeight = 30; // TODO derive this instead public static final String ID = "perRuleProperties"; public static final Map<Class<?>, EditorFactory> editorFactoriesByPropertyType; static { Map<Class<?>, EditorFactory> factoriesByPropertyType = new HashMap<Class<?>, EditorFactory>(); factoriesByPropertyType.put(Boolean.class, BooleanEditorFactory.instance); factoriesByPropertyType.put(String.class, StringEditorFactory.instance); factoriesByPropertyType.put(Integer.class, IntegerEditorFactory.instance); factoriesByPropertyType.put(Float.class, FloatEditorFactory.instance); factoriesByPropertyType.put(Double.class, DoubleEditorFactory.instance); factoriesByPropertyType.put(Object.class, EnumerationEditorFactory.instance); factoriesByPropertyType.put(Character.class, CharacterEditorFactory.instance); factoriesByPropertyType.put(Class.class, TypeEditorFactory.instance); factoriesByPropertyType.put(Class[].class, MultiTypeEditorFactory.instance); factoriesByPropertyType.put(Method.class, MethodEditorFactory.instance); factoriesByPropertyType.put(Method[].class, MultiMethodEditorFactory.instance); factoriesByPropertyType.put(String[].class, MultiStringEditorFactory.instance); factoriesByPropertyType.put(Integer[].class, MultiIntegerEditorFactory.instance); factoriesByPropertyType.put(Object[].class, MultiEnumerationEditorFactory.instance); factoriesByPropertyType.put(File.class, FileEditorFactory.instance); // factoriesByPropertyType.put(Package.class, PackageEditorFactory.instance); editorFactoriesByPropertyType = Collections.unmodifiableMap(factoriesByPropertyType); } public PerRulePropertyPanelManager(String theTitle, EditorUsageMode theMode, ValueChangeListener theListener) { super(ID, theTitle, theMode, theListener); } protected boolean canManageMultipleRules() { return false; } protected boolean canWorkWith(Rule rule) { // TODO if (rule.hasDescriptor(XPathRule.XPATH_DESCRIPTOR)) return true; won't work, need to tweak Rule implementation as map is empty // alternate approach for now for (PropertyDescriptor<?> desc : rule.getPropertyDescriptors()) { if (desc.equals(XPathRule.XPATH_DESCRIPTOR)) return true; } return !Configuration.filteredPropertiesOf(rule).isEmpty(); } protected void clearControls() { formArranger.clearChildren(); } public void loadValues() { formArranger.loadValues(); } public void showControls(boolean flag) { clearControls(); } /* * We want to intercept this and update the tab if we detect problems after we pass it on.. */ private ValueChangeListener chainedListener() { return FormArranger.chain(changeListener, new ValueChangeListener() { public void changed(RuleSelection rule, PropertyDescriptor<?> desc, Object newValue) { updateUI(); } public void changed(PropertySource source, PropertyDescriptor<?> desc, Object newValue) { updateUI(); } } ); } public Control setupOn(Composite parent) { sComposite = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); composite = new Composite(sComposite, SWT.NONE); sComposite.setContent(composite); sComposite.setExpandHorizontal(true); sComposite.setExpandVertical(true); formArranger = new FormArranger(composite, editorFactoriesByPropertyType, chainedListener(), this); return sComposite; } public void addedRows(int rowCountDelta) { widgetRowCount += rowCountDelta; adjustMinimumHeight(); } private void adjustMinimumHeight() { sComposite.setMinSize(composite.computeSize(500, widgetRowCount * MaxWidgetHeight)); } protected void adapt() { widgetRowCount = formArranger.arrangeFor(soleRule()); validate(); if (widgetRowCount < 0) return; adjustMinimumHeight(); } public boolean validate() { if (!super.validate()) return false; unreferencedVariables = formArranger.updateDeleteButtons(); // any unref'd vars are not real errors return true; } protected List<String> fieldWarnings() { List<String> warnings = new ArrayList<String>(2); if (rules != null && !canManageMultipleRules()) { // TODO can do better Rule soleRule = soleRule(); if (soleRule != null) { String dysfunctionReason = soleRule.dysfunctionReason(); if (dysfunctionReason != null) { warnings.add(dysfunctionReason); } } } if (unreferencedVariables == null || unreferencedVariables.isEmpty()) { return warnings; } warnings.add("Unreferences variables: " + unreferencedVariables); return warnings; } }