| /******************************************************************************* |
| * Copyright (c) 2008-2015 Sonatype, Inc. and others |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Sonatype, Inc. - initial API and implementation |
| * Anton Tanasenko - Refactor marker resolutions and quick fixes (Bug #484359) |
| *******************************************************************************/ |
| |
| package org.eclipse.m2e.editor.xml.internal; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.ToolBarManager; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.text.AbstractInformationControl; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IInformationControl; |
| import org.eclipse.jface.text.IInformationControlCreator; |
| import org.eclipse.jface.text.IInformationControlExtension2; |
| import org.eclipse.jface.text.IInformationControlExtension3; |
| import org.eclipse.jface.text.IInformationControlExtension5; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.IRewriteTarget; |
| import org.eclipse.jface.text.ITextViewer; |
| import org.eclipse.jface.text.ITextViewerExtension; |
| import org.eclipse.jface.text.contentassist.ICompletionProposal; |
| import org.eclipse.jface.text.contentassist.ICompletionProposalExtension; |
| import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2; |
| import org.eclipse.jface.viewers.StyledString; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.ScrolledComposite; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.KeyListener; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Canvas; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Link; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.IMarkerResolution; |
| import org.eclipse.ui.IMarkerResolution2; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.PreferencesUtil; |
| import org.eclipse.ui.editors.text.EditorsUI; |
| import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; |
| |
| import org.eclipse.m2e.core.ui.internal.markers.MavenProblemResolution; |
| import org.eclipse.m2e.editor.xml.MvnImages; |
| import org.eclipse.m2e.editor.xml.PomHyperlinkDetector; |
| import org.eclipse.m2e.editor.xml.PomHyperlinkDetector.ExpressionRegion; |
| import org.eclipse.m2e.editor.xml.PomHyperlinkDetector.ManagedArtifactRegion; |
| import org.eclipse.m2e.editor.xml.PomHyperlinkDetector.MarkerRegion; |
| import org.eclipse.m2e.editor.xml.PomTextHover; |
| import org.eclipse.m2e.editor.xml.PomTextHover.CompoundRegion; |
| import org.eclipse.m2e.internal.discovery.markers.MavenDiscoveryMarkerResolutionGenerator; |
| |
| |
| public class MarkerHoverControl extends AbstractInformationControl |
| implements IInformationControlExtension2, IInformationControlExtension3, IInformationControlExtension5 { |
| |
| private CompoundRegion region; |
| |
| private Control focusControl; |
| |
| private Composite parent; |
| |
| private final DefaultMarkerAnnotationAccess markerAccess; |
| |
| public MarkerHoverControl(Shell shell, ToolBarManager toolbarManager) { |
| super(shell, toolbarManager); |
| markerAccess = new DefaultMarkerAnnotationAccess(); |
| create(); |
| } |
| |
| public MarkerHoverControl(Shell shell) { |
| super(shell, EditorsUI.getTooltipAffordanceString()); |
| markerAccess = new DefaultMarkerAnnotationAccess(); |
| create(); |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object) |
| */ |
| public void setInput(Object input) { |
| assert input instanceof CompoundRegion; |
| if(input instanceof CompoundRegion) { |
| region = (CompoundRegion) input; |
| } else { |
| throw new IllegalStateException("Not CompoundRegion"); //$NON-NLS-1$ |
| } |
| disposeDeferredCreatedContent(); |
| deferredCreateContent(); |
| } |
| |
| Shell getMyShell() { |
| return super.getShell(); |
| } |
| |
| Control getRoot() { |
| return parent; |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.IInformationControlExtension#hasContents() |
| */ |
| public boolean hasContents() { |
| return region != null; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractAnnotationHover.AbstractInformationControl#setFocus() |
| */ |
| public void setFocus() { |
| super.setFocus(); |
| if(focusControl != null) { |
| focusControl.setFocus(); |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.AbstractInformationControl#setVisible(boolean) |
| */ |
| public final void setVisible(boolean visible) { |
| if(!visible) |
| disposeDeferredCreatedContent(); |
| super.setVisible(visible); |
| } |
| |
| protected void disposeDeferredCreatedContent() { |
| Control[] children = parent.getChildren(); |
| for(int i = 0; i < children.length; i++ ) { |
| children[i].dispose(); |
| } |
| ToolBarManager toolBarManager = getToolBarManager(); |
| if(toolBarManager != null) |
| toolBarManager.removeAll(); |
| } |
| |
| /* |
| * @see org.eclipse.jface.text.AbstractInformationControl#createContent(org.eclipse.swt.widgets.Composite) |
| */ |
| protected void createContent(Composite parent) { |
| this.parent = parent; |
| GridLayout layout = new GridLayout(1, false); |
| layout.verticalSpacing = 0; |
| layout.marginWidth = 0; |
| layout.marginHeight = 0; |
| parent.setLayout(layout); |
| } |
| |
| @Override |
| public Point computeSizeHint() { |
| Point preferedSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true); |
| |
| Point constrains = getSizeConstraints(); |
| if(constrains == null) |
| return preferedSize; |
| |
| int trimWidth = getShell().computeTrim(0, 0, 0, 0).width; |
| Point constrainedSize = getShell().computeSize(constrains.x - trimWidth, SWT.DEFAULT, true); |
| |
| int width = Math.min(preferedSize.x, constrainedSize.x); |
| int height = Math.max(preferedSize.y, constrainedSize.y); |
| |
| return new Point(width, height); |
| } |
| |
| /** |
| * Create content of the hover. This is called after the input has been set. |
| */ |
| protected void deferredCreateContent() { |
| if(region != null) { |
| final ScrolledComposite scrolledComposite = new ScrolledComposite(parent, SWT.V_SCROLL); |
| GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); |
| scrolledComposite.setLayoutData(gridData); |
| scrolledComposite.setExpandVertical(true); |
| scrolledComposite.setExpandHorizontal(true); |
| Composite composite = new Composite(scrolledComposite, SWT.NONE); |
| GridLayout layout = new GridLayout(1, false); |
| composite.setLayout(layout); |
| scrolledComposite.setContent(composite); |
| |
| // force resize of scrolledComposite when its content height changes |
| composite.addListener(SWT.Resize, new Listener() { |
| int width = -1; |
| |
| public void handleEvent(Event e) { |
| int newWidth = composite.getSize().x; |
| if(newWidth != width) { |
| scrolledComposite.setMinHeight(composite.computeSize(newWidth, SWT.DEFAULT).y); |
| width = newWidth; |
| } |
| } |
| }); |
| |
| boolean lifecycleMarkers = false; |
| for(IRegion reg : region.getRegions()) { |
| if(reg instanceof PomHyperlinkDetector.MarkerRegion) { |
| PomHyperlinkDetector.MarkerRegion markerReg = (PomHyperlinkDetector.MarkerRegion) reg; |
| IMarker mark = markerReg.getAnnotation().getMarker(); |
| if(MavenDiscoveryMarkerResolutionGenerator.canResolve(mark)) { |
| lifecycleMarkers = true; |
| break; |
| } |
| } |
| } |
| fillToolbar(lifecycleMarkers); |
| |
| for(IRegion reg : region.getRegions()) { |
| if(reg instanceof PomHyperlinkDetector.MarkerRegion) { |
| final PomHyperlinkDetector.MarkerRegion markerReg = (PomHyperlinkDetector.MarkerRegion) reg; |
| createAnnotationInformation(composite, markerReg); |
| final IMarker mark = markerReg.getAnnotation().getMarker(); |
| |
| if(MavenProblemResolution.hasResolutions(mark)) { |
| List<IMarkerResolution> resolutions = MavenProblemResolution.getResolutions(mark); |
| createResolutionsControl(composite, mark, resolutions); |
| } |
| } |
| if(reg instanceof ManagedArtifactRegion) { |
| final ManagedArtifactRegion man = (ManagedArtifactRegion) reg; |
| Composite comp = createTooltipComposite(composite, PomTextHover.getLabelForRegion(man)); |
| //only create the hyperlink when the origin location for jumping is present. |
| //in some cases (managed version comes from imported dependencies) we don't have the location and have nowhere to jump) |
| if(PomHyperlinkDetector.canCreateHyperLink(man)) { |
| Link link = createHyperlink(comp); |
| link.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| dispose(); |
| PomHyperlinkDetector.createHyperlink(man).open(); |
| } |
| }); |
| } |
| |
| } |
| if(reg instanceof ExpressionRegion) { |
| final ExpressionRegion expr = (ExpressionRegion) reg; |
| Composite tooltipComposite = createTooltipComposite(composite, PomTextHover.getLabelForRegion(expr)); |
| if(PomHyperlinkDetector.canCreateHyperLink(expr)) { |
| Link link = createHyperlink(tooltipComposite); |
| link.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| dispose(); |
| PomHyperlinkDetector.createHyperlink(expr).open(); |
| } |
| }); |
| } |
| } |
| if(region.getRegions().indexOf(reg) < region.getRegions().size() - 1) { |
| createSeparator(composite); |
| } |
| } |
| |
| Point constraints = getSizeConstraints(); |
| Point contentSize = composite.computeSize(constraints != null ? constraints.x : SWT.DEFAULT, SWT.DEFAULT); |
| |
| composite.setSize(new Point(contentSize.x, contentSize.y)); //12 is the magic number for height of status line |
| |
| } |
| |
| setColorAndFont(parent, parent.getForeground(), parent.getBackground(), JFaceResources.getDialogFont()); |
| |
| parent.layout(true); |
| } |
| |
| protected void fillToolbar(boolean includeLifecycle) { |
| ToolBarManager toolBarManager = getToolBarManager(); |
| if(toolBarManager == null) |
| return; |
| toolBarManager.add(new OpenPreferencesAction(this, // |
| MvnImages.IMGD_WARNINGS, Messages.MarkerHoverControl_openWarningsPrefs, // |
| "org.eclipse.m2e.core.ui.preferences.WarningsPreferencePage")); //$NON-NLS-1$ |
| |
| if(includeLifecycle) { |
| toolBarManager.add(new OpenPreferencesAction(this, // |
| MvnImages.IMGD_EXECUTION, Messages.MarkerHoverControl_openLifecyclePrefs, // |
| "org.eclipse.m2e.core.preferences.LifecycleMappingPreferencePag")); //$NON-NLS-1$ |
| toolBarManager.add(new OpenPreferencesAction(this, // |
| MvnImages.IMGD_DISCOVERY, Messages.MarkerHoverControl_openDiscoveryPrefs, // |
| "org.eclipse.m2e.discovery.internal.preferences.DiscoveryPreferencePage")); //$NON-NLS-1$ |
| } |
| toolBarManager.update(true); |
| } |
| |
| private Link createHyperlink(Composite parent) { |
| Link link = new Link(parent, SWT.NONE); |
| GridData data2 = new GridData(SWT.FILL, SWT.FILL, true, true); |
| data2.horizontalIndent = 18; |
| link.setLayoutData(data2); |
| link.setText(Messages.PomTextHover_jump_to); |
| return link; |
| } |
| |
| private Composite createTooltipComposite(Composite parent, StyledString text) { |
| Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); |
| GridLayout layout = new GridLayout(2, false); |
| layout.marginHeight = 2; |
| layout.marginWidth = 2; |
| layout.horizontalSpacing = 0; |
| composite.setLayout(layout); |
| |
| //this paints the icon.. |
| final Canvas canvas = new Canvas(composite, SWT.NO_FOCUS); |
| GridData gridData = new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false); |
| gridData.widthHint = 17; |
| gridData.heightHint = 16; |
| canvas.setLayoutData(gridData); |
| |
| //and now comes the text |
| StyledText styledtext = new StyledText(composite, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY); |
| GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| |
| styledtext.setLayoutData(data); |
| styledtext.setText(text.getString()); |
| styledtext.setStyleRanges(text.getStyleRanges()); |
| |
| new Label(composite, SWT.NONE); |
| |
| return composite; |
| } |
| |
| private void setColorAndFont(Control control, Color foreground, Color background, Font font) { |
| control.setForeground(foreground); |
| control.setBackground(background); |
| control.setFont(font); |
| |
| if(control instanceof Composite) { |
| Control[] children = ((Composite) control).getChildren(); |
| for(int i = 0; i < children.length; i++ ) { |
| setColorAndFont(children[i], foreground, background, font); |
| } |
| } |
| } |
| |
| private void createAnnotationInformation(Composite parent, final MarkerRegion annotation) { |
| Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); |
| GridLayout layout = new GridLayout(2, false); |
| layout.marginHeight = 2; |
| layout.marginWidth = 2; |
| layout.horizontalSpacing = 0; |
| composite.setLayout(layout); |
| |
| //this paints the icon.. |
| final Canvas canvas = new Canvas(composite, SWT.NO_FOCUS); |
| GridData gridData = new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false); |
| gridData.widthHint = 17; |
| gridData.heightHint = 16; |
| canvas.setLayoutData(gridData); |
| canvas.addPaintListener(e -> { |
| e.gc.setFont(null); |
| markerAccess.paint(annotation.getAnnotation(), e.gc, canvas, new Rectangle(0, 0, 16, 16)); |
| }); |
| |
| //and now comes the text |
| StyledText text = new StyledText(composite, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY); |
| GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| text.setLayoutData(data); |
| String annotationText = annotation.getAnnotation().getText(); |
| if(annotationText != null) { |
| text.setText(annotationText); |
| } |
| if(annotation.isDefinedInParent()) { |
| new Label(composite, SWT.NONE); |
| |
| Link link = new Link(composite, SWT.NONE); |
| GridData data2 = new GridData(SWT.FILL, SWT.FILL, true, true); |
| data2.horizontalIndent = 18; |
| link.setLayoutData(data2); |
| link.setText(Messages.MarkerHoverControl_openParentDefinition); |
| link.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| PomHyperlinkDetector.createHyperlink(annotation).open(); |
| dispose(); |
| } |
| }); |
| } |
| |
| } |
| |
| private void createSeparator(Composite parent) { |
| Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); |
| GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false); |
| gridData.verticalIndent = 2; |
| separator.setLayoutData(gridData); |
| } |
| |
| private void createResolutionsControl(Composite parent, IMarker mark, List<IMarkerResolution> resolutions) { |
| Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); |
| GridLayout layout = new GridLayout(1, false); |
| layout.marginWidth = 0; |
| layout.verticalSpacing = 2; |
| layout.marginHeight = 0; |
| composite.setLayout(layout); |
| |
| Label quickFixLabel = new Label(composite, SWT.NONE); |
| GridData layoutData = new GridData(SWT.BEGINNING, SWT.TOP, false, false); |
| layoutData.horizontalIndent = 4; |
| quickFixLabel.setLayoutData(layoutData); |
| String text; |
| |
| if(resolutions.size() == 1) { |
| text = Messages.PomTextHover_one_quickfix; |
| } else { |
| text = NLS.bind(Messages.PomTextHover_more_quickfixes, String.valueOf(resolutions.size())); |
| } |
| quickFixLabel.setText(text); |
| |
| Composite composite2 = new Composite(parent, SWT.NONE); |
| composite2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); |
| GridLayout layout2 = new GridLayout(2, false); |
| layout2.marginLeft = 5; |
| layout2.verticalSpacing = 2; |
| composite2.setLayout(layout2); |
| |
| List<Link> list = new ArrayList<>(); |
| for(IMarkerResolution r : resolutions) { |
| list.add(createCompletionProposalLink(composite2, mark, r, 1));// Original link for single fix, hence pass 1 for count |
| |
| } |
| final Link[] links = list.toArray(new Link[list.size()]); |
| |
| focusControl = links.length == 0 ? null : links[0]; |
| for(int i = 0; i < links.length; i++ ) { |
| final int index = i; |
| final Link link = links[index]; |
| link.addKeyListener(new KeyListener() { |
| public void keyPressed(KeyEvent e) { |
| switch(e.keyCode) { |
| case SWT.ARROW_DOWN: |
| if(index + 1 < links.length) { |
| links[index + 1].setFocus(); |
| } |
| break; |
| case SWT.ARROW_UP: |
| if(index > 0) { |
| links[index - 1].setFocus(); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| public void keyReleased(KeyEvent e) { |
| } |
| }); |
| |
| } |
| } |
| |
| private Link createCompletionProposalLink(Composite parent, final IMarker mark, final IMarkerResolution proposal, |
| int count) { |
| final boolean isMultiFix = count > 1; |
| if(isMultiFix) { |
| new Label(parent, SWT.NONE); // spacer to fill image cell |
| parent = new Composite(parent, SWT.NONE); // indented composite for multi-fix |
| GridLayout layout = new GridLayout(2, false); |
| layout.marginWidth = 0; |
| layout.marginHeight = 0; |
| parent.setLayout(layout); |
| } |
| |
| Label proposalImage = new Label(parent, SWT.NONE); |
| proposalImage.setLayoutData(new GridData(SWT.BEGINNING, SWT.TOP, false, false)); |
| Image image = null; |
| if(proposal instanceof ICompletionProposal) { |
| image = ((ICompletionProposal) proposal).getImage(); |
| } else if(proposal instanceof IMarkerResolution2) { |
| image = ((IMarkerResolution2) proposal).getImage(); |
| } |
| if(image != null) { |
| proposalImage.setImage(image); |
| |
| proposalImage.addMouseListener(new MouseListener() { |
| |
| public void mouseDoubleClick(MouseEvent e) { |
| } |
| |
| public void mouseDown(MouseEvent e) { |
| } |
| |
| public void mouseUp(MouseEvent e) { |
| if(e.button == 1) { |
| apply(proposal, mark, region.textViewer, region.textOffset); |
| } |
| } |
| }); |
| } |
| |
| Link proposalLink = new Link(parent, SWT.WRAP); |
| GridData layoutData = new GridData(SWT.BEGINNING, SWT.TOP, false, false); |
| String linkText; |
| if(isMultiFix) { |
| linkText = NLS.bind(Messages.PomTextHover_category_fix, Integer.valueOf(count)); |
| } else { |
| linkText = proposal.getLabel(); |
| } |
| proposalLink.setText("<a>" + linkText + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$ |
| proposalLink.setLayoutData(layoutData); |
| proposalLink.addSelectionListener(new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| apply(proposal, mark, region.textViewer, region.textOffset); |
| } |
| }); |
| return proposalLink; |
| } |
| |
| /** |
| * {@inheritDoc} This default implementation returns <code>null</code>. Subclasses may override. |
| */ |
| public IInformationControlCreator getInformationPresenterControlCreator() { |
| return parent -> new MarkerHoverControl(parent, new ToolBarManager(SWT.FLAT)); |
| } |
| |
| private void apply(IMarkerResolution res, IMarker mark, ITextViewer viewer, int offset) { |
| if(res instanceof ICompletionProposal) { |
| apply((ICompletionProposal) res, viewer, offset, false); |
| } else { |
| dispose(); |
| res.run(mark); |
| } |
| } |
| |
| private void apply(ICompletionProposal p, ITextViewer viewer, int offset, boolean isMultiFix) { |
| //Focus needs to be in the text viewer, otherwise linked mode does not work |
| dispose(); |
| |
| IRewriteTarget target = null; |
| try { |
| IDocument document = viewer.getDocument(); |
| |
| if(viewer instanceof ITextViewerExtension) { |
| ITextViewerExtension extension = (ITextViewerExtension) viewer; |
| target = extension.getRewriteTarget(); |
| } |
| |
| if(target != null) |
| target.beginCompoundChange(); |
| |
| if(p instanceof ICompletionProposalExtension2) { |
| ICompletionProposalExtension2 e = (ICompletionProposalExtension2) p; |
| e.apply(viewer, (char) 0, isMultiFix ? SWT.CONTROL : SWT.NONE, offset); |
| } else if(p instanceof ICompletionProposalExtension) { |
| ICompletionProposalExtension e = (ICompletionProposalExtension) p; |
| e.apply(document, (char) 0, offset); |
| } else { |
| p.apply(document); |
| } |
| |
| Point selection = p.getSelection(document); |
| if(selection != null) { |
| viewer.setSelectedRange(selection.x, selection.y); |
| viewer.revealRange(selection.x, selection.y); |
| } |
| } finally { |
| if(target != null) |
| target.endCompoundChange(); |
| } |
| } |
| |
| private static final class OpenPreferencesAction extends Action { |
| |
| private final IInformationControl infoControl; |
| |
| private String prefsId; |
| |
| public OpenPreferencesAction(IInformationControl infoControl, ImageDescriptor imageDesc, String tooltip, |
| String prefsId) { |
| this.infoControl = infoControl; |
| this.prefsId = prefsId; |
| setImageDescriptor(imageDesc); |
| setToolTipText(tooltip); |
| } |
| |
| @Override |
| public void run() { |
| Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); |
| infoControl.dispose(); |
| PreferencesUtil.createPreferenceDialogOn(shell, prefsId, null, null).open(); |
| } |
| } |
| } |