From c297330c9cdcf0c8ba32768476c2a96fc0b9a32c Mon Sep 17 00:00:00 2001 From: William Riley Date: Tue, 8 Mar 2016 13:39:56 -0500 Subject: [PATCH] Bug 476797 - Port Expand annotation hover from JDT Ported the JDT expand annotation hover code into CDT & adapted. Added preference to control in equivalent location to JDT. Default is disabled for now. Changed behaviour from JDT version - * Breakpoint annotations & add breakpoint option displayed last * Tooltips displayed with no delay after expanded hover is displayed * Reverted fix for bug 165533 due to issue where single click on 1st item in expanded hover also triggers single click on top item in ruler if mouse within ruler area (Same as JDT) Known issues - * Double click on ruler column sometimes triggers single click on 1st item in expanded hover if user is too slow (Same as JDT) Change-Id: I87c2f8efd04ea5084b056241a04758a368e2ca55 Signed-off-by: William Riley --- core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF | 2 +- core/org.eclipse.cdt.ui/pom.xml | 2 +- .../internal/ui/editor/CDocumentProvider.java | 4 +- .../cdt/internal/ui/editor/CEditor.java | 48 +- .../ui/editor/CSelectMarkerRulerAction.java | 130 +++ .../CEditorHoverConfigurationBlock.java | 48 +- .../ui/preferences/PreferencesMessages.java | 3 +- .../PreferencesMessages.properties | 3 +- .../text/c/hover/AnnotationExpandHover.java | 331 ++++++ .../c/hover/AnnotationExpansionControl.java | 955 ++++++++++++++++++ .../ui/text/c/hover/CExpandHover.java | 234 +++++ .../ui/text/c/hover/CHoverMessages.java | 3 +- .../ui/text/c/hover/CHoverMessages.properties | 3 +- .../eclipse/cdt/ui/PreferenceConstants.java | 15 +- 14 files changed, 1765 insertions(+), 16 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSelectMarkerRulerAction.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/AnnotationExpandHover.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/AnnotationExpansionControl.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CExpandHover.java diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index 9e6eb758184..262e811d3e3 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true -Bundle-Version: 6.0.0.qualifier +Bundle-Version: 6.1.0.qualifier Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/core/org.eclipse.cdt.ui/pom.xml b/core/org.eclipse.cdt.ui/pom.xml index e4e16a93917..c8420d7b260 100644 --- a/core/org.eclipse.cdt.ui/pom.xml +++ b/core/org.eclipse.cdt.ui/pom.xml @@ -11,7 +11,7 @@ ../../pom.xml - 6.0.0-SNAPSHOT + 6.1.0-SNAPSHOT org.eclipse.cdt.ui eclipse-plugin diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java index aaae306f9c6..11e45eefb17 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2015 QNX Software Systems and others. + * Copyright (c) 2002, 2016 QNX Software Systems 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 @@ -107,7 +107,7 @@ public class CDocumentProvider extends TextFileDocumentProvider { /** * Annotation representing an {@code IProblem}. */ - static protected class ProblemAnnotation extends Annotation implements ICAnnotation { + public static class ProblemAnnotation extends Annotation implements ICAnnotation { private static final String INDEXER_ANNOTATION_TYPE= "org.eclipse.cdt.ui.indexmarker"; //$NON-NLS-1$ private final ITranslationUnit fTranslationUnit; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index a7962c7c862..fc9c2e57aa5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2016 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 @@ -97,6 +97,8 @@ import org.eclipse.jface.text.link.LinkedModeUI.IExitPolicy; import org.eclipse.jface.text.link.LinkedPosition; import org.eclipse.jface.text.link.LinkedPositionGroup; import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.AnnotationRulerColumn; +import org.eclipse.jface.text.source.CompositeRuler; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.IAnnotationModelExtension; import org.eclipse.jface.text.source.IAnnotationModelExtension2; @@ -105,11 +107,14 @@ import org.eclipse.jface.text.source.IOverviewRuler; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.ISourceViewerExtension2; import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.IVerticalRulerColumn; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; import org.eclipse.jface.text.source.projection.ProjectionSupport; import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; @@ -136,6 +141,7 @@ import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPartService; +import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionContext; @@ -232,6 +238,7 @@ import org.eclipse.cdt.internal.ui.text.DocumentCharacterIterator; import org.eclipse.cdt.internal.ui.text.ICReconcilingListener; import org.eclipse.cdt.internal.ui.text.Symbols; import org.eclipse.cdt.internal.ui.text.TabsToSpacesConverter; +import org.eclipse.cdt.internal.ui.text.c.hover.CExpandHover; import org.eclipse.cdt.internal.ui.text.c.hover.SourceViewerInformationControl; import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference; import org.eclipse.cdt.internal.ui.util.CUIHelp; @@ -2347,6 +2354,10 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi action.setActionDefinitionId(ICEditorActionDefinitionIds.SELECT_LAST); setAction(StructureSelectionAction.HISTORY, action); + // add annotation actions for roll-over expand hover + action= new CSelectMarkerRulerAction(bundle, "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$ + setAction("AnnotationAction", action); //$NON-NLS-1$ + // Assorted action groupings fSelectionSearchGroup = createSelectionSearchGroup(); @@ -3651,4 +3662,39 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi public void removePostSaveListener(IPostSaveListener listener) { fPostSaveListeners.remove(listener); } + + @Override + protected IVerticalRulerColumn createAnnotationRulerColumn(CompositeRuler ruler) { + if (!getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER)) { + return super.createAnnotationRulerColumn(ruler); + } + + AnnotationRulerColumn column= new AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess()); + column.setHover(new CExpandHover(ruler, getAnnotationAccess(), new IDoubleClickListener() { + + @Override + public void doubleClick(DoubleClickEvent event) { + // for now: just invoke ruler double click action + triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK); + } + + private void triggerAction(String actionID) { + IAction action= getAction(actionID); + if (action != null) { + if (action instanceof IUpdate) + ((IUpdate) action).update(); + // hack to propagate line change + if (action instanceof ISelectionListener) { + ((ISelectionListener)action).selectionChanged(null, null); + } + if (action.isEnabled()) { + action.run(); + } + } + } + + })); + + return column; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSelectMarkerRulerAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSelectMarkerRulerAction.java new file mode 100644 index 00000000000..0fbf8813a01 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSelectMarkerRulerAction.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2000, 2016 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 + * William Riley (Renesas) - Adapted for CDT + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.editor; + +import java.util.ResourceBundle; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Event; + +import org.eclipse.jface.action.IAction; + +import org.eclipse.jface.text.ITextOperationTarget; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.VerticalRulerEvent; + +import org.eclipse.ui.ISelectionListener; + +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.ITextEditorActionConstants; +import org.eclipse.ui.texteditor.IUpdate; +import org.eclipse.ui.texteditor.SelectAnnotationRulerAction; + +import org.eclipse.cdt.internal.ui.text.correction.CCorrectionProcessor; +import org.eclipse.cdt.internal.ui.text.correction.QuickAssistLightBulbUpdater.AssistAnnotation; +import org.eclipse.cdt.internal.ui.text.c.hover.CExpandHover; + +/** + * A special select marker ruler action which activates quick fix if clicked on a quick fixable problem. + *

+ * Originally copied from org.eclipse.jdt.internal.ui.javaeditor.JavaSelectMarkerRulerAction + */ +public class CSelectMarkerRulerAction extends SelectAnnotationRulerAction { + + public CSelectMarkerRulerAction(ResourceBundle bundle, String prefix, ITextEditor editor) { + super(bundle, prefix, editor); + } + + /* + * @see org.eclipse.ui.texteditor.IVerticalRulerListener#annotationDefaultSelected(org.eclipse.ui.texteditor.VerticalRulerEvent) + */ + @Override + public void annotationDefaultSelected(VerticalRulerEvent event) { + Annotation annotation= event.getSelectedAnnotation(); + IAnnotationModel model= getAnnotationModel(); + + if (isOverrideIndicator(annotation)) { + ((OverrideIndicatorManager.OverrideIndicator)annotation).open(); + return; + } + + if (isBreakpoint(annotation)) + triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK, event.getEvent()); + + Position position= model.getPosition(annotation); + if (position == null) + return; + + if (isQuickFixTarget(annotation)) { + ITextOperationTarget operation= getTextEditor().getAdapter(ITextOperationTarget.class); + final int opCode= ISourceViewer.QUICK_ASSIST; + if (operation != null && operation.canDoOperation(opCode)) { + getTextEditor().selectAndReveal(position.getOffset(), position.getLength()); + operation.doOperation(opCode); + return; + } + } + + // default: + super.annotationDefaultSelected(event); + } + + /** + * Tells whether the given annotation is an override annotation. + * + * @param annotation the annotation + * @return true iff the annotation is an override annotation + */ + private boolean isOverrideIndicator(Annotation annotation) { + return annotation instanceof OverrideIndicatorManager.OverrideIndicator; + } + + /** + * Checks whether the given annotation is a breakpoint annotation. + * + * @param annotation the annotation + * @return true if the annotation is a breakpoint annotation + */ + private boolean isBreakpoint(Annotation annotation) { + return annotation.getType().equals("org.eclipse.cdt.debug.core.breakpoint") || annotation.getType().equals(CExpandHover.NO_BREAKPOINT_ANNOTATION); //$NON-NLS-1$ + } + + private boolean isQuickFixTarget(Annotation a) { + return CCorrectionProcessor.hasCorrections(a) || a instanceof AssistAnnotation; + } + + private void triggerAction(String actionID, Event event) { + IAction action= getTextEditor().getAction(actionID); + if (action != null) { + if (action instanceof IUpdate) + ((IUpdate) action).update(); + // hack to propagate line change + if (action instanceof ISelectionListener) { + ((ISelectionListener)action).selectionChanged(null, null); + } + if (action.isEnabled()) { + if (event == null) { + action.run(); + } else { + event.type= SWT.MouseDoubleClick; + event.count= 2; + action.runWithEvent(event); + } + } + } + } + +} + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorHoverConfigurationBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorHoverConfigurationBlock.java index 90376a12681..a844a0a3952 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorHoverConfigurationBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/CEditorHoverConfigurationBlock.java @@ -14,6 +14,8 @@ package org.eclipse.cdt.internal.ui.preferences; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.StringTokenizer; import org.eclipse.core.runtime.Assert; @@ -44,6 +46,7 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; 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.Label; @@ -155,6 +158,19 @@ public class CEditorHoverConfigurationBlock implements IPreferenceConfigurationB private TableColumn fNameColumn; private TableColumn fModifierColumn; private Text fDescription; + private Map fCheckBoxes= new HashMap<>(); + private SelectionListener fCheckBoxListener= new SelectionListener() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + Button button= (Button) e.widget; + fStore.setValue(fCheckBoxes.get(button), button.getSelection()); + } + @Override + public void widgetSelected(SelectionEvent e) { + Button button= (Button) e.widget; + fStore.setValue(fCheckBoxes.get(button), button.getSelection()); + } + }; private PreferencePage fMainPreferencePage; @@ -173,7 +189,7 @@ public class CEditorHoverConfigurationBlock implements IPreferenceConfigurationB ArrayList overlayKeys= new ArrayList(); - //overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER)); + overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS)); overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.STRING, PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIER_MASKS)); @@ -204,9 +220,8 @@ public class CEditorHoverConfigurationBlock implements IPreferenceConfigurationB hoverComposite.setLayout(layout); hoverComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); - //String rollOverLabel= PreferencesMessages.getString("CEditorHoverConfigurationBlock.annotationRollover"); //$NON-NLS-1$ - //addCheckBox(hoverComposite, rollOverLabel, PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER, 0); //$NON-NLS-1$ - + String rollOverLabel= PreferencesMessages.CEditorHoverConfigurationBlock_annotationRollover; + addCheckBox(hoverComposite, rollOverLabel, PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER, 0); //$NON-NLS-1$ //addFiller(hoverComposite); Label label= new Label(hoverComposite, SWT.NONE); @@ -384,7 +399,14 @@ public class CEditorHoverConfigurationBlock implements IPreferenceConfigurationB void initializeFields() { fModifierEditor.setEnabled(false); - + + Iterator