| /******************************************************************************* |
| * Copyright (c) 2009, 2014 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 |
| *******************************************************************************/ |
| package org.eclipse.pde.api.tools.ui.internal.use; |
| |
| import java.util.ArrayList; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.TreeSet; |
| import java.util.regex.PatternSyntaxException; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.IInputValidator; |
| import org.eclipse.jface.viewers.ArrayContentProvider; |
| import org.eclipse.jface.viewers.ColumnLayoutData; |
| import org.eclipse.jface.viewers.ColumnWeightData; |
| import org.eclipse.jface.viewers.DoubleClickEvent; |
| import org.eclipse.jface.viewers.IDoubleClickListener; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| 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.TableViewer; |
| import org.eclipse.jface.viewers.ViewerComparator; |
| import org.eclipse.jface.wizard.WizardDialog; |
| import org.eclipse.pde.api.tools.ui.internal.ApiUIPlugin; |
| import org.eclipse.pde.api.tools.ui.internal.IApiToolsConstants; |
| import org.eclipse.pde.api.tools.ui.internal.IApiToolsHelpContextIds; |
| import org.eclipse.pde.api.tools.ui.internal.SWTFactory; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.KeyAdapter; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.TableColumn; |
| import org.eclipse.ui.PlatformUI; |
| |
| /** |
| * Tab that allows users to specify patterns that can be used to augment the |
| * search to override API description settings for what is and what is not API. <br> |
| * <br> |
| * For example a bundle manifest could say that a.b.c.provisional.package is API |
| * and using this tab a user could provide a pattern a\.\.c\.provisional.* |
| * saying that this should be treated as internal code use |
| * |
| * @since 1.1 |
| */ |
| public class ApiUsePatternTab extends AbstractLaunchConfigurationTab { |
| |
| class Labels extends LabelProvider implements ITableLabelProvider { |
| @Override |
| public Image getColumnImage(Object element, int columnIndex) { |
| return null; |
| } |
| |
| @Override |
| public String getColumnText(Object element, int columnIndex) { |
| Pattern pattern = (Pattern) element; |
| switch (columnIndex) { |
| case 0: { |
| return pattern.pattern; |
| } |
| case 1: { |
| switch (pattern.kind) { |
| case Pattern.API: { |
| return Messages.ApiUsePatternTab_API; |
| } |
| case Pattern.INTERNAL: { |
| return Messages.ApiUsePatternTab_internal; |
| } |
| case Pattern.JAR: { |
| return Messages.ApiUsePatternTab_archive; |
| } |
| case Pattern.REPORT: { |
| return Messages.ApiUsePatternTab_report; |
| } |
| case Pattern.REPORT_TO: { |
| return Messages.ApiUsePatternTab_report_to; |
| } |
| default: |
| break; |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| return null; |
| } |
| } |
| |
| class RegexValidator implements IInputValidator { |
| @Override |
| public String isValid(String newText) { |
| if (IApiToolsConstants.EMPTY_STRING.equals(newText)) { |
| return Messages.ApiUsePatternTab_provide_regex; |
| } |
| try { |
| java.util.regex.Pattern.compile(newText); |
| } catch (PatternSyntaxException pse) { |
| return pse.getDescription(); |
| } |
| return null; |
| } |
| } |
| |
| class Pattern { |
| static final int API = 1, INTERNAL = 2, JAR = 3, REPORT = 4, |
| REPORT_TO = 5; |
| String pattern = null; |
| int kind = -1; |
| |
| public Pattern(String pattern, int kind) { |
| this.pattern = pattern; |
| this.kind = kind; |
| } |
| |
| @Override |
| public String toString() { |
| return this.pattern; |
| } |
| } |
| |
| TreeSet<Pattern> patterns = new TreeSet<Pattern>(new Comparator<Object>() { |
| @Override |
| public int compare(Object o1, Object o2) { |
| return ((Pattern) o1).pattern.compareTo(((Pattern) o2).pattern); |
| } |
| }); |
| TableViewer viewer = null; |
| Image image = null; |
| Button addbutton = null, editbutton = null, removebutton = null; |
| ColumnLayoutData[] columndata = { |
| new ColumnWeightData(80), new ColumnWeightData(20) }; |
| String[] columnnames = { |
| Messages.ApiUsePatternTab_column_pattern, |
| Messages.ApiUsePatternTab_column_kind }; |
| |
| @Override |
| public void createControl(Composite parent) { |
| Composite comp = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_BOTH); |
| SWTFactory.createWrapLabel(comp, Messages.ApiUsePatternTab_patterns, 2, 100); |
| Composite tcomp = SWTFactory.createComposite(comp, 1, 1, GridData.FILL_BOTH, 0, 0); |
| GridData gd = (GridData) tcomp.getLayoutData(); |
| gd.grabExcessHorizontalSpace = true; |
| Table table = new Table(tcomp, SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI); |
| table.setHeaderVisible(true); |
| TableLayout layout = new TableLayout(); |
| for (ColumnLayoutData element : columndata) { |
| layout.addColumnData(element); |
| } |
| table.setLayout(layout); |
| gd = new GridData(GridData.FILL_BOTH); |
| gd.grabExcessHorizontalSpace = true; |
| gd.widthHint = 250; |
| table.setLayoutData(gd); |
| this.viewer = new TableViewer(table); |
| this.viewer.setColumnProperties(columnnames); |
| this.viewer.setComparator(new ViewerComparator() { |
| @Override |
| public int category(Object element) { |
| return ((Pattern) element).kind; |
| } |
| }); |
| this.viewer.setLabelProvider(new Labels()); |
| this.viewer.setContentProvider(new ArrayContentProvider()); |
| this.viewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| updateButtons((IStructuredSelection) event.getSelection()); |
| } |
| }); |
| this.viewer.addDoubleClickListener(new IDoubleClickListener() { |
| @Override |
| public void doubleClick(DoubleClickEvent event) { |
| doEdit(); |
| } |
| }); |
| TableColumn column = null; |
| for (String columnname : columnnames) { |
| column = new TableColumn(table, SWT.NONE); |
| column.setResizable(false); |
| column.setMoveable(false); |
| column.setText(columnname); |
| } |
| this.viewer.setInput(this.patterns); |
| table.addKeyListener(new KeyAdapter() { |
| @Override |
| public void keyPressed(KeyEvent event) { |
| if (event.character == SWT.DEL && event.stateMask == 0) { |
| doRemove(); |
| } |
| } |
| }); |
| |
| Composite bcomp = SWTFactory.createComposite(comp, 1, 1, GridData.FILL_VERTICAL, 0, 0); |
| this.addbutton = SWTFactory.createPushButton(bcomp, Messages.ApiUsePatternTab_add, null); |
| this.addbutton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| PatternWizard wizard = new PatternWizard(null, -1); |
| WizardDialog dialog = new WizardDialog(getShell(), wizard); |
| if (dialog.open() == IDialogConstants.OK_ID) { |
| addPattern(wizard.getPattern(), wizard.getKind()); |
| ApiUsePatternTab.this.viewer.refresh(true, true); |
| updateLaunchConfigurationDialog(); |
| } |
| } |
| }); |
| this.editbutton = SWTFactory.createPushButton(bcomp, Messages.ApiUsePatternTab_edit, null); |
| this.editbutton.setEnabled(false); |
| this.editbutton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| doEdit(); |
| } |
| }); |
| this.removebutton = SWTFactory.createPushButton(bcomp, Messages.ApiUsePatternTab_remove, null); |
| this.removebutton.setEnabled(false); |
| this.removebutton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| doRemove(); |
| } |
| }); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(comp, IApiToolsHelpContextIds.API_USE_PATTERN_TAB); |
| setControl(comp); |
| } |
| |
| @Override |
| protected Shell getShell() { |
| return super.getShell(); |
| } |
| |
| @Override |
| protected void updateLaunchConfigurationDialog() { |
| super.updateLaunchConfigurationDialog(); |
| } |
| |
| /** |
| * Removes the selected elements from the table |
| */ |
| void doRemove() { |
| IStructuredSelection selection = ApiUsePatternTab.this.viewer.getStructuredSelection(); |
| for (Iterator<?> iter = selection.iterator(); iter.hasNext();) { |
| removePattern((Pattern) iter.next()); |
| } |
| this.viewer.refresh(); |
| updateLaunchConfigurationDialog(); |
| } |
| |
| /** |
| * handles editing a selected pattern |
| */ |
| void doEdit() { |
| IStructuredSelection selection = ApiUsePatternTab.this.viewer.getStructuredSelection(); |
| Pattern pattern = (Pattern) selection.getFirstElement(); |
| PatternWizard wizard = new PatternWizard(pattern.pattern, pattern.kind); |
| WizardDialog dialog = new WizardDialog(getShell(), wizard); |
| if (dialog.open() == IDialogConstants.OK_ID) { |
| pattern.pattern = wizard.getPattern(); |
| pattern.kind = wizard.getKind(); |
| ApiUsePatternTab.this.viewer.refresh(pattern, true, true); |
| updateLaunchConfigurationDialog(); |
| } |
| } |
| |
| /** |
| * Updates the buttons based on the selection in the viewer |
| * |
| * @param selection |
| */ |
| void updateButtons(IStructuredSelection selection) { |
| int size = selection.size(); |
| this.editbutton.setEnabled(size == 1); |
| this.removebutton.setEnabled(size > 0); |
| } |
| |
| @Override |
| public String getName() { |
| return Messages.ApiUsePatternTab_patterns_title; |
| } |
| |
| @Override |
| public Image getImage() { |
| return ApiUIPlugin.getSharedImage(IApiToolsConstants.IMG_ELCL_TEXT_EDIT); |
| } |
| |
| @Override |
| public void initializeFrom(ILaunchConfiguration configuration) { |
| try { |
| this.patterns.clear(); |
| List<String> pats = configuration.getAttribute(ApiUseLaunchDelegate.API_PATTERNS_LIST, (List<String>) null); |
| if (pats != null) { |
| for (String pattern : pats) { |
| addPattern(pattern, Pattern.API); |
| } |
| } |
| pats = configuration.getAttribute(ApiUseLaunchDelegate.INTERNAL_PATTERNS_LIST, (List<String>) null); |
| if (pats != null) { |
| for (String pattern : pats) { |
| addPattern(pattern, Pattern.INTERNAL); |
| } |
| } |
| pats = configuration.getAttribute(ApiUseLaunchDelegate.JAR_PATTERNS_LIST, (List<String>) null); |
| if (pats != null) { |
| for (String pattern : pats) { |
| addPattern(pattern, Pattern.JAR); |
| } |
| } |
| pats = configuration.getAttribute(ApiUseLaunchDelegate.REPORT_PATTERNS_LIST, (List<String>) null); |
| if (pats != null) { |
| for (String pattern : pats) { |
| addPattern(pattern, Pattern.REPORT); |
| } |
| } |
| pats = configuration.getAttribute(ApiUseLaunchDelegate.REPORT_TO_PATTERNS_LIST, (List<String>) null); |
| if (pats != null) { |
| for (String pattern : pats) { |
| addPattern(pattern, Pattern.REPORT_TO); |
| } |
| } |
| this.viewer.refresh(); |
| } catch (CoreException ce) { |
| ApiUIPlugin.log(ce); |
| } |
| } |
| |
| /** |
| * Adds a new pattern to the list |
| * |
| * @param pattern |
| * @param kind |
| * @return |
| */ |
| boolean addPattern(String pattern, int kind) { |
| return this.patterns.add(new Pattern(pattern, kind)); |
| } |
| |
| /** |
| * Removes the pattern from the listing |
| * |
| * @param pattern |
| * @return |
| */ |
| boolean removePattern(Pattern pattern) { |
| return this.patterns.remove(pattern); |
| } |
| |
| @Override |
| public void performApply(ILaunchConfigurationWorkingCopy configuration) { |
| ArrayList<String> api = new ArrayList<String>(); |
| ArrayList<String> internal = new ArrayList<String>(); |
| ArrayList<String> jar = new ArrayList<String>(); |
| ArrayList<String> report = new ArrayList<String>(); |
| ArrayList<String> reportto = new ArrayList<String>(); |
| for (Pattern pattern : this.patterns) { |
| switch (pattern.kind) { |
| case Pattern.API: { |
| api.add(pattern.pattern); |
| break; |
| } |
| case Pattern.INTERNAL: { |
| internal.add(pattern.pattern); |
| break; |
| } |
| case Pattern.JAR: { |
| jar.add(pattern.pattern); |
| break; |
| } |
| case Pattern.REPORT: { |
| report.add(pattern.pattern); |
| break; |
| } |
| case Pattern.REPORT_TO: { |
| reportto.add(pattern.pattern); |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| configuration.setAttribute(ApiUseLaunchDelegate.API_PATTERNS_LIST, api.size() > 0 ? api : (List<String>) null); |
| configuration.setAttribute(ApiUseLaunchDelegate.INTERNAL_PATTERNS_LIST, internal.size() > 0 ? internal : (List<String>) null); |
| configuration.setAttribute(ApiUseLaunchDelegate.JAR_PATTERNS_LIST, jar.size() > 0 ? jar : (List<String>) null); |
| configuration.setAttribute(ApiUseLaunchDelegate.REPORT_PATTERNS_LIST, report.size() > 0 ? report : (List<String>) null); |
| configuration.setAttribute(ApiUseLaunchDelegate.REPORT_TO_PATTERNS_LIST, reportto.size() > 0 ? reportto : (List<String>) null); |
| } |
| |
| @Override |
| public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { |
| // do nothing, default is no patterns |
| } |
| } |