/******************************************************************************* * Copyright (c) 2009 IBM Corporation and others. * 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 * * Contributors: * IBM Corporation - initial API and implementation * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.debug.ui.preferences.stepFilter; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.StringTokenizer; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.preferences.DefaultScope; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.internal.core.StepFilterManager; import org.eclipse.debug.internal.ui.SWTFactory; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.dltk.core.IBuildpathEntry; import org.eclipse.dltk.core.environment.EnvironmentPathUtils; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.viewers.*; import org.eclipse.php.internal.debug.core.IPHPDebugConstants; import org.eclipse.php.internal.debug.core.PHPDebugPlugin; import org.eclipse.php.internal.debug.core.preferences.stepFilters.*; import org.eclipse.php.internal.debug.ui.PHPDebugUIMessages; import org.eclipse.php.internal.ui.IPHPHelpContextIds; import org.eclipse.php.internal.ui.PHPUiPlugin; import org.eclipse.swt.SWT; 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.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.ISelectionValidator; /** * The preference page for PHP step filtering, located at the node PHP > Debug > * Step Filtering * * @author yaronm */ public class PHPDebugStepFilterPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { public static final String PREFIX = PHPDebugPlugin.ID + '.'; public static final String PAGE_ID = "org.eclipse.php.debug.ui.PHPStepFilterPreferencePage"; //$NON-NLS-1$ /** * Content provider for the table. Content consists of instances of * StepFilter. */ class StepFilterContentProvider implements IStructuredContentProvider { public StepFilterContentProvider() { initTableState(false); } public Object[] getElements(Object inputElement) { return getAllFiltersFromTable(); } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } public void dispose() { } } private ArrayList<IDebugStepFilterPrefListener> debugStepFilterPrefListeners = new ArrayList<IDebugStepFilterPrefListener>(); // widgets private CheckboxTableViewer fTableViewer; private Button fUseStepFiltersButton; private Button fAddResourceButton; private Button fRemoveFilterButton; private Button fAddFilterButton; private Button fSelectAllButton; private Button fDeselectAllButton; /** * Constructor */ public PHPDebugStepFilterPreferencePage() { super(); setPreferenceStore(PHPUiPlugin.getDefault().getPreferenceStore()); setTitle(PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_stepFiltering); setDescription(PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_stepFiltersAreApplied); addPreferenceListener(DebugStepFilterController.getInstance()); } /* * (non-Javadoc) * * @see * org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse * .swt.widgets.Composite) */ protected Control createContents(Composite parent) { PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IPHPHelpContextIds.STEP_FILTERING_PREFERENCES); // $NON-NLS-1$ // The main composite Composite composite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0); createStepFilterPreferences(composite); return composite; } /* * (non-Javadoc) * * @see * org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) */ public void init(IWorkbench workbench) { } /** * handles the filter button being clicked * * @param event * the clicked event */ private void handleFilterViewerKeyPress(KeyEvent event) { if (event.character == SWT.DEL && event.stateMask == 0) { removeFilters(); } } /** * Create a group to contain the step filter related widgetry */ private void createStepFilterPreferences(Composite parent) { Composite container = SWTFactory.createComposite(parent, parent.getFont(), 2, 1, GridData.FILL_BOTH, 0, 0); fUseStepFiltersButton = SWTFactory.createCheckButton(container, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_useStepFilters, null, DebugUITools.isUseStepFilters(), 2); fUseStepFiltersButton.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { setPageEnablement(fUseStepFiltersButton.getSelection()); } public void widgetDefaultSelected(SelectionEvent e) { } }); SWTFactory.createLabel(container, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_definedStepFilters, 2); fTableViewer = CheckboxTableViewer.newCheckList(container, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION); fTableViewer.getTable().setFont(container.getFont()); fTableViewer.setLabelProvider(new FilterLabelProvider()); fTableViewer.setComparator(new FilterViewerComparator()); fTableViewer.setContentProvider(new StepFilterContentProvider()); fTableViewer.setInput(getAllPersistedFilters(false)); fTableViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH)); fTableViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { ((DebugStepFilter) event.getElement()).setEnabled(event.getChecked()); } }); fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (selection.isEmpty()) { fRemoveFilterButton.setEnabled(false); } else { DebugStepFilter filter = (DebugStepFilter) ((StructuredSelection) selection).getFirstElement(); if (filter.isReadOnly()) { fRemoveFilterButton.setEnabled(false); } else { fRemoveFilterButton.setEnabled(true); } } } }); fTableViewer.getControl().addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent event) { handleFilterViewerKeyPress(event); } }); createStepFilterButtons(container); fUseStepFiltersButton.setSelection(DebugPlugin.isUseStepFilters()); setPageEnablement(fUseStepFiltersButton.getSelection()); } /** * initializes the checked state of the filters when the dialog opens */ private void initTableState(boolean defaults) { DebugStepFilter[] filters = getAllPersistedFilters(defaults); if (filters == null) { return; } for (int i = 0; i < filters.length; i++) { fTableViewer.add(filters[i]); fTableViewer.setChecked(filters[i], filters[i].isEnabled()); } } /** * Enables or disables the widgets on the page, with the exception of * <code>fUseStepFiltersButton</code> according to the passed boolean * * @param enabled * the new enablement status of the page's widgets * @since 3.2 */ protected void setPageEnablement(boolean enabled) { fAddFilterButton.setEnabled(enabled); fAddResourceButton.setEnabled(enabled); fDeselectAllButton.setEnabled(enabled); fSelectAllButton.setEnabled(enabled); fTableViewer.getTable().setEnabled(enabled); fRemoveFilterButton.setEnabled(enabled & !fTableViewer.getSelection().isEmpty()); } /** * Creates the button for the step filter options * * @param container * the parent container */ private void createStepFilterButtons(Composite container) { initializeDialogUnits(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 = SWTFactory.createPushButton(buttonContainer, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_addFilter, null); fAddFilterButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { addFilter(); } }); // Add resource button fAddResourceButton = SWTFactory.createPushButton(buttonContainer, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_addResource, null); fAddResourceButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { addResource(); } }); // Remove button fRemoveFilterButton = SWTFactory.createPushButton(buttonContainer, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_remove, null); fRemoveFilterButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { removeFilters(); } }); fRemoveFilterButton.setEnabled(false); Label separator = new Label(buttonContainer, SWT.NONE); separator.setVisible(false); gd = new GridData(); gd.horizontalAlignment = GridData.FILL; gd.verticalAlignment = GridData.BEGINNING; gd.heightHint = 4; separator.setLayoutData(gd); // Select All button fSelectAllButton = SWTFactory.createPushButton(buttonContainer, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_selectAll, null); fSelectAllButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { fTableViewer.setAllChecked(true); } }); // De-Select All button fDeselectAllButton = SWTFactory.createPushButton(buttonContainer, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_deselectAll, null); fDeselectAllButton.addListener(SWT.Selection, new Listener() { public void handleEvent(Event e) { fTableViewer.setAllChecked(false); } }); } /** * Allows a new filter to be added to the listing */ private void addFilter() { DebugStepFilter newfilter = CreateStepFilterDialog.showCreateStepFilterDialog(getShell(), getAllFiltersFromTable()); if (newfilter == null) { return; } fTableViewer.add(newfilter); fTableViewer.setChecked(newfilter, true); fTableViewer.refresh(newfilter); } /** * add a new type to the listing of available filters */ private void addResource() { PHPResourceSelectionDialog dialog = new PHPResourceSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), true, PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_selectResourceToFilter); dialog.setValidator(new FilterSelectionValidator(getAllFiltersFromTable())); dialog.open(); Object[] result = dialog.getResult(); if (result != null && result.length > 0) { Object resourceToFilter = result[0]; String filteredPath = ""; //$NON-NLS-1$ if (resourceToFilter instanceof IResource) { filteredPath = ((IResource) resourceToFilter).getFullPath().toString(); if (resourceToFilter instanceof IProject) { addFilter(filteredPath, true, IStepFilterTypes.PHP_PROJECT); } else if (resourceToFilter instanceof IFolder) { addFilter(filteredPath, true, IStepFilterTypes.PHP_PROJECT_FOLDER); } else if (resourceToFilter instanceof IFile) { addFilter(filteredPath, true, IStepFilterTypes.PHP_PROJECT_FILE); } } else if (resourceToFilter instanceof IBuildpathEntry) { IBuildpathEntry entry = (IBuildpathEntry) resourceToFilter; filteredPath = EnvironmentPathUtils.getLocalPath(entry.getPath()).toOSString(); if (entry.getEntryKind() == IBuildpathEntry.BPE_VARIABLE) {// variable addFilter(filteredPath, true, IStepFilterTypes.PHP_INCLUDE_PATH_VAR); } else if (entry.getEntryKind() == IBuildpathEntry.BPE_LIBRARY) {// library // = // folder addFilter(filteredPath, true, IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY); } } else if (resourceToFilter instanceof IncPathFile) { IBuildpathEntry entry = ((IncPathFile) resourceToFilter).getBuildpathEntry(); File file = ((IncPathFile) resourceToFilter).file; filteredPath = file.getAbsolutePath(); if (file.isDirectory()) { if (entry.getEntryKind() == IBuildpathEntry.BPE_VARIABLE) { addFilter(filteredPath, true, IStepFilterTypes.PHP_INCLUDE_PATH_VAR_FOLDER); } else if (entry.getEntryKind() == IBuildpathEntry.BPE_LIBRARY) { addFilter(filteredPath, true, IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY_FOLDER); } } else { if (entry.getEntryKind() == IBuildpathEntry.BPE_VARIABLE) { addFilter(filteredPath, true, IStepFilterTypes.PHP_INCLUDE_PATH_VAR_FILE); } else if (entry.getEntryKind() == IBuildpathEntry.BPE_LIBRARY) { addFilter(filteredPath, true, IStepFilterTypes.PHP_INCLUDE_PATH_LIBRARY_FILE); } } } } } /** * Removes the currently selected filters. */ protected void removeFilters() { fTableViewer.remove(((IStructuredSelection) fTableViewer.getSelection()).toArray()); } /* * (non-Javadoc) * * @see org.eclipse.jface.preference.PreferencePage#performOk() */ public boolean performOk() { IPreferenceStore store = getPreferenceStore(); ArrayList<String> filtersPersistenceList = new ArrayList<String>(); DebugStepFilter[] filters = getAllFiltersFromTable(); for (int i = 0; i < filters.length; i++) { filtersPersistenceList.add(filters[i].getType() + DebugStepFilter.FILTER_TOKENS_DELIM + filters[i].isEnabled() + DebugStepFilter.FILTER_TOKENS_DELIM + filters[i].isReadOnly() + DebugStepFilter.FILTER_TOKENS_DELIM + filters[i].getPath()); } String pref = serializeList( (String[]) filtersPersistenceList.toArray(new String[filtersPersistenceList.size()])); store.setValue(IPHPDebugConstants.PREF_STEP_FILTERS_LIST, pref); DebugPlugin.setUseStepFilters(fUseStepFiltersButton.getSelection()); notifyPrefListeners(); return super.performOk(); } private void notifyPrefListeners() { DebugStepFilterEvent event = new DebugStepFilterEvent(getAllFiltersFromTable(), fUseStepFiltersButton.getSelection()); Iterator<IDebugStepFilterPrefListener> iter = debugStepFilterPrefListeners.iterator(); while (iter.hasNext()) { iter.next().debugStepFilterModified(event); } } /* * (non-Javadoc) * * @see org.eclipse.jface.preference.PreferencePage#performDefaults() */ protected void performDefaults() { boolean stepenabled = DefaultScope.INSTANCE.getNode(DebugPlugin.getUniqueIdentifier()) .getBoolean(StepFilterManager.PREF_USE_STEP_FILTERS, false); fUseStepFiltersButton.setSelection(stepenabled); setPageEnablement(stepenabled); DebugStepFilter[] filters = getAllFiltersFromTable(); for (DebugStepFilter filter : filters) { if (!filter.isReadOnly()) { fTableViewer.remove(filter); } } super.performDefaults(); } /** * adds a single filter to the viewer * * @param filter * the new filter to add * @param checked * the checked state of the new filter * @since 3.2 */ protected void addFilter(String path, boolean checked, int type) { if (path != null) { DebugStepFilter f = new DebugStepFilter(type, checked, false, path); fTableViewer.add(f); fTableViewer.setChecked(f, checked); } } /** * returns all of the filters from the table, this includes ones that have * not yet been saved * * @return a possibly empty lits of filters fron the table * @since 3.2 */ protected DebugStepFilter[] getAllFiltersFromTable() { TableItem[] items = fTableViewer.getTable().getItems(); DebugStepFilter[] filters = new DebugStepFilter[items.length]; for (int i = 0; i < items.length; i++) { filters[i] = (DebugStepFilter) items[i].getData(); filters[i].setEnabled(items[i].getChecked()); } return filters; } /** * Returns all of the committed filters along with extended filters list * * @return an array of committed filters * @since 3.2 */ protected DebugStepFilter[] getAllPersistedFilters(boolean defaults) { ArrayList<DebugStepFilter> filtersToAdd = new ArrayList<DebugStepFilter>(); IPreferenceStore store = getPreferenceStore(); String[] parsedFilters = parseList(store.getString(IPHPDebugConstants.PREF_STEP_FILTERS_LIST)); for (int i = 0; i < parsedFilters.length; i++) { String[] tokens = parsedFilters[i].split("\\" + DebugStepFilter.FILTER_TOKENS_DELIM); //$NON-NLS-1$ if (tokens.length < 3) { return new DebugStepFilter[0]; } DebugStepFilter filter = new DebugStepFilter(Integer.parseInt(tokens[0]), Boolean.parseBoolean(tokens[1]), Boolean.parseBoolean(tokens[2]), tokens[3]); filtersToAdd.add(filter); } DebugStepFilter[] extendedList = DebugStepFilterController.getInstance().getExtendedFiltersList(); for (DebugStepFilter extendedFilter : extendedList) { if (!filtersToAdd.contains(extendedFilter)) { filtersToAdd.add(extendedFilter); } } DebugStepFilter[] result = new DebugStepFilter[filtersToAdd.size()]; filtersToAdd.toArray(result); return result; } // Parses the comma separated string into an array of strings private String[] parseList(String listString) { ArrayList<String> list = new ArrayList<String>(); StringTokenizer tokenizer = new StringTokenizer(listString, DebugStepFilter.FILTERS_PREF_LIST_DELIM); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); list.add(token); } return (String[]) list.toArray(new String[list.size()]); } // Serializes the array of strings into one comma // separated string. private 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(DebugStepFilter.FILTERS_PREF_LIST_DELIM); } buffer.append(list[i]); } return buffer.toString(); } class FilterSelectionValidator implements ISelectionValidator { private DebugStepFilter[] existingFilters; public FilterSelectionValidator(DebugStepFilter[] existingFilters) { this.existingFilters = existingFilters; } public String isValid(Object selection) { if (selection != null) { Path selectedPath = (Path) selection; for (DebugStepFilter filter : existingFilters) { if (selectedPath.equals(new Path(filter.getPath()))) { return PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_filterColon + selectedPath + PHPDebugUIMessages.PHPDebugStepFilterPreferencePage_alreadyExists; } } } return null; } } public void addPreferenceListener(IDebugStepFilterPrefListener listener) { debugStepFilterPrefListeners.add(listener); } public void removePreferenceListener(IDebugStepFilterPrefListener listener) { debugStepFilterPrefListeners.remove(listener); } }