package net.sourceforge.pmd.eclipse.ui.preferences.br; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.PropertySource; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.eclipse.runtime.preferences.IPreferences; import net.sourceforge.pmd.eclipse.runtime.preferences.impl.PreferenceUIStore; import net.sourceforge.pmd.eclipse.runtime.writer.IRuleSetWriter; import net.sourceforge.pmd.eclipse.runtime.writer.WriterException; import net.sourceforge.pmd.eclipse.ui.ColumnDescriptor; import net.sourceforge.pmd.eclipse.ui.PMDUiConstants; import net.sourceforge.pmd.eclipse.ui.nls.StringKeys; import net.sourceforge.pmd.eclipse.ui.preferences.RuleDupeChecker; import net.sourceforge.pmd.eclipse.ui.preferences.RuleSetSelectionDialog; import net.sourceforge.pmd.eclipse.ui.preferences.editors.SWTUtil; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.CreateRuleWizard; import net.sourceforge.pmd.eclipse.util.IOUtil; import net.sourceforge.pmd.eclipse.util.ResourceManager; import net.sourceforge.pmd.eclipse.util.Util; import net.sourceforge.pmd.util.FileUtil; import net.sourceforge.pmd.util.StringUtil; import net.sourceforge.pmd.util.designer.Designer; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ICheckStateProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; /** * Instantiates and manages a tree table widget holding all the rules in a ruleset. * * @author Brian Remedios */ public class RuleTableManager extends AbstractTreeTableManager<Rule> implements ValueChangeListener, RuleDupeChecker { private RuleSet ruleSet; private RuleColumnDescriptor groupingColumn; protected String groupColumnLabel; private RuleFieldAccessor checkedColumnAccessor; // private Map<RulePriority, MenuItem> priorityMenusByPriority; // private Map<String, MenuItem> rulesetMenusByName; private RuleSelection ruleSelection; // may hold rules and/or group nodes // private Menu ruleListMenu; private MenuItem useDefaultsItem; private Button addRuleButton; private Button removeRuleButton; private Button exportRuleSetButton; private RuleSelectionListener ruleSelectionListener; private ValueResetHandler resetHandler; public RuleTableManager(String theWidgetId, RuleColumnDescriptor[] theColumns, IPreferences thePreferences, ValueResetHandler aResetHandler) { super(theWidgetId, thePreferences, theColumns); columnSorter = RuleFieldAccessor.name; checkedColumnAccessor = createCheckedItemAccessor(); resetHandler = aResetHandler; } protected boolean isQualifiedItem(Object item) { return item instanceof Rule; } public List<Rule> activeRules() { Object[] checkedItems = treeViewer.getCheckedElements(); List<Rule> activeOnes = new ArrayList<Rule>(checkedItems.length); for (Object item : checkedItems) { if (isQualifiedItem(item)) { activeOnes.add((Rule)item); } } return activeOnes; } protected String nameFor(Object treeItemData) { return ((Rule)treeItemData).getName(); } public void selectionListener(RuleSelectionListener theListener) { ruleSelectionListener = theListener; } private RuleFieldAccessor createCheckedItemAccessor() { return new BasicRuleFieldAccessor() { public Comparable<Boolean> valueFor(Rule rule) { return isActive(rule.getName()); } }; } // private void addRulesetMenuOptions(Menu menu) { // // MenuItem rulesetMenu = new MenuItem(menu, SWT.CASCADE); // rulesetMenu.setText("Ruleset"); // Menu rulesetSubMenu = new Menu(menu); // rulesetMenu.setMenu(rulesetSubMenu); // rulesetMenusByName = new HashMap<String, MenuItem>(); // // MenuItem demoItem = new MenuItem(rulesetSubMenu, SWT.PUSH); // demoItem.setText("---demo only---"); // NO API to re-parent rules to other rulesets (yet) // // for (String rulesetName : rulesetNames()) { // MenuItem rulesetItem = new MenuItem(rulesetSubMenu, SWT.RADIO); // rulesetMenusByName.put(rulesetName, rulesetItem); // rulesetItem.setText(rulesetName); // final String rulesetStr = rulesetName; // rulesetItem.addSelectionListener( new SelectionAdapter() { // public void widgetSelected(SelectionEvent e) { // setRuleset(rulesetStr); // } // } // ); // } // } // private void adjustMenuPrioritySettings() { // // RulePriority priority = ruleSelection == null ? null : RuleUtil.commonPriority(ruleSelection); // Iterator<Map.Entry<RulePriority, MenuItem>> iter = priorityMenusByPriority.entrySet().iterator(); // // while (iter.hasNext()) { // Map.Entry<RulePriority, MenuItem> entry = iter.next(); // MenuItem item = entry.getValue(); // if (entry.getKey() == priority) { // item.setSelection(true); // item.setEnabled(false); // } else { // item.setSelection(false); // item.setEnabled(true); // } // } // } // if all the selected rules/ruleGroups reference a common ruleset name // then check that item and disable it, do the reverse for all others. // private void adjustMenuRulesetSettings() { // // String rulesetName = ruleSelection == null ? null : ruleSetNameFrom(RuleUtil.commonRuleset(ruleSelection)); // Iterator<Map.Entry<String, MenuItem>> iter = rulesetMenusByName.entrySet().iterator(); // // while (iter.hasNext()) { // Map.Entry<String, MenuItem> entry = iter.next(); // MenuItem item = entry.getValue(); // if (rulesetName == null) { // allow all entries if none or conflicting // item.setSelection(false); // item.setEnabled(true); // continue; // } // if (StringUtil.areSemanticEquals(entry.getKey(), rulesetName)) { // item.setSelection(true); // item.setEnabled(false); // } else { // item.setSelection(false); // item.setEnabled(true); // } // } // } protected void addTableSelectionOptions(Menu menu) { useDefaultsItem = new MenuItem(menu, SWT.PUSH); useDefaultsItem.setText("Use defaults"); // useDefaultsItem.setEnabled(false); useDefaultsItem.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { resetHandler.resetValuesIn(ruleSelection); } }); } protected void adjustTableMenuOptions() { boolean hasDefaults = ruleSelection.haveDefaultValues(); useDefaultsItem.setEnabled( ! hasDefaults ); } /** * Build the edit rule button * @param parent Composite * @return Button */ public Button buildAddRuleButton(final Composite parent) { Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_ADD, StringKeys.PREF_RULESET_BUTTON_ADDRULE); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { createRule(parent.getShell()); } }); return button; } private void createRule(Shell shell) { // RuleDialog dialog = new RuleDialog(parent.getShell()); // int result = dialog.open(); try { CreateRuleWizard wiz = new CreateRuleWizard(); WizardDialog dialog = new WizardDialog(shell, wiz); wiz.dialog(dialog); int result = dialog.open(); if (result != Window.OK) return; Rule addedRule = wiz.rule(); ruleSet.addRule(addedRule); added(addedRule); setModified(); try { refresh(); treeViewer.reveal(addedRule); } catch (Throwable t) { plugin.logError("Exception when refreshing the rule table", t); } } catch (Exception ex) { ex.printStackTrace(); } } /** * Build the remove rule button * @param parent Composite * @return Button */ public Button buildRemoveRuleButton(Composite parent) { Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_DELETE, StringKeys.PREF_RULESET_BUTTON_REMOVERULE); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { removeSelectedItems(); } }); return button; } protected void removeSelectedItems() { if (ruleSelection == null) return; int removeCount = ruleSelection.removeAllFrom(ruleSet); if (removeCount == 0) return; List<Rule> removedRules = ruleSelection.allRules(); for (Rule r : removedRules) { preferences.isActive(r.getName(), false); } removed(removedRules); setModified(); try { refresh(); } catch (Throwable t) { treeViewer.setSelection(null); } updateCheckControls(); } /** * Build the export rule set button * @param parent Composite * @return Button */ private Button buildExportRuleSetButton(final Composite parent) { Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_EXPORT, StringKeys.PREF_RULESET_BUTTON_EXPORTRULESET); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { exportSelectedRules(); } }); return button; } private void exportSelectedRules() { Shell shell = treeViewer.getTree().getShell(); FileDialog dialog = new FileDialog(shell, SWT.SAVE); dialog.setText("Export " + ruleSelection.allRules().size() + " rules"); String fileName = dialog.open(); if (StringUtil.isNotEmpty(fileName)) { try { exportTo(fileName, shell); } catch (Exception e) { plugin.showError(getMessage(StringKeys.ERROR_EXPORTING_RULESET), e); } } } private RuleSet ruleSelectionAsRuleSet() { RuleSet rs = new RuleSet(); rs.setName( ruleSet.getName() ); rs.setDescription( ruleSet.getDescription() ); rs.setFileName( ruleSet.getFileName()); rs.addExcludePatterns( ruleSet.getExcludePatterns() ); rs.addIncludePatterns( ruleSet.getIncludePatterns() ); for (Rule rule : ruleSelection.allRules()) { rs.addRule(rule); } return rs; } private void exportTo(String fileName, Shell shell) throws FileNotFoundException, WriterException, IOException { File file = new File(fileName); boolean flContinue = true; if (file.exists()) { flContinue = MessageDialog.openConfirm(shell, getMessage(StringKeys.CONFIRM_TITLE), getMessage(StringKeys.CONFIRM_RULESET_EXISTS)); } InputDialog input = null; RuleSet ruleSet = null; if (flContinue) { ruleSet = ruleSelectionAsRuleSet(); input = new InputDialog(shell, getMessage(StringKeys.PREF_RULESET_DIALOG_TITLE), getMessage(StringKeys.PREF_RULESET_DIALOG_RULESET_DESCRIPTION), ruleSet.getDescription() == null ? "" : ruleSet.getDescription().trim(), null); flContinue = input.open() == Window.OK; } if (flContinue) { OutputStream out = null; try { ruleSet.setName(FileUtil.getFileNameWithoutExtension(file.getName())); ruleSet.setDescription(input.getValue()); out = new FileOutputStream(fileName); IRuleSetWriter writer = plugin.getRuleSetWriter(); writer.write(out, ruleSet); } finally { IOUtil.closeQuietly(out); } MessageDialog.openInformation(shell, getMessage(StringKeys.INFORMATION_TITLE), getMessage(StringKeys.INFORMATION_RULESET_EXPORTED)); } } private RuleColumnDescriptor newDupeIndicatorColumn() { return new SimpleColumnDescriptor("a", "", SWT.CENTER, 35, null, false, null) { public String stringValueFor(Rule rule) { return isDuplicate(rule) ? "X" : ""; } public Image imageFor(Rule rule) { return null; } }; } private RuleColumnDescriptor[] ruleImportColumns() { return new RuleColumnDescriptor[] { newDupeIndicatorColumn(), new SimpleColumnDescriptor("a", RuleTableColumns.name.label(), SWT.LEFT, 210, RuleTableColumns.name.accessor(), true, null), new SimpleColumnDescriptor("a", RuleTableColumns.language.label(), SWT.LEFT, 40, RuleTableColumns.language.accessor(), true, null), }; } /** * Build the import ruleset button * @param parent Composite * @return Button */ private Button buildImportRuleSetButton(final Composite parent) { Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_IMPORT, StringKeys.PREF_RULESET_BUTTON_IMPORTRULESET); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { RuleColumnDescriptor[] rcd = ruleImportColumns(); RuleSetSelectionDialog dialog = new RuleSetSelectionDialog(parent.getShell(), "Import rules", rcd, RuleTableManager.this); dialog.open(); if (dialog.getReturnCode() == Window.OK) { doImport(dialog.checkedRules(), dialog.isImportByReference()); } } }); return button; } public static boolean areSemanticEquals(Rule a, Rule b) { return a.getName().equals(b.getName()) && a.getLanguage().equals(b.getLanguage()); } /** * Return whether adding the rule arg to the ruleset would * constitute a duplicate or now. * * @param rule * @return */ public boolean isDuplicate(Rule otherRule) { for (Rule rule : ruleSet.getRules()) { if (areSemanticEquals(rule, otherRule)) return true; } return false; } private void add(RuleSet incomingRuleSet) { Iterator<Rule> iter = incomingRuleSet.getRules().iterator(); while (iter.hasNext()) { Rule rule = iter.next(); ruleSet.addRule(rule); rule.setRuleSetName(ruleSet.getName()); added(rule); } ruleSet.addIncludePatterns( incomingRuleSet.getIncludePatterns() ); ruleSet.addExcludePatterns( incomingRuleSet.getExcludePatterns() ); } private void doImport(RuleSet selectedRuleSet, boolean doByReference) { try { if (doByReference) { RuleSet filteredRS = new RuleSet(); filteredRS.setFileName(selectedRuleSet.getFileName()); for (Rule rule : selectedRuleSet.getRules()) { filteredRS.addRule(rule); } ruleSet.addRuleSetByReference(filteredRS, false); ruleSet.addIncludePatterns(selectedRuleSet.getIncludePatterns()); ruleSet.addExcludePatterns(selectedRuleSet.getExcludePatterns()); } else { add(selectedRuleSet); } setModified(); try { refresh(); } catch (Throwable t) { plugin.logError("Exception when refreshing the rule table", t); } } catch (RuntimeException e) { plugin.showError(getMessage(StringKeys.ERROR_IMPORTING_RULESET), e); } updateCheckControls(); } public Composite buildGroupCombo(Composite parent, String comboLabelKey, final Object[][] groupingChoices) { Composite panel = new Composite(parent, 0); GridLayout layout = new GridLayout(6, false); panel.setLayout(layout); buildCheckButtons(panel); Label label = new Label(panel, 0); GridData data = new GridData(); data.horizontalAlignment = SWT.LEFT; data.verticalAlignment = SWT.CENTER; label.setLayoutData(data); label.setText(SWTUtil.stringFor(comboLabelKey)); final Combo combo = new Combo(panel, SWT.READ_ONLY); combo.setItems(SWTUtil.i18lLabelsIn(groupingChoices, 1)); combo.select(groupingChoices.length - 1); // picks last one by default TODO make it a persistent preference combo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int selectionIdx = combo.getSelectionIndex(); Object[] choice = groupingChoices[selectionIdx]; groupingColumn = (RuleColumnDescriptor)choice[0]; redrawTable(); } }); buildActiveCountWidgets(panel); return panel; } /** * Build the Rule Designer button * @param parent Composite * @return Button */ private Button buildRuleDesignerButton(Composite parent) { Button button = newImageButton(parent, PMDUiConstants.ICON_BUTTON_EDITOR, StringKeys.PREF_RULESET_BUTTON_RULEDESIGNER); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { // TODO Is this cool from Eclipse? Is there a nicer way to spawn a J2SE Application? new Thread(new Runnable() { public void run() { Designer.main(new String[] { "-noexitonclose" }); } }).start(); } }); return button; } /** * Create buttons for rule table management * @param parent Composite * @return Composite */ public Composite buildRuleTableButtons(Composite parent) { Composite composite = new Composite(parent, SWT.NULL); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 1; gridLayout.verticalSpacing = 3; composite.setLayout(gridLayout); addRuleButton = buildAddRuleButton(composite); removeRuleButton = buildRemoveRuleButton(composite); Button importRuleSetButton = buildImportRuleSetButton(composite); exportRuleSetButton = buildExportRuleSetButton(composite); Button ruleDesignerButton = buildRuleDesignerButton(composite); GridData data = new GridData(); addRuleButton.setLayoutData(data); data = new GridData(); importRuleSetButton.setLayoutData(data); data = new GridData(); exportRuleSetButton.setLayoutData(data); data = new GridData(); data.horizontalAlignment = GridData.FILL; data.grabExcessVerticalSpace = true; data.verticalAlignment = GridData.END; ruleDesignerButton.setLayoutData(data); return composite; } protected boolean hasIssue(TreeItem item) { Object data = item.getData(); return data instanceof Rule && ((Rule)data).dysfunctionReason() != null; } protected void addIssueStyler(final Tree tree) { final Display display = tree.getDisplay(); final Color issueColor = display.getSystemColor(SWT.COLOR_YELLOW); tree.addListener(SWT.EraseItem, new Listener() { public void handleEvent(Event event) { // event.detail &= ~SWT.HOT; // // GC gc = event.gc; // // gc.setAdvanced(true); // if (gc.getAdvanced()) gc.setAlpha(127); // Rectangle rect = event.getBounds(); // Color foreground = gc.getForeground(); // Color background = gc.getBackground(); // // TreeItem item = (TreeItem)event.item; // // if (hasIssue(item)) { // gc.setBackground(issueColor); // gc.setForeground(issueColor); // } else { // // gc.setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND)); // } // // gc.setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND)); // gc.fillRectangle(event.x, rect.y, rect.width, rect.height); // gc.setForeground(display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); // // gc.setForeground(foreground); // restore colors for subsequent drawing // gc.setBackground(background); // event.detail &= ~SWT.SELECTED; } }); } /** * Build rule table viewer * @param parent Composite * @return Tree */ public Tree buildRuleTreeViewer(Composite parent) { buildTreeViewer(parent); final Tree ruleTree = treeViewer.getTree(); // ruleListMenu = createMenuFor(ruleTree); // ruleTree.setMenu(ruleListMenu); // ruleTree.addListener(SWT.MenuDetect, new Listener () { // public void handleEvent (Event event) { // popupRuleSelectionMenu(event); // } // }); addIssueStyler(treeViewer.getTree()); treeViewer.setCheckStateProvider(createCheckStateProvider()); return ruleTree; } public void changed(PropertySource source, PropertyDescriptor<?> desc, Object newValue) { // TODO enhance to recognize default values // RuleUtil.modifiedPropertiesIn(rule); treeViewer.update(source, null); setModified(); } public void changed(RuleSelection selection, PropertyDescriptor<?> desc, Object newValue) { // TODO enhance to recognize default values for (Rule rule : selection.allRules()) { if (newValue != null) { // non-reliable update behaviour, alternate trigger option - weird treeViewer.getTree().redraw(); // System.out.println("doing redraw"); } else { treeViewer.update(rule, null); // System.out.println("viewer update"); } } setModified(); } private void checkSelections() { // List<Rule> activeRules = new ArrayList<Rule>(); // // for (Rule rule : ruleSet.getRules()) { // if (preferences.isActive(rule.getName())) { // activeRules.add(rule); // } // } // // ruleTreeViewer.setCheckedElements(activeRules.toArray()); } // protected String[] columnLabels() { // String[] names = new String[availableColumns.length]; // for (int i=0; i<availableColumns.length; i++) { // names[i] = availableColumns[i].label(); // } // return names; // } private ICheckStateProvider createCheckStateProvider() { return new ICheckStateProvider() { public boolean isChecked(Object item) { if (item instanceof Rule) { return isActive(((Rule)item).getName()); } else { if (item instanceof RuleGroup) { SelectionStats stats = selectionRatioIn(((RuleGroup)item).rules()); return (stats.selectedCount > 0) && stats.allSelected(); } } return false; // should never get here } public boolean isGrayed(Object item) { if (item instanceof Rule) return false; if (item instanceof RuleGroup) { SelectionStats stats = selectionRatioIn(((RuleGroup)item).rules()); return (stats.selectedCount > 0) && (!stats.allSelected()); } return false; } }; } // private Menu createMenuFor(Control control) { // // Menu menu = new Menu(control); // // MenuItem priorityMenu = new MenuItem (menu, SWT.CASCADE); // priorityMenu.setText(SWTUtil.stringFor(StringKeys.MSGKEY_PREF_RULESET_COLUMN_PRIORITY)); // Menu subMenu = new Menu(menu); // priorityMenu.setMenu (subMenu); // priorityMenusByPriority = new HashMap<RulePriority, MenuItem>(RulePriority.values().length); // // for (RulePriority priority : RulePriority.values()) { // MenuItem priorityItem = new MenuItem (subMenu, SWT.RADIO); // priorityMenusByPriority.put(priority, priorityItem); // priorityItem.setText(priority.getName()); // TODO need to internationalize? // // priorityItem.setImage(imageFor(priority)); not visible with radiobuttons // final RulePriority pri = priority; // priorityItem.addSelectionListener( new SelectionAdapter() { // public void widgetSelected(SelectionEvent e) { // setPriority(pri); // } // } // ); // } // // MenuItem hideItem = new MenuItem(menu, SWT.PUSH); // hideItem.setText("Hide"); // hideItem.addSelectionListener(new SelectionAdapter() { // public void widgetSelected(SelectionEvent event) { // toggleColumnVisiblity("??"); // TODO // } // }); // hideItem.setEnabled(false); // // useDefaultsItem = new MenuItem(menu, SWT.PUSH); // useDefaultsItem.setText("Use defaults"); // useDefaultsItem.setEnabled(false); // useDefaultsItem.addSelectionListener(new SelectionAdapter() { // public void widgetSelected(SelectionEvent event) { // ruleSelection.useDefaultValues(); // } // }); // // return menu; // } /** * Method groupBy. * @param chosenColumn RuleColumnDescriptor */ public void groupBy(RuleColumnDescriptor chosenColumn) { groupColumnLabel = chosenColumn == null ? null : chosenColumn.label(); List<ColumnDescriptor> visibleColumns = new ArrayList<ColumnDescriptor>(availableColumns.length); for (ColumnDescriptor desc : availableColumns) { if (desc == chosenColumn) continue; // redundant, don't include it if (isHidden(desc)) continue; visibleColumns.add(desc); } setupTreeColumns( visibleColumns.toArray(new RuleColumnDescriptor[visibleColumns.size()]), chosenColumn == null ? null : chosenColumn.accessor() ); selectedItems(new Object[0]); // selections are killed by grouping } // private boolean hasPriorityGrouping() { // return // groupingColumn == TextColumnDescriptor.priorityName || // groupingColumn == TextColumnDescriptor.priority; // } private String labelFor(TreeColumn tc) { return groupColumnLabel == null ? tc.getText() : groupColumnLabel + " / " + tc.getText(); } /** * Populate the rule table */ public void populateRuleTable() { treeViewer.setInput(ruleSet); checkSelections(); restoreSavedRuleSelections(); updateCheckControls(); } // private void popupRuleSelectionMenu(Event event) { // // // have to do it here or else the ruleset var is null in the menu setup - timing issue //// if (rulesetMenusByName == null) { // // addRulesetMenuOptions(ruleListMenu); // // new MenuItem(ruleListMenu, SWT.SEPARATOR); // // addColumnSelectionOptions(ruleListMenu); //// } // // // adjustMenuPrioritySettings(); //// adjustMenuRulesetSettings(); //// adjustMenuUseDefaultsOption(); //// ruleListMenu.setLocation(event.x, event.y); //// ruleListMenu.setVisible(true); // } protected void redrawTable(String sortColumnLabel, int sortDir) { groupBy(groupingColumn); // In order to be able to use TreeItem.getItems() later, we need to expand all and collapse again. // Use TreeItem.getItems(). Note that sub items are only available if the parent node has been expanded at least once. // from: http://stackoverflow.com/questions/9766476/accessing-subitem-of-a-tree-in-swt-eclipse treeViewer.expandAll(); treeViewer.collapseAll(); super.redrawTable(sortColumnLabel, sortDir); } private void restoreSavedRuleSelections() { Set<String> names = PreferenceUIStore.instance.selectedRuleNames(); List<Rule> rules = new ArrayList<Rule>(); for (String name : names) rules.add(ruleSet.getRuleByName(name)); IStructuredSelection selection = new StructuredSelection(rules); treeViewer.setSelection(selection); } public RuleSet ruleSet() { return ruleSet; } // private String[] rulesetNames() { // // Set<String> names = new HashSet<String>(); // for (Rule rule : ruleSet.getRules()) { // names.add(ruleSetNameFrom(rule)); // if we strip out the 'Rules' portions then we don't get matches...need to rename rulesets // } // return names.toArray(new String[names.size()]); // } protected void saveItemSelections() { IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection(); List<String> ruleNames = new ArrayList<String>(); for (Object item : selection.toList()) { if (item instanceof Rule) ruleNames.add(((Rule)item).getName()); } PreferenceUIStore.instance.selectedRuleNames(ruleNames); } /** * @param item Object[] */ protected void selectedItems(Object[] items) { ruleSelection = new RuleSelection(items); if (ruleSelectionListener != null) { ruleSelectionListener.selection(ruleSelection); } boolean hasSelections = items.length > 0; if (removeRuleButton != null) removeRuleButton.setEnabled(hasSelections); if (exportRuleSetButton != null) exportRuleSetButton.setEnabled(hasSelections); } private class SelectionStats { public int selectedCount; public int totalCount; public int dysfunctionCount; public SelectionStats(int theSelectedCount, int theTotalCount, int theDysfunctionCount) { selectedCount = theSelectedCount; totalCount = theTotalCount; dysfunctionCount = theDysfunctionCount; } public boolean allSelected() { return selectedCount == totalCount; } } private SelectionStats selectionRatioIn(Rule[] rules) { int selectedCount = 0; int dysfunctionCount = 0; for (Rule rule : rules) { if (isActive(rule.getName())) { selectedCount++; if (StringUtil.isNotEmpty(rule.dysfunctionReason())) dysfunctionCount++; } } return new SelectionStats(selectedCount, rules.length, dysfunctionCount) ; } protected void setAllItemsActive() { Collection<Rule> rules = ruleSet.getRules(); Rule[] rulesArray = rules.toArray(new Rule[rules.size()]); Set<String> activeRules = new HashSet<String>(); for (int i = 0; i < rulesArray.length; i++) { activeRules.add(rulesArray[i].getName()); } // set all active rules preferences.setActiveRuleNames(activeRules); treeViewer().setCheckedElements(rulesArray); updateCheckControls(); setModified(); } // private void setPriority(RulePriority priority) { // // if (ruleSelection == null) return; // // ruleSelection.setPriority(priority); // // if (hasPriorityGrouping()) { // redrawTable(); // } else { // treeViewer.update(ruleSelection.allRules().toArray(), null); // } // // setModified(); // } // private void setRuleset(String rulesetName) { // // TODO - awaiting support in PMD itself // } /** * * @param columnDescs RuleColumnDescriptor[] * @param groupingField RuleFieldAccessor */ private void setupTreeColumns(RuleColumnDescriptor[] columnDescs, RuleFieldAccessor groupingField) { Tree ruleTree = cleanupRuleTree(); createCheckBoxColumn(ruleTree); for (int i=0; i<columnDescs.length; i++) { TreeColumn tc =columnDescs[i].newTreeColumnFor(ruleTree, i+1, this, paintListeners()); if (i==0 && groupingColumn != null) { tc.setText( labelFor(tc) ); } } treeViewer.setLabelProvider(new RuleLabelProvider(columnDescs)); treeViewer.setContentProvider( new RuleSetTreeItemProvider(groupingField, "??", Util.comparatorFrom(columnSorter(), sortDescending)) ); treeViewer.setInput(ruleSet); checkSelections(); TreeColumn[] columns = ruleTree.getColumns(); for (TreeColumn column : columns) column.pack(); } private RuleFieldAccessor columnSorter() { return (RuleFieldAccessor)columnSorter; } protected void sortByCheckedItems() { sortBy(checkedColumnAccessor, treeViewer.getTree().getColumn(0)); } public void useRuleSet(RuleSet theSet) { ruleSet = theSet; } private boolean activeRulesHaveIssues(Rule[] rules) { for (Rule rule : rules) { if (isActive(rule.getName()) && StringUtil.isNotEmpty(rule.dysfunctionReason())) return true; } return false; } protected void updateCheckControls() { Rule[] rules = new Rule[ruleSet.size()]; rules = ruleSet.getRules().toArray(rules); SelectionStats stats = selectionRatioIn(rules); boolean hasIssues = stats.dysfunctionCount > 0; updateButtonsFor(stats.selectedCount, stats.totalCount); String label = SWTUtil.stringFor(StringKeys.PREF_RULESET_ACTIVE_RULE_COUNT); activeCountDetails( label + " " + activeItemCount() + " / " + ruleSet.size(), hasIssues ? ResourceManager.imageFor(PMDUiConstants.ICON_WARN) : null ); } protected void updateTooltipFor(TreeItem item, int columnIndex) { RuleLabelProvider provider = (RuleLabelProvider)treeViewer.getLabelProvider(); String txt = provider.getDetailText(item.getData(), columnIndex); treeViewer.getTree().setToolTipText(txt); } }