Java tutorial
/******************************************************************************* * Copyright (c) 2010 Andrey Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * Contributor: Andrey Loskutov - initial API and implementation *******************************************************************************/ package de.loskutov.eclipse.jdepend.preferences; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.StringTokenizer; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModel; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.ui.ISharedImages; import org.eclipse.jdt.ui.JavaElementLabelProvider; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; 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.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.dialogs.ElementListSelectionDialog; import org.eclipse.ui.model.WorkbenchViewerComparator; import de.loskutov.eclipse.jdepend.JDepend4EclipsePlugin; import de.loskutov.eclipse.jdepend.JDependConstants; public final class JDependPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { private static final String DEFAULT_NEW_FILTER_TEXT = ""; //$NON-NLS-1$ // filter widgets protected CheckboxTableViewer fFilterViewer; protected Table fFilterTable; protected Button fUseFiltersCheckbox; // private Button fUseSourcesCheckbox; protected Button fUseAllCyclesSearchCheckbox; protected Button saveAsXml; protected Button askBeforeSave; protected Button fAddPackageButton; protected Button fRemoveFilterButton; protected Button fAddFilterButton; protected Button fEnableAllButton; protected Button fDisableAllButton; protected Text fEditorText; protected String fInvalidEditorText = null; protected TableEditor fTableEditor; protected TableItem fNewTableItem; protected Filter fNewStepFilter; protected Label fTableLabel; protected FilterContentProvider fStepFilterContentProvider; public JDependPreferencePage() { super(); setPreferenceStore(JDepend4EclipsePlugin.getDefault().getPreferenceStore()); setDescription(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Options_for_JDepend")); //$NON-NLS-1$ } protected static Composite createContainer(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; composite.setLayout(layout); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL); gridData.grabExcessHorizontalSpace = true; composite.setLayoutData(gridData); return composite; } @Override protected Control createContents(Composite parent) { TabFolder tabFolder = new TabFolder(parent, SWT.TOP); tabFolder.setLayout(new GridLayout(1, true)); tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH)); TabItem tabFilter = new TabItem(tabFolder, SWT.NONE); tabFilter.setText("Filters"); Group defPanel = new Group(tabFolder, SWT.NONE); defPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); defPanel.setLayout(new GridLayout(1, false)); defPanel.setText("Search Filters"); tabFilter.setControl(defPanel); TabItem support = new TabItem(tabFolder, SWT.NONE); support.setText("Misc..."); Composite supportPanel = createContainer(tabFolder); support.setControl(supportPanel); SupportPanel.createSupportLinks(supportPanel); createFilterPreferences(defPanel); return tabFolder; } /** * @see IWorkbenchPreferencePage#init(IWorkbench) */ @Override public void init(IWorkbench workbench) { /** ignored */ } /** * Create a group to contain the step filter related widgetry */ private void createFilterPreferences(Composite parent) { // top level container Composite container = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginHeight = 0; layout.marginWidth = 0; container.setLayout(layout); GridData gd = new GridData(GridData.FILL_BOTH); container.setLayoutData(gd); // use filters checkbox fUseFiltersCheckbox = new Button(container, SWT.CHECK); fUseFiltersCheckbox .setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Use_package_filters")); //$NON-NLS-1$ fUseFiltersCheckbox.setToolTipText("Default is true"); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; fUseFiltersCheckbox.setLayoutData(gd); fUseFiltersCheckbox.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent se) { toggleFilterWidgetsEnabled(fUseFiltersCheckbox.getSelection()); } @Override public void widgetDefaultSelected(SelectionEvent se) { /** ignored */ } }); fUseAllCyclesSearchCheckbox = new Button(container, SWT.CHECK); fUseAllCyclesSearchCheckbox.setText(JDepend4EclipsePlugin .getResourceString("JDependPreferencePage.Use_more_comprehensive_cycles_search")); //$NON-NLS-1$ fUseAllCyclesSearchCheckbox.setToolTipText("Default is true"); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; fUseAllCyclesSearchCheckbox.setLayoutData(gd); saveAsXml = new Button(container, SWT.CHECK); saveAsXml.setText(JDepend4EclipsePlugin.getResourceString("Save as XML (and not as plain text)")); //$NON-NLS-1$ saveAsXml.setToolTipText("JDepend output can be saved as XML or plain text, default is XML"); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; saveAsXml.setLayoutData(gd); askBeforeSave = new Button(container, SWT.CHECK); askBeforeSave.setText(JDepend4EclipsePlugin.getResourceString("Ask before save")); //$NON-NLS-1$ askBeforeSave.setToolTipText("Default is true"); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; askBeforeSave.setLayoutData(gd); askBeforeSave.addSelectionListener(new SelectionListener() { @Override public void widgetSelected(SelectionEvent se) { saveAsXml.setEnabled(!askBeforeSave.getSelection()); } @Override public void widgetDefaultSelected(SelectionEvent se) { /** ignored */ } }); //table label fTableLabel = new Label(container, SWT.NONE); fTableLabel .setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Defined_package_filters")); //$NON-NLS-1$ gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; fTableLabel.setLayoutData(gd); fFilterTable = new Table(container, SWT.CHECK | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER); fFilterTable.setHeaderVisible(true); // fFilterTable.setLinesVisible(true); fFilterTable.setLayoutData(new GridData(GridData.FILL_BOTH)); TableLayout tlayout = new TableLayout(); tlayout.addColumnData(new ColumnWeightData(100, 200)); fFilterTable.setLayout(tlayout); TableColumn tableCol = new TableColumn(fFilterTable, SWT.LEFT); tableCol.setResizable(true); tableCol.setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Enable_disable_package")); //$NON-NLS-1$ fFilterViewer = new CheckboxTableViewer(fFilterTable); fTableEditor = new TableEditor(fFilterTable); fFilterViewer.setLabelProvider(new FilterLabelProvider()); fFilterViewer.setComparator(new FilterViewerSorter()); fStepFilterContentProvider = new FilterContentProvider(fFilterViewer); fFilterViewer.setContentProvider(fStepFilterContentProvider); //@todo table width input just needs to be non-null fFilterViewer.setInput(this); fFilterViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStateChanged(CheckStateChangedEvent event) { Filter filter = (Filter) event.getElement(); fStepFilterContentProvider.toggleFilter(filter); } }); fFilterViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (selection.isEmpty()) { fRemoveFilterButton.setEnabled(false); } else { fRemoveFilterButton.setEnabled(true); } } }); createFilterButtons(container); boolean enabled = getPreferenceStore().getBoolean(JDependConstants.PREF_USE_FILTERS); fUseFiltersCheckbox.setSelection(enabled); toggleFilterWidgetsEnabled(enabled); enabled = getPreferenceStore().getBoolean(JDependConstants.PREF_USE_ALL_CYCLES_SEARCH); fUseAllCyclesSearchCheckbox.setSelection(enabled); enabled = getPreferenceStore().getBoolean(JDependConstants.SAVE_TO_SHOW_OPTIONS); askBeforeSave.setSelection(enabled); enabled = getPreferenceStore().getBoolean(JDependConstants.SAVE_AS_XML); saveAsXml.setSelection(enabled); saveAsXml.setEnabled(!askBeforeSave.getSelection()); } private void createFilterButtons(Composite container) { // button container Composite buttonContainer = new Composite(container, SWT.NONE); GridData gd = new GridData(GridData.FILL_VERTICAL); buttonContainer.setLayoutData(gd); GridLayout buttonLayout = new GridLayout(); buttonLayout.numColumns = 1; buttonLayout.marginHeight = 0; buttonLayout.marginWidth = 0; buttonContainer.setLayout(buttonLayout); // Add filter button fAddFilterButton = new Button(buttonContainer, SWT.PUSH); fAddFilterButton.setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Add_filter")); //$NON-NLS-1$ fAddFilterButton.setToolTipText(JDepend4EclipsePlugin .getResourceString("JDependPreferencePage.Key_in_the_name_of_a_new_package_filter")); //$NON-NLS-1$ gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING); fAddFilterButton.setLayoutData(gd); fAddFilterButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event e) { editFilter(); } }); // Add package button fAddPackageButton = new Button(buttonContainer, SWT.PUSH); fAddPackageButton.setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Add_package")); //$NON-NLS-1$ fAddPackageButton.setToolTipText(JDepend4EclipsePlugin .getResourceString("JDependPreferencePage.Choose_a_package_and_add_it_to_package_filters")); //$NON-NLS-1$ gd = getButtonGridData(fAddPackageButton); fAddPackageButton.setLayoutData(gd); fAddPackageButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event e) { addPackage(); } }); // Remove button fRemoveFilterButton = new Button(buttonContainer, SWT.PUSH); fRemoveFilterButton.setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Remove")); //$NON-NLS-1$ fRemoveFilterButton.setToolTipText(JDepend4EclipsePlugin .getResourceString("JDependPreferencePage.Remove_all_selected_package_filters")); //$NON-NLS-1$ gd = getButtonGridData(fRemoveFilterButton); fRemoveFilterButton.setLayoutData(gd); fRemoveFilterButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event e) { removeFilters(); } }); fRemoveFilterButton.setEnabled(false); fEnableAllButton = new Button(buttonContainer, SWT.PUSH); fEnableAllButton.setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Enable_all")); //$NON-NLS-1$ fEnableAllButton.setToolTipText( JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Enables_all_package_filters")); //$NON-NLS-1$ gd = getButtonGridData(fEnableAllButton); fEnableAllButton.setLayoutData(gd); fEnableAllButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event e) { checkAllFilters(true); } }); fDisableAllButton = new Button(buttonContainer, SWT.PUSH); fDisableAllButton.setText(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Disable_all")); //$NON-NLS-1$ fDisableAllButton.setToolTipText( JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Disables_all_package_filters")); //$NON-NLS-1$ gd = getButtonGridData(fDisableAllButton); fDisableAllButton.setLayoutData(gd); fDisableAllButton.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event e) { checkAllFilters(false); } }); } protected void toggleFilterWidgetsEnabled(boolean enabled) { fFilterViewer.getTable().setEnabled(enabled); fAddPackageButton.setEnabled(enabled); fAddFilterButton.setEnabled(enabled); if (!enabled) { fRemoveFilterButton.setEnabled(enabled); } else if (!fFilterViewer.getSelection().isEmpty()) { fRemoveFilterButton.setEnabled(true); } } private GridData getButtonGridData(Button button) { GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING); GC gc = new GC(button); gc.setFont(button.getFont()); FontMetrics fontMetrics = gc.getFontMetrics(); gc.dispose(); int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics, IDialogConstants.BUTTON_WIDTH); gd.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); gd.heightHint = Dialog.convertVerticalDLUsToPixels(fontMetrics, IDialogConstants.BUTTON_HEIGHT); return gd; } protected void checkAllFilters(boolean check) { Object[] filters = fStepFilterContentProvider.getElements(null); for (int i = 0; i != filters.length; i++) { ((Filter) filters[i]).setChecked(check); } fFilterViewer.setAllChecked(check); } /** * Create a new filter in the table (with the default 'new filter' value), * then open up an in-place editor on it. */ protected void editFilter() { // if a previous edit is still in progress, finish it if (fEditorText != null) { validateChangeAndCleanup(); } fNewStepFilter = fStepFilterContentProvider.addFilter(DEFAULT_NEW_FILTER_TEXT, true); fNewTableItem = fFilterTable.getItem(0); // create & configure Text widget for editor // Fix for bug 1766. Border behavior on for text fields varies per platform. // On Motif, you always get a border, on other platforms, // you don't. Specifying a border on Motif results in the characters // getting pushed down so that only there very tops are visible. Thus, // we have to specify different style constants for the different platforms. int textStyles = SWT.SINGLE | SWT.LEFT; if (!SWT.getPlatform().equals("motif")) { //$NON-NLS-1$ textStyles |= SWT.BORDER; } fEditorText = new Text(fFilterTable, textStyles); GridData gd = new GridData(GridData.FILL_BOTH); fEditorText.setLayoutData(gd); // set the editor fTableEditor.horizontalAlignment = SWT.LEFT; fTableEditor.grabHorizontal = true; fTableEditor.setEditor(fEditorText, fNewTableItem, 0); // get the editor ready to use fEditorText.setText(fNewStepFilter.getName()); fEditorText.selectAll(); setEditorListeners(fEditorText); fEditorText.setFocus(); } private void setEditorListeners(Text text) { // CR means commit the changes, ESC means abort and don't commit text.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent event) { if (event.character == SWT.CR) { if (fInvalidEditorText != null) { fEditorText.setText(fInvalidEditorText); fInvalidEditorText = null; } else { validateChangeAndCleanup(); } } else if (event.character == SWT.ESC) { removeNewFilter(); cleanupEditor(); } } }); // Consider loss of focus on the editor to mean the same as CR text.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent event) { if (fInvalidEditorText != null) { fEditorText.setText(fInvalidEditorText); fInvalidEditorText = null; } else { validateChangeAndCleanup(); } } }); // Consume traversal events from the text widget so that CR doesn't // traverse away to dialog's default button. Without this, hitting // CR in the text field closes the entire dialog. text.addListener(SWT.Traverse, new Listener() { @Override public void handleEvent(Event event) { event.doit = false; } }); } protected void validateChangeAndCleanup() { String trimmedValue = fEditorText.getText().trim(); // if the new value is blank, remove the filter if (trimmedValue.length() < 1) { removeNewFilter(); } // if it's invalid, beep and leave sitting in the editor else if (!validateEditorInput(trimmedValue)) { fInvalidEditorText = trimmedValue; fEditorText.setText( JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Invalid_package_filter")); //$NON-NLS-1$ getShell().getDisplay().beep(); return; // otherwise, commit the new value if not a duplicate } else { Object[] filters = fStepFilterContentProvider.getElements(null); for (int i = 0; i < filters.length; i++) { Filter filter = (Filter) filters[i]; if (filter.getName().equals(trimmedValue)) { removeNewFilter(); cleanupEditor(); return; } } fNewTableItem.setText(trimmedValue); fNewStepFilter.setName(trimmedValue); fFilterViewer.refresh(); } cleanupEditor(); } /** * Cleanup all widgetry & resources used by the in-place editing */ protected void cleanupEditor() { if (fEditorText != null) { fNewStepFilter = null; fNewTableItem = null; fTableEditor.setEditor(null, null, 0); fEditorText.dispose(); fEditorText = null; } } protected void removeNewFilter() { fStepFilterContentProvider.removeFilters(new Object[] { fNewStepFilter }); } /** * A valid step filter is simply one that is a valid Java identifier. * and, as defined in the JDI spec, the regular expressions used for * step filtering must be limited to exact matches or patterns that * begin with '*' or end with '*'. Beyond this, a string cannot be validated * as corresponding to an existing type or package (and this is probably not * even desirable). */ private boolean validateEditorInput(String trimmedValue) { char firstChar = trimmedValue.charAt(0); if (!Character.isJavaIdentifierStart(firstChar)) { if (!(firstChar == '*')) { return false; } } int length = trimmedValue.length(); for (int i = 1; i < length; i++) { char c = trimmedValue.charAt(i); if (!Character.isJavaIdentifierPart(c)) { if (c == '.' && i != (length - 1)) { continue; } if (c == '*' && i == (length - 1)) { continue; } return false; } } return true; } /** * Utility method to create and return a selection dialog that allows * selection of a specific Java package. Empty packages are not returned. * If Java Projects are provided, only packages found within those projects * are included. If no Java projects are provided, all Java projects in the * workspace are considered. */ public static ElementListSelectionDialog createAllPackagesDialog(Shell shell, IJavaProject[] originals, final boolean includeDefaultPackage) throws JavaModelException { final List<IPackageFragment> packageList = new ArrayList<IPackageFragment>(); if (originals == null) { IWorkspaceRoot wsroot = ResourcesPlugin.getWorkspace().getRoot(); IJavaModel model = JavaCore.create(wsroot); originals = model.getJavaProjects(); } final IJavaProject[] projects = originals; final JavaModelException[] exception = new JavaModelException[1]; ProgressMonitorDialog monitor = new ProgressMonitorDialog(shell); IRunnableWithProgress r = new IRunnableWithProgress() { @Override public void run(IProgressMonitor myMonitor) { try { Set<String> packageNameSet = new HashSet<String>(); myMonitor.beginTask(JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Searching"), //$NON-NLS-1$ projects.length); for (int i = 0; i < projects.length; i++) { IPackageFragment[] pkgs = projects[i].getPackageFragments(); for (int j = 0; j < pkgs.length; j++) { IPackageFragment pkg = pkgs[j]; if (!pkg.hasChildren() && (pkg.getNonJavaResources().length > 0)) { continue; } String pkgName = pkg.getElementName(); if (!includeDefaultPackage && pkgName.length() == 0) { continue; } if (packageNameSet.add(pkgName)) { packageList.add(pkg); } } myMonitor.worked(1); } myMonitor.done(); } catch (JavaModelException jme) { exception[0] = jme; } } }; try { monitor.run(false, false, r); } catch (InvocationTargetException e) { JDepend4EclipsePlugin.logError(e, "ooo"); //$NON-NLS-1$ } catch (InterruptedException e) { JDepend4EclipsePlugin.logError(e, "ooo"); //$NON-NLS-1$ } if (exception[0] != null) { throw exception[0]; } int flags = JavaElementLabelProvider.SHOW_DEFAULT; ElementListSelectionDialog dialog = new ElementListSelectionDialog(shell, new JavaElementLabelProvider(flags)); dialog.setIgnoreCase(false); dialog.setElements(packageList.toArray()); // XXX inefficient return dialog; } protected void addPackage() { Shell shell = getShell(); ElementListSelectionDialog dialog = null; try { dialog = createAllPackagesDialog(shell, null, true); } catch (JavaModelException jme) { String title = JDepend4EclipsePlugin .getResourceString("JDependPreferencePage.Add_package_to_package_filters"); //$NON-NLS-1$ String message = JDepend4EclipsePlugin.getResourceString( "JDependPreferencePage.Could_not_open_package_selection_dialog_for_package_filters"); //$NON-NLS-1$ JDepend4EclipsePlugin.logError(jme, title + message); return; } dialog.setTitle( JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.Add_package_to_package_filters")); //$NON-NLS-1$ dialog.setMessage(JDepend4EclipsePlugin .getResourceString("JDependPreferencePage.Select_a_package_to_filter_for_JDepend")); //$NON-NLS-1$ dialog.setMultipleSelection(true); if (dialog.open() == IDialogConstants.CANCEL_ID) { return; } Object[] packages = dialog.getResult(); if (packages != null) { for (int i = 0; i < packages.length; i++) { IJavaElement pkg = (IJavaElement) packages[i]; String filter = pkg.getElementName(); if (filter.length() < 1) { filter = JDepend4EclipsePlugin.getResourceString("JDependPreferencePage.default_package"); //$NON-NLS-1$ } else { filter += ".*"; //$NON-NLS-1$ } fStepFilterContentProvider.addFilter(filter, true); } } } protected void removeFilters() { IStructuredSelection selection = (IStructuredSelection) fFilterViewer.getSelection(); fStepFilterContentProvider.removeFilters(selection.toArray()); } @Override public boolean performOk() { fStepFilterContentProvider.saveFilters(); IPreferenceStore prefs = getPreferenceStore(); prefs.setValue(JDependConstants.PREF_USE_ALL_CYCLES_SEARCH, fUseAllCyclesSearchCheckbox.getSelection()); prefs.setValue(JDependConstants.SAVE_AS_XML, saveAsXml.getSelection()); prefs.setValue(JDependConstants.SAVE_TO_SHOW_OPTIONS, askBeforeSave.getSelection()); return super.performOk(); } /** * Sets the default preferences. * @see PreferencePage#performDefaults() */ @Override protected void performDefaults() { setDefaultValues(); super.performDefaults(); } private void setDefaultValues() { fStepFilterContentProvider.setDefaults(); } /** * Parses the comma separated string into an array of strings * * @return list */ public static String[] parseList(String listString) { List<String> list = new ArrayList<String>(10); StringTokenizer tokenizer = new StringTokenizer(listString, ","); //$NON-NLS-1$ while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); list.add(token); } return list.toArray(new String[list.size()]); } /** * Serializes the array of strings into one comma * separated string. * * @param list array of strings * @return a single string composed of the given list */ public static String serializeList(String[] list) { if (list == null) { return ""; //$NON-NLS-1$ } StringBuffer buffer = new StringBuffer(); for (int i = 0; i < list.length; i++) { if (i > 0) { buffer.append(','); } buffer.append(list[i]); } return buffer.toString(); } protected void updateActions() { if (fEnableAllButton != null) { boolean enabled = fFilterViewer.getTable().getItemCount() > 0; fEnableAllButton.setEnabled(enabled); fDisableAllButton.setEnabled(enabled); } } /** * Content provider for the table. Content consists of instances of StepFilter. */ protected final class FilterContentProvider implements IStructuredContentProvider { private final CheckboxTableViewer fViewer; private List<Filter> fFilters; public FilterContentProvider(CheckboxTableViewer viewer) { fViewer = viewer; List<String> active = createActiveStepFiltersList(); List<String> inactive = createInactiveStepFiltersList(); List<String> defaultlist = createDefaultStepFiltersList(); populateFilters(active, inactive, defaultlist); updateActions(); } public void setDefaults() { fViewer.remove(fFilters.toArray()); List<String> active = createActiveStepFiltersList(); List<String> inactive = createInactiveStepFiltersList(); List<String> defaultlist = createDefaultStepFiltersList(); populateFilters(active, inactive, defaultlist); boolean useStepFilters = getPreferenceStore().getDefaultBoolean(JDependConstants.PREF_USE_FILTERS); fUseFiltersCheckbox.setSelection(useStepFilters); toggleFilterWidgetsEnabled(useStepFilters); boolean useFastSearch = getPreferenceStore() .getDefaultBoolean(JDependConstants.PREF_USE_ALL_CYCLES_SEARCH); fUseAllCyclesSearchCheckbox.setSelection(useFastSearch); boolean saveAsXmlValue = getPreferenceStore().getDefaultBoolean(JDependConstants.SAVE_AS_XML); saveAsXml.setSelection(saveAsXmlValue); boolean askBeforeValue = getPreferenceStore().getDefaultBoolean(JDependConstants.SAVE_TO_SHOW_OPTIONS); askBeforeSave.setSelection(askBeforeValue); saveAsXml.setEnabled(!askBeforeValue); } protected void populateFilters(List<String> activeList, List<String> inactiveList, List<String> defaultlist) { fFilters = new ArrayList<Filter>(activeList.size() + inactiveList.size() + defaultlist.size()); populateList(inactiveList, false); populateList(activeList, true); populateList(defaultlist, true); } protected void populateList(List<String> list, boolean checked) { Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String name = iterator.next(); addFilter(name, checked); } } /** * Returns a list of active step filters. * * @return list */ protected List<String> createActiveStepFiltersList() { String[] strings = parseList(getPreferenceStore().getString(JDependConstants.PREF_ACTIVE_FILTERS_LIST)); return Arrays.asList(strings); } /** * Returns a list of active step filters. * * @return list */ protected List<String> createDefaultStepFiltersList() { String[] strings = parseList( getPreferenceStore().getDefaultString(JDependConstants.PREF_ACTIVE_FILTERS_LIST)); return Arrays.asList(strings); } /** * Returns a list of active step filters. * * @return list */ protected List<String> createInactiveStepFiltersList() { String[] strings = parseList( getPreferenceStore().getString(JDependConstants.PREF_INACTIVE_FILTERS_LIST)); return Arrays.asList(strings); } public Filter addFilter(String name, boolean checked) { Filter filter = new Filter(name, checked); if (!fFilters.contains(filter)) { fFilters.add(filter); fViewer.add(filter); fViewer.setChecked(filter, checked); } updateActions(); return filter; } public void saveFilters() { getPreferenceStore().setValue(JDependConstants.PREF_USE_FILTERS, fUseFiltersCheckbox.getSelection()); List<String> active = new ArrayList<String>(fFilters.size()); List<String> inactive = new ArrayList<String>(fFilters.size()); Iterator<Filter> iterator = fFilters.iterator(); while (iterator.hasNext()) { Filter filter = iterator.next(); String name = filter.getName(); if (filter.isChecked()) { active.add(name); } else { inactive.add(name); } } String pref = serializeList(active.toArray(new String[active.size()])); getPreferenceStore().setValue(JDependConstants.PREF_ACTIVE_FILTERS_LIST, pref); pref = serializeList(inactive.toArray(new String[inactive.size()])); getPreferenceStore().setValue(JDependConstants.PREF_INACTIVE_FILTERS_LIST, pref); } public void removeFilters(Object[] filters) { for (int i = 0; i < filters.length; i++) { Filter filter = (Filter) filters[i]; fFilters.remove(filter); } fViewer.remove(filters); updateActions(); } public void toggleFilter(Filter filter) { boolean newState = !filter.isChecked(); filter.setChecked(newState); fViewer.setChecked(filter, newState); } /** * @see IStructuredContentProvider#getElements(Object) */ @Override public Object[] getElements(Object inputElement) { return fFilters.toArray(); } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { /** ignored */ } @Override public void dispose() { /** ignored */ } } } /** * Model object that represents a single entry in a filter table. */ final class Filter { private String fName; private boolean fChecked; public Filter(String name, boolean checked) { setName(name); setChecked(checked); } public String getName() { return fName; } public void setName(String name) { fName = name; } public boolean isChecked() { return fChecked; } public void setChecked(boolean checked) { fChecked = checked; } @Override public boolean equals(Object o) { if (o instanceof Filter) { Filter other = (Filter) o; if (getName().equals(other.getName())) { return true; } } return false; } @Override public int hashCode() { return getName().hashCode(); } } /** * Label provider for Filter model objects */ class FilterLabelProvider extends LabelProvider implements ITableLabelProvider { private static final Image IMG_PKG = JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_PACKAGE); /** * @see ITableLabelProvider#getColumnText(Object, int) */ @Override public String getColumnText(Object object, int column) { if (column == 0) { return ((Filter) object).getName(); } return ""; //$NON-NLS-1$ } /** * @see ILabelProvider#getText(Object) */ @Override public String getText(Object element) { return ((Filter) element).getName(); } /** * @see ITableLabelProvider#getColumnImage(Object, int) */ @Override public Image getColumnImage(Object object, int column) { return IMG_PKG; } } class FilterViewerSorter extends WorkbenchViewerComparator { @Override public int compare(Viewer viewer, Object e1, Object e2) { ILabelProvider lprov = (ILabelProvider) ((ContentViewer) viewer).getLabelProvider(); String name1 = lprov.getText(e1); String name2 = lprov.getText(e2); if (name1 == null) { name1 = ""; //$NON-NLS-1$ } if (name2 == null) { name2 = ""; //$NON-NLS-1$ } if (name1.length() > 0 && name2.length() > 0) { char char1 = name1.charAt(name1.length() - 1); char char2 = name2.charAt(name2.length() - 1); if (char1 == '*' && char1 != char2) { return -1; } if (char2 == '*' && char2 != char1) { return 1; } } return name1.compareTo(name2); } }