From b6a8f778f93202ef41b024ae6971ad6cf0139e70 Mon Sep 17 00:00:00 2001 From: Jonah Graham Date: Tue, 15 Jun 2021 15:02:08 -0400 Subject: [PATCH] Bug 546981: Add #pragma mark to Outline view Adds #pragma mark support to outline view. With mark, dashes (-) cause divider lines before/after the mark label. When outline is sorted, the divider lines are omitted (lest they appear all grouped at the bottom of the view). The system property org.eclipse.cdt.core.model_include_pragmas can be set to false in case there are side effects of introducing IPragma elements to the CModel. This change applies to the Outline view and the Quick Outline (Ctrl-o) information popup. Icons contributed by Greg Willits. Also-by: Greg Willits Change-Id: I072ef26fb14e21b5453f909bade391a3f0521823 --- .../core/model/tests/CModelElementsTests.java | 64 ++++++++++ .../cfiles/CModelElementsTestStart.h | 13 ++- .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 2 +- .../org/eclipse/cdt/core/model/ICElement.java | 6 + .../org/eclipse/cdt/core/model/IPragma.java | 54 +++++++++ .../internal/core/model/CModelBuilder2.java | 46 ++++++++ .../cdt/internal/core/model/Pragma.java | 109 ++++++++++++++++++ core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF | 4 +- core/org.eclipse.cdt.ui/css/e4-dark_cdt.css | 2 + .../icons/dlcl16/outline_mark.png | Bin 0 -> 142 bytes .../icons/dlcl16/outline_mark@2x.png | Bin 0 -> 168 bytes .../icons/elcl16/outline_mark.png | Bin 0 -> 142 bytes .../icons/elcl16/outline_mark@2x.png | Bin 0 -> 168 bytes .../icons/obj16/outline_mark.png | Bin 0 -> 142 bytes .../icons/obj16/outline_mark@2x.png | Bin 0 -> 168 bytes core/org.eclipse.cdt.ui/plugin.properties | 9 ++ core/org.eclipse.cdt.ui/plugin.xml | 34 ++++++ .../ui/BaseCElementContentProvider.java | 80 ++++++++++++- .../cdt/internal/ui/CPluginImages.java | 1 + .../internal/ui/actions/ActionMessages.java | 3 + .../ui/actions/ActionMessages.properties | 4 + .../cdt/internal/ui/cview/DividerLine.java | 48 ++++++++ .../ui/editor/AbstractCModelOutlinePage.java | 46 +++++++- .../ui/editor/CContentOutlinerProvider.java | 16 ++- .../preferences/AppearancePreferencePage.java | 9 ++ .../ui/preferences/PreferencesMessages.java | 1 + .../PreferencesMessages.properties | 1 + .../ui/text/COutlineInformationControl.java | 4 +- .../ui/viewsupport/CElementImageProvider.java | 12 ++ .../ui/viewsupport/CElementLabelComposer.java | 52 +++++++++ .../DecoratingCOutlineLabelProvider.java | 77 +++++++++++++ .../org/eclipse/cdt/ui/CDTSharedImages.java | 3 + .../cdt/ui/CElementContentProvider.java | 2 +- .../eclipse/cdt/ui/PreferenceConstants.java | 26 +++++ 34 files changed, 714 insertions(+), 14 deletions(-) create mode 100644 core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPragma.java create mode 100644 core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Pragma.java create mode 100644 core/org.eclipse.cdt.ui/icons/dlcl16/outline_mark.png create mode 100644 core/org.eclipse.cdt.ui/icons/dlcl16/outline_mark@2x.png create mode 100644 core/org.eclipse.cdt.ui/icons/elcl16/outline_mark.png create mode 100644 core/org.eclipse.cdt.ui/icons/elcl16/outline_mark@2x.png create mode 100644 core/org.eclipse.cdt.ui/icons/obj16/outline_mark.png create mode 100644 core/org.eclipse.cdt.ui/icons/obj16/outline_mark@2x.png create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/DividerLine.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCOutlineLabelProvider.java diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java index 00920e6bb1a..5c648109821 100644 --- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelElementsTests.java @@ -35,6 +35,7 @@ import org.eclipse.cdt.core.model.IMethodDeclaration; import org.eclipse.cdt.core.model.IMethodTemplateDeclaration; import org.eclipse.cdt.core.model.INamespace; import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.core.model.IPragma; import org.eclipse.cdt.core.model.ISourceRange; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.IStructure; @@ -137,6 +138,69 @@ public class CModelElementsTests extends BaseTestCase { checkBug180815(tu); checkBug352350(tu); + + checkPragmas(tu); + } + + private void checkPragmas(ITranslationUnit tu) throws CModelException { + List pragmas = tu.getChildrenOfType(ICElement.C_PRAGMA); + + int line = 0; + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("mark - before and after -", pragma.getElementName()); + assertEquals(true, pragma.getPragmaMarkInfo().get().isDividerBeforeMark()); + assertEquals(true, pragma.getPragmaMarkInfo().get().isDividerAfterMark()); + assertEquals("before and after", pragma.getPragmaMarkInfo().get().getMarkName()); + } + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("mark - before", pragma.getElementName()); + assertEquals(true, pragma.getPragmaMarkInfo().get().isDividerBeforeMark()); + assertEquals(false, pragma.getPragmaMarkInfo().get().isDividerAfterMark()); + assertEquals("before", pragma.getPragmaMarkInfo().get().getMarkName()); + } + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("mark after -", pragma.getElementName()); + assertEquals(false, pragma.getPragmaMarkInfo().get().isDividerBeforeMark()); + assertEquals(true, pragma.getPragmaMarkInfo().get().isDividerAfterMark()); + assertEquals("after", pragma.getPragmaMarkInfo().get().getMarkName()); + } + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("mark neither", pragma.getElementName()); + assertEquals(false, pragma.getPragmaMarkInfo().get().isDividerBeforeMark()); + assertEquals(false, pragma.getPragmaMarkInfo().get().isDividerAfterMark()); + assertEquals("neither", pragma.getPragmaMarkInfo().get().getMarkName()); + } + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("mark -", pragma.getElementName()); + assertEquals(true, pragma.getPragmaMarkInfo().get().isDividerBeforeMark()); + assertEquals(false, pragma.getPragmaMarkInfo().get().isDividerAfterMark()); + assertEquals("", pragma.getPragmaMarkInfo().get().getMarkName()); + } + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("mark", pragma.getElementName()); + assertEquals(false, pragma.getPragmaMarkInfo().get().isDividerBeforeMark()); + assertEquals(false, pragma.getPragmaMarkInfo().get().isDividerAfterMark()); + assertEquals("", pragma.getPragmaMarkInfo().get().getMarkName()); + } + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("ms_struct on", pragma.getElementName()); + assertEquals(true, pragma.getPragmaMarkInfo().isEmpty()); + assertEquals(false, pragma.isPragmaOperator()); + } + { + IPragma pragma = (IPragma) pragmas.get(line++); + assertEquals("_Pragma(\"once\")", pragma.getElementName()); + assertEquals(true, pragma.getPragmaMarkInfo().isEmpty()); + assertEquals(true, pragma.isPragmaOperator()); + } + assertEquals(line, pragmas.size()); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=180815 diff --git a/core/org.eclipse.cdt.core.tests/resources/cfiles/CModelElementsTestStart.h b/core/org.eclipse.cdt.core.tests/resources/cfiles/CModelElementsTestStart.h index d9736eff1d3..18ca36e0829 100644 --- a/core/org.eclipse.cdt.core.tests/resources/cfiles/CModelElementsTestStart.h +++ b/core/org.eclipse.cdt.core.tests/resources/cfiles/CModelElementsTestStart.h @@ -143,4 +143,15 @@ struct bug180815 { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=352350 namespace { int bug352350; -} \ No newline at end of file +} + +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=574271 +#pragma mark - before and after - +#pragma mark - before +#pragma mark after - +#pragma mark neither +#pragma mark -// blank1 +#pragma mark // blank2 +#pragma ms_struct on +_Pragma("once") + diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index d692c5c25be..8a329b9f158 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.core; singleton:=true -Bundle-Version: 7.2.200.qualifier +Bundle-Version: 7.3.0.qualifier Bundle-Activator: org.eclipse.cdt.core.CCorePlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java index 28034b42238..c4e069976ec 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/ICElement.java @@ -243,6 +243,12 @@ public interface ICElement extends IAdaptable { */ static final int ASM_LABEL = 94; + /** + * A pragma statement. + * @since 7.3 + */ + static final int C_PRAGMA = 95; + /** * @deprecated use {@link IMethodDeclaration#isConstructor()} * @noreference This field is not intended to be referenced by clients. diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPragma.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPragma.java new file mode 100644 index 00000000000..334f9ed971e --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/IPragma.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2021 Kichwa Coders Canada Inc. and others. + * + * 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 + *******************************************************************************/ + +package org.eclipse.cdt.core.model; + +import java.util.Optional; + +/** + * Represents a pragma statement. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @since 7.3 + */ +public interface IPragma extends ICElement, ISourceManipulation, ISourceReference { + + public interface PragmaMarkInfo { + /** + * Whether the pragma indicates a divider before it. + */ + public boolean isDividerBeforeMark(); + + /** + * Whether the pragma indicates a divider after it. + */ + public boolean isDividerAfterMark(); + + /** + * The display string of the mark. + */ + public String getMarkName(); + } + + /** + * Returns whether this uses the pragma operator syntax, e.g: _Pragma("once") + * @since 5.2 + */ + public boolean isPragmaOperator(); + + /** + * Returns the PragmaMarkInfo if the pragma represents a #pragma mark or similar pragma + * that should be interpreted as such. + * @return {@link Optional} of the {@link PragmaMarkInfo} + */ + Optional getPragmaMarkInfo(); +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java index 51253f7bc59..97c13fac1f5 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java @@ -43,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorFunctionStyleMacroDefinition; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration; @@ -109,6 +110,14 @@ public class CModelBuilder2 implements IContributedModelBuilder { private Stack fVisibilityStack; private HashMap fEqualElements; + /** + * To support the new feature "#pragma mark to Outline view" (Bug 546981) the model was updated + * to include pragmas. Because the model is widely used, this feature flag allows turning off + * including pragmas in the model. + */ + private static final boolean INCLUDE_PRAGMAS_IN_MODEL = Boolean + .parseBoolean(System.getProperty("org.eclipse.cdt.core.model_include_pragmas", "true")); //$NON-NLS-1$ //$NON-NLS-2$ + /** * Create a model builder for the given translation unit. * @@ -220,6 +229,12 @@ public class CModelBuilder2 implements IContributedModelBuilder { if (isLocalToFile(statement)) { createMacro(fTranslationUnit, (IASTPreprocessorMacroDefinition) statement); } + } else if (statement instanceof IASTPreprocessorPragmaStatement) { + if (INCLUDE_PRAGMAS_IN_MODEL) { + if (isLocalToFile(statement)) { + createPragma(fTranslationUnit, (IASTPreprocessorPragmaStatement) statement); + } + } } } @@ -320,6 +335,27 @@ public class CModelBuilder2 implements IContributedModelBuilder { return element; } + private Pragma createPragma(Parent parent, IASTPreprocessorPragmaStatement pragma) throws CModelException { + // Create element + String name; + if (pragma.isPragmaOperator()) { + name = pragma.getRawSignature(); + } else { + char[] message = pragma.getMessage(); + name = new String(message); + } + Pragma element = new Pragma(parent, name); + setIndex(element); + element.setActive(pragma.isActive()); + // Add to parent + parent.addChild(element); + // Set positions + setIdentifierPosition(element, pragma); + setBodyPosition(element, pragma); + element.setPragmaOperator(pragma.isPragmaOperator()); + return element; + } + private void createDeclaration(Parent parent, IASTDeclaration declaration) throws CModelException, DOMException { if (declaration instanceof IASTFunctionDefinition) { createFunctionDefinition(parent, (IASTFunctionDefinition) declaration, false); @@ -1219,6 +1255,16 @@ public class CModelBuilder2 implements IContributedModelBuilder { } } + /** + * Utility method to set the identifier position of an element from an AST node. + * + * @param element + * @param astNode + */ + private void setIdentifierPosition(SourceManipulation element, IASTNode astNode) { + setIdentifierPosition(getSourceManipulationInfo(element), astNode); + } + /** * Utility method to set the identifier position of an element from an AST name. * diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Pragma.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Pragma.java new file mode 100644 index 00000000000..b6ccc4570f0 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/Pragma.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2021 Kichwa Coders Canada Inc. and others. + * + * 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 + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.model; + +import java.util.Optional; +import java.util.StringTokenizer; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IPragma; + +public class Pragma extends SourceManipulation implements IPragma { + + private boolean isPragmaOperator = false; + private Optional pragmaMarkInfo = null; + + public Pragma(ICElement parent, String name) { + super(parent, name, ICElement.C_PRAGMA); + } + + private PragmaMarkInfo calculateMarkInfo(String name) { + String nameTrimmed = name.trim(); + + StringTokenizer tokenizer = new StringTokenizer(nameTrimmed); + if (tokenizer.hasMoreTokens()) { + + boolean dividerBeforeMark = false; + boolean dividerAfterMark = false; + String markName = ""; //$NON-NLS-1$ + + String pragmaName = tokenizer.nextToken(); + String restOfLine; + if (tokenizer.hasMoreTokens()) { + restOfLine = tokenizer.nextToken("").trim(); //$NON-NLS-1$ + } else { + restOfLine = ""; //$NON-NLS-1$ + } + switch (pragmaName) { + case "mark": { //$NON-NLS-1$ + if (restOfLine.startsWith("-")) { //$NON-NLS-1$ + dividerBeforeMark = true; + restOfLine = restOfLine.substring(1); + } + if (restOfLine.endsWith("-")) { //$NON-NLS-1$ + dividerAfterMark = true; + restOfLine = restOfLine.substring(0, restOfLine.length() - 1); + } + markName = restOfLine.trim(); + } + break; + default: + return null; + } + + boolean finalDividerBeforeMark = dividerBeforeMark; + boolean finalDividerAfterMark = dividerAfterMark; + String finalMarkName = markName; + return new PragmaMarkInfo() { + + @Override + public boolean isDividerBeforeMark() { + return finalDividerBeforeMark; + } + + @Override + public boolean isDividerAfterMark() { + return finalDividerAfterMark; + } + + @Override + public String getMarkName() { + return finalMarkName; + } + }; + } else { + return null; + } + } + + @Override + protected CElementInfo createElementInfo() { + return new SourceManipulationInfo(this); + } + + public void setPragmaOperator(boolean isPragmaOperator) { + this.isPragmaOperator = isPragmaOperator; + } + + @Override + public boolean isPragmaOperator() { + return isPragmaOperator; + } + + @Override + public Optional getPragmaMarkInfo() { + if (pragmaMarkInfo == null) { + pragmaMarkInfo = Optional.ofNullable(calculateMarkInfo(getElementName())); + } + return pragmaMarkInfo; + } +} diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index 334f57a3475..f29e47c1eea 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: 7.2.100.qualifier +Bundle-Version: 7.3.0.qualifier Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -102,7 +102,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.ui.wizards, org.eclipse.cdt.ui.wizards.conversion, org.eclipse.cdt.utils.ui.controls -Require-Bundle: org.eclipse.cdt.core;bundle-version="[7.0.0,8.0.0)", +Require-Bundle: org.eclipse.cdt.core;bundle-version="[7.3.0,8.0.0)", org.eclipse.compare;bundle-version="[3.7.700,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.6.500,4.0.0)", org.eclipse.core.filesystem;bundle-version="[1.7.500,2.0.0)", diff --git a/core/org.eclipse.cdt.ui/css/e4-dark_cdt.css b/core/org.eclipse.cdt.ui/css/e4-dark_cdt.css index 9de73825e4e..ef225ddadf5 100644 --- a/core/org.eclipse.cdt.ui/css/e4-dark_cdt.css +++ b/core/org.eclipse.cdt.ui/css/e4-dark_cdt.css @@ -82,4 +82,6 @@ IEclipsePreferences#org-eclipse-cdt-ui:org-eclipse-cdt-ui { IEclipsePreferences#org-eclipse-ui-workbench:org-eclipse-cdt-ui { /* pseudo attribute added to allow contributions without replacing this node, see Bug 466075 */ preferences: "org.eclipse.cdt.ui.ColoredLabels.writeaccess_highlight=255,128,128" + "org.eclipse.cdt.ui.outline.mark.textcolor=115,129,133" + "org.eclipse.cdt.ui.outline.mark.dividercolor=80,80,80" } diff --git a/core/org.eclipse.cdt.ui/icons/dlcl16/outline_mark.png b/core/org.eclipse.cdt.ui/icons/dlcl16/outline_mark.png new file mode 100644 index 0000000000000000000000000000000000000000..14a9e25681f86f639e6f2ef9b005dc61d53fd158 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X3_M*NLn>}1{rUgjo>{e_v(d>Qi$Rnp!BO1e;F^B(INg77 lDN9yyOSlVPDllMBIKbe=!6jY1L;z$XgQu&X%Q~loCIF2UDR2M) literal 0 HcmV?d00001 diff --git a/core/org.eclipse.cdt.ui/icons/dlcl16/outline_mark@2x.png b/core/org.eclipse.cdt.ui/icons/dlcl16/outline_mark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d4065a94a922b67b9f52aad59d3daad3d3ca0c3 GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GUY;(FAr-fh{`~)Mf7pRZt&NdwF`q=~ffdYdvIegj0@*hR z1Qj$z&R_KE(xdmT$1Z9}T;WTQ$rbFiO1Q!ZQ@Mwkfr*D}1{rUgjo>{e_v(d>Qi$Rnp!BO1e;F^B(INg77 lDN9yyOSlVPDllMBIKbe=!6jY1L;z$XgQu&X%Q~loCIF2UDR2M) literal 0 HcmV?d00001 diff --git a/core/org.eclipse.cdt.ui/icons/elcl16/outline_mark@2x.png b/core/org.eclipse.cdt.ui/icons/elcl16/outline_mark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d4065a94a922b67b9f52aad59d3daad3d3ca0c3 GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GUY;(FAr-fh{`~)Mf7pRZt&NdwF`q=~ffdYdvIegj0@*hR z1Qj$z&R_KE(xdmT$1Z9}T;WTQ$rbFiO1Q!ZQ@Mwkfr*D}1{rUgjo>{e_v(d>Qi$Rnp!BO1e;F^B(INg77 lDN9yyOSlVPDllMBIKbe=!6jY1L;z$XgQu&X%Q~loCIF2UDR2M) literal 0 HcmV?d00001 diff --git a/core/org.eclipse.cdt.ui/icons/obj16/outline_mark@2x.png b/core/org.eclipse.cdt.ui/icons/obj16/outline_mark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d4065a94a922b67b9f52aad59d3daad3d3ca0c3 GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GUY;(FAr-fh{`~)Mf7pRZt&NdwF`q=~ffdYdvIegj0@*hR z1Qj$z&R_KE(xdmT$1Z9}T;WTQ$rbFiO1Q!ZQ@Mwkfr*D + + + + + %COutline.mark.font.description + + + + + %COutline.mark.textcolor.description + + + + + %COutline.mark.dividercolor.description + + false); } - public BaseCElementContentProvider(boolean provideMembers, boolean provideWorkingCopy) { + /** + * + * @param provideMembers + * @param provideWorkingCopy + * @param providePragmaMarks Include {@link PragmaMark} and its {@link DividerLine}s + * @param isSorted is a non-null supplier that returns true if the content is sorted, this is used + * to remove {@link DividerLine}s when sorted + */ + public BaseCElementContentProvider(boolean provideMembers, boolean provideWorkingCopy, boolean providePragmaMarks, + BooleanSupplier isSorted) { + Assert.isNotNull(isSorted); fProvideMembers = provideMembers; fProvideWorkingCopy = provideWorkingCopy; + fProvidePragmaMarks = providePragmaMarks; + fIsSorted = isSorted; } /** @@ -187,6 +209,21 @@ public class BaseCElementContentProvider implements ITreeContentProvider { fMacroGrouping = enable; } + /** + * @return whether hiding pragma mark is enabled + */ + public boolean isHidePragmaMarkEnabled() { + return !fProvidePragmaMarks; + } + + /** + * Enable/disable hiding pragma mark + * @param enable + */ + public void setHidePragmaMark(boolean enable) { + fProvidePragmaMarks = !enable; + } + /* (non-Cdoc) * Method declared on IContentProvider. */ @@ -452,6 +489,7 @@ public class BaseCElementContentProvider implements ITreeContentProvider { protected Object[] getTranslationUnitChildren(ITranslationUnit unit) throws CModelException { Object[] children = unit.getChildren(); + children = filterAndTransformPragmas(children); if (fIncludesGrouping) { boolean hasInclude = false; ArrayList list = new ArrayList<>(children.length); @@ -538,6 +576,42 @@ public class BaseCElementContentProvider implements ITreeContentProvider { return children; } + /** + * Filter and transform pragma elements in the list + * @param children the list of objects + * @return a new list of objects + */ + private Object[] filterAndTransformPragmas(Object[] children) { + List list = new LinkedList<>(Arrays.asList(children)); + boolean isSorted = fIsSorted.getAsBoolean(); + for (ListIterator iterator = list.listIterator(); iterator.hasNext();) { + Object object = iterator.next(); + if (object instanceof IPragma) { + IPragma pragma = (IPragma) object; + // remove the pragma + iterator.remove(); + if (!fProvidePragmaMarks) { + continue; + } + + pragma.getPragmaMarkInfo().ifPresent(info -> { + if (!isSorted && info.isDividerBeforeMark()) { + iterator.add(new DividerLine(pragma)); + } + if (!info.getMarkName().isEmpty()) { + // Add the pragma back in if the mark has something to display + iterator.add(pragma); + } + if (!isSorted && info.isDividerAfterMark()) { + iterator.add(new DividerLine(pragma)); + } + }); + } + } + + return list.toArray(); + } + protected Object[] getNamespaceChildren(IParent element) throws CModelException { Object[] children = element.getChildren(); if (fMemberGrouping) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java index a69660fcbd9..85e1a497857 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java @@ -378,6 +378,7 @@ public class CPluginImages { public static final String IMG_MENU_SHIFT_LEFT = NAME_PREFIX + "shift_l_edit.gif"; //$NON-NLS-1$ public static final String IMG_MENU_OPEN_INCLUDE = NAME_PREFIX + "open_include.gif"; //$NON-NLS-1$ public static final String IMG_MENU_GROUP_INCLUDE = NAME_PREFIX + "group_include.gif"; //$NON-NLS-1$ + public static final String IMG_MENU_HIDE_PRAGMA_MARKS = NAME_PREFIX + "outline_mark.png"; //$NON-NLS-1$ public static final String IMG_MENU_SEGMENT_EDIT = NAME_PREFIX + "segment_edit.gif"; //$NON-NLS-1$ public static final String IMG_MENU_CODE_ASSIST = NAME_PREFIX + "metharg_obj.gif"; //$NON-NLS-1$ public static final String IMG_MENU_COLLAPSE_ALL = NAME_PREFIX + "collapseall.png"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java index 862faf82193..8617f1b40cd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.java @@ -111,6 +111,9 @@ public class ActionMessages extends NLS { public static String CopyQualifiedNameAction_ActionName; public static String CopyQualifiedNameAction_ErrorTitle; public static String CopyQualifiedNameAction_NoElementToQualify; + public static String HidePragmaMarks_label; + public static String HidePragmaMarks_tooltip; + public static String HidePragmaMarks_description; static { // Initialize resource bundle. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties index baeddfc01b3..626b2de4d34 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ActionMessages.properties @@ -77,6 +77,10 @@ MacroGroupingAction_label= Group Macros MacroGroupingAction_tooltip= Group macro definitions MacroGroupingAction_description= Group macro definitions +HidePragmaMarks_label=Hide Dividers +HidePragmaMarks_tooltip=Hide Dividers (#pragma mark) +HidePragmaMarks_description=Hide Dividers (#pragma mark) + COutlineInformationControl_viewMenu_sort_label=Sort ChangeBuildConfigMenuAction_title=Sorry diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/DividerLine.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/DividerLine.java new file mode 100644 index 00000000000..5352dbac6d8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/cview/DividerLine.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2021 Kichwa Coders Canada Inc. and others. + * + * 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 + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.cview; + +import org.eclipse.cdt.core.model.ISourceReference; +import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCOutlineLabelProvider; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.ui.model.WorkbenchAdapter; + +public class DividerLine extends WorkbenchAdapter implements IAdaptable { + + private ISourceReference element; + + public DividerLine(ISourceReference element) { + this.element = element; + } + + @Override + public T getAdapter(Class adapter) { + if (adapter == IWorkbenchAdapter.class) { + return adapter.cast(this); + } + if (adapter == ISourceReference.class) { + return adapter.cast(element); + } + return null; + } + + /** + * When owner draw is not enabled ( General > Appearance > Use mixed fonts and colors for labels.) + * the custom draw in {@link DecoratingCOutlineLabelProvider} is not used and therefore the + * entry uses the getLabel value to fill the entry. + * @see DecoratingCOutlineLabelProvider + */ + @Override + public String getLabel(Object object) { + return "-".repeat(20); //$NON-NLS-1$ + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AbstractCModelOutlinePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AbstractCModelOutlinePage.java index 93d0ffcca12..10f31d86dd8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AbstractCModelOutlinePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/AbstractCModelOutlinePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -37,7 +37,7 @@ import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; import org.eclipse.cdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; import org.eclipse.cdt.internal.ui.viewsupport.CElementLabels; import org.eclipse.cdt.internal.ui.viewsupport.CUILabelProvider; -import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCLabelProvider; +import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCOutlineLabelProvider; import org.eclipse.cdt.ui.CDTSharedImages; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.IncludesGrouping; @@ -52,6 +52,7 @@ import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.commands.ActionHandler; +import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.util.PropertyChangeEvent; @@ -60,6 +61,7 @@ import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; @@ -108,14 +110,18 @@ public abstract class AbstractCModelOutlinePage extends Page public COutlineLabelProvider(long textFlags, int imageFlags) { super(textFlags, imageFlags); + JFaceResources.getFontRegistry().addListener(this); PreferenceConstants.getPreferenceStore().addPropertyChangeListener(this); + PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().addListener(this); fSimpleName = PreferenceConstants.getPreferenceStore() .getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS); } @Override public void dispose() { + JFaceResources.getFontRegistry().removeListener(this); PreferenceConstants.getPreferenceStore().removePropertyChangeListener(this); + PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().removeListener(this); super.dispose(); } @@ -138,6 +144,15 @@ public abstract class AbstractCModelOutlinePage extends Page .getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS); } } + if (PreferenceConstants.OUTLINE_MARK_TEXT_FONT.equals(event.getProperty())) { + fireLabelProviderChanged(new LabelProviderChangedEvent(this)); + } + if (PreferenceConstants.OUTLINE_MARK_TEXT_COLOR.equals(event.getProperty())) { + fireLabelProviderChanged(new LabelProviderChangedEvent(this)); + } + if (PreferenceConstants.OUTLINE_MARK_DIVIDER_COLOR.equals(event.getProperty())) { + fireLabelProviderChanged(new LabelProviderChangedEvent(this)); + } } } @@ -240,6 +255,29 @@ public abstract class AbstractCModelOutlinePage extends Page } } + protected static class HidePragmaMarkAction extends Action { + + public HidePragmaMarkAction(AbstractCModelOutlinePage outlinePage) { + super(ActionMessages.HidePragmaMarks_label); + setDescription(ActionMessages.HidePragmaMarks_description); + setToolTipText(ActionMessages.HidePragmaMarks_tooltip); + CPluginImages.setImageDescriptors(this, CPluginImages.T_LCL, CPluginImages.IMG_MENU_HIDE_PRAGMA_MARKS); + + boolean enabled = isHidePragmaMarkEnabled(); + setChecked(enabled); + } + + @Override + public void run() { + PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.OUTLINE_HIDE_PRAGMA_MARK, + isChecked()); + } + + public boolean isHidePragmaMarkEnabled() { + return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_HIDE_PRAGMA_MARK); + } + } + /** * This action toggles whether this C Outline page links * its selection to the active editor. @@ -454,7 +492,7 @@ public abstract class AbstractCModelOutlinePage extends Page protected ProblemTreeViewer createTreeViewer(Composite parent) { ProblemTreeViewer treeViewer = new OutlineTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); treeViewer.setContentProvider(createContentProvider(treeViewer)); - treeViewer.setLabelProvider(new DecoratingCLabelProvider(createLabelProvider(), true)); + treeViewer.setLabelProvider(new DecoratingCOutlineLabelProvider(createLabelProvider())); treeViewer.setAutoExpandLevel(3); treeViewer.setUseHashlookup(true); treeViewer.addSelectionChangedListener(this); @@ -604,6 +642,8 @@ public abstract class AbstractCModelOutlinePage extends Page fToggleLinkingAction = new ToggleLinkingAction(); menu.add(fToggleLinkingAction); + menu.add(new Separator("dividers.layout")); //$NON-NLS-1$ + menu.add(new HidePragmaMarkAction(this)); menu.add(new Separator("group.layout")); //$NON-NLS-1$ menu.add(new IncludeGroupingAction(this)); menu.add(new MacroGroupingAction(this)); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java index 9da4664ef72..8bf77fb379b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinerProvider.java @@ -71,13 +71,18 @@ public class CContentOutlinerProvider extends BaseCElementContentProvider { * Tree viewer. */ public CContentOutlinerProvider(TreeViewer viewer, IWorkbenchPartSite site) { - super(true, true); + super(true, true, true, () -> isSorted(viewer)); treeViewer = viewer; final IPreferenceStore store = PreferenceConstants.getPreferenceStore(); setIncludesGrouping(store.getBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); setNamespacesGrouping(store.getBoolean(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)); setMemberGrouping(store.getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)); setMacroGrouping(store.getBoolean(PreferenceConstants.OUTLINE_GROUP_MACROS)); + setHidePragmaMark(store.getBoolean(PreferenceConstants.OUTLINE_HIDE_PRAGMA_MARK)); + } + + private static boolean isSorted(TreeViewer viewer) { + return viewer != null && viewer.getComparator() != null; } /** @@ -376,6 +381,15 @@ public class CContentOutlinerProvider extends BaseCElementContentProvider { contentUpdated(); } } + } else if (prop.equals(PreferenceConstants.OUTLINE_HIDE_PRAGMA_MARK)) { + Object newValue = event.getNewValue(); + if (newValue instanceof Boolean) { + boolean value = ((Boolean) newValue).booleanValue(); + if (isHidePragmaMarkEnabled() != value) { + setHidePragmaMark(value); + contentUpdated(); + } + } } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AppearancePreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AppearancePreferencePage.java index 23a90c5f6bf..56bc31a791a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AppearancePreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AppearancePreferencePage.java @@ -56,6 +56,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben private SelectionButtonDialogField fOutlineGroupMacros; private SelectionButtonDialogField fShowSourceRootsAtTopOfProject; private SelectionButtonDialogField fCViewSortOrderOfExcludedFiles; + private SelectionButtonDialogField fOutlineHidePragmaMarks; public AppearancePreferencePage() { setPreferenceStore(PreferenceConstants.getPreferenceStore()); @@ -102,6 +103,10 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fOutlineGroupMacros.setDialogFieldListener(listener); fOutlineGroupMacros.setLabelText(PreferencesMessages.AppearancePreferencePage_outlineGroupMacros_label); + fOutlineHidePragmaMarks = new SelectionButtonDialogField(SWT.CHECK); + fOutlineHidePragmaMarks.setDialogFieldListener(listener); + fOutlineHidePragmaMarks.setLabelText(PreferencesMessages.AppearancePreferencePage_HidePragmaMarks_label); + fCViewGroupMacros = new SelectionButtonDialogField(SWT.CHECK); fCViewGroupMacros.setDialogFieldListener(listener); fCViewGroupMacros.setLabelText(PreferencesMessages.AppearancePreferencePage_cviewGroupMacros_label); @@ -123,6 +128,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fOutlineGroupNamespaces.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)); fOutlineGroupMembers.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)); fOutlineGroupMacros.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_MACROS)); + fOutlineHidePragmaMarks.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_HIDE_PRAGMA_MARK)); boolean showSourceRootsAtTopOfProject = CCorePlugin.showSourceRootsAtTopOfProject(); fShowSourceRootsAtTopOfProject.setSelection(showSourceRootsAtTopOfProject); fCViewSortOrderOfExcludedFiles.setSelection(prefs.getBoolean(PreferenceConstants.SORT_ORDER_OF_EXCLUDED_FILES)); @@ -159,6 +165,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fOutlineGroupMembers.doFillIntoGrid(result, nColumns); fCViewGroupMacros.doFillIntoGrid(result, nColumns); fOutlineGroupMacros.doFillIntoGrid(result, nColumns); + fOutlineHidePragmaMarks.doFillIntoGrid(result, nColumns); new Separator().doFillIntoGrid(result, nColumns); @@ -216,6 +223,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben prefs.setValue(PreferenceConstants.OUTLINE_GROUP_NAMESPACES, fOutlineGroupNamespaces.isSelected()); prefs.setValue(PreferenceConstants.OUTLINE_GROUP_MEMBERS, fOutlineGroupMembers.isSelected()); prefs.setValue(PreferenceConstants.OUTLINE_GROUP_MACROS, fOutlineGroupMacros.isSelected()); + prefs.setValue(PreferenceConstants.OUTLINE_HIDE_PRAGMA_MARK, fOutlineHidePragmaMarks.isSelected()); prefs.setValue(PreferenceConstants.SORT_ORDER_OF_EXCLUDED_FILES, fCViewSortOrderOfExcludedFiles.isSelected()); try { InstanceScope.INSTANCE.getNode(CUIPlugin.PLUGIN_ID).flush(); @@ -244,6 +252,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fOutlineGroupNamespaces.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)); fOutlineGroupMembers.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)); fOutlineGroupMacros.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_MACROS)); + fOutlineHidePragmaMarks.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_HIDE_PRAGMA_MARK)); boolean showSourceRootsPref = DefaultScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID) .getBoolean(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT, true); fShowSourceRootsAtTopOfProject.setSelection(showSourceRootsPref); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java index 4298052a36c..a0e29530635 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java @@ -155,6 +155,7 @@ public final class PreferencesMessages extends NLS { public static String AppearancePreferencePage_outlineGroupMethods_label; public static String AppearancePreferencePage_outlineGroupNamespaces_label; public static String AppearancePreferencePage_outlineGroupMacros_label; + public static String AppearancePreferencePage_HidePragmaMarks_label; public static String AppearancePreferencePage_note; public static String AppearancePreferencePage_preferenceOnlyForNewViews; public static String AppearancePreferencePage_showSourceRootsAtTopOfProject_label; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties index 7a42b567672..43f7929aea8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -188,6 +188,7 @@ AppearancePreferencePage_outlineGroupNamespaces_label= Group namespaces in the O AppearancePreferencePage_note=Note: AppearancePreferencePage_preferenceOnlyForNewViews=These two preferences do not affect open views AppearancePreferencePage_outlineGroupMacros_label=Group macro definitions in the Outline view +AppearancePreferencePage_HidePragmaMarks_label=Hide Dividers (#pragma mark) in the Outline view AppearancePreferencePage_showSourceRootsAtTopOfProject_label=Show source roots at top of project #Build Logging diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java index 464924753d1..23e9404c5a0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java @@ -23,7 +23,7 @@ import org.eclipse.cdt.internal.ui.editor.LexicalSortingAction; import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; import org.eclipse.cdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; import org.eclipse.cdt.internal.ui.viewsupport.CElementLabels; -import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCLabelProvider; +import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCOutlineLabelProvider; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.Separator; @@ -84,7 +84,7 @@ public class COutlineInformationControl extends AbstractInformationControl { if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)) textFlags = textFlags | CElementLabels.M_SIMPLE_NAME | CElementLabels.F_SIMPLE_NAME; treeViewer.setLabelProvider( - new DecoratingCLabelProvider(new AppearanceAwareLabelProvider(textFlags, IMAGE_FLAGS), true)); + new DecoratingCOutlineLabelProvider(new AppearanceAwareLabelProvider(textFlags, IMAGE_FLAGS))); treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); return treeViewer; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java index bc4bbcabd1e..50b5a652a75 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java @@ -18,6 +18,7 @@ package org.eclipse.cdt.internal.ui.viewsupport; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CModelException; @@ -36,6 +37,8 @@ import org.eclipse.cdt.core.model.IInclude; import org.eclipse.cdt.core.model.IIncludeReference; import org.eclipse.cdt.core.model.ILibraryReference; import org.eclipse.cdt.core.model.IMethodDeclaration; +import org.eclipse.cdt.core.model.IPragma; +import org.eclipse.cdt.core.model.IPragma.PragmaMarkInfo; import org.eclipse.cdt.core.model.ISourceReference; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.model.ITemplate; @@ -484,6 +487,15 @@ public class CElementImageProvider { case ICElement.C_USING: return getUsingImageDescriptor(); + case ICElement.C_PRAGMA: + IPragma pragma = (IPragma) celement; + Optional pragmaMarkInfo = pragma.getPragmaMarkInfo(); + if (pragmaMarkInfo.isPresent()) { + return CDTSharedImages.getImageDescriptor(CDTSharedImages.IMG_OUTLINE_MARK); + } else { + return null; + } + default: return getImageDescriptor(type); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementLabelComposer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementLabelComposer.java index 27a5712453b..555d85ab0f5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementLabelComposer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementLabelComposer.java @@ -16,6 +16,8 @@ *******************************************************************************/ package org.eclipse.cdt.internal.ui.viewsupport; +import java.util.Optional; + import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.IBinary; @@ -27,6 +29,8 @@ import org.eclipse.cdt.core.model.IFunctionDeclaration; import org.eclipse.cdt.core.model.IInheritance; import org.eclipse.cdt.core.model.IMacro; import org.eclipse.cdt.core.model.IMethodDeclaration; +import org.eclipse.cdt.core.model.IPragma; +import org.eclipse.cdt.core.model.IPragma.PragmaMarkInfo; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.model.ITemplate; import org.eclipse.cdt.core.model.ITranslationUnit; @@ -35,12 +39,18 @@ import org.eclipse.cdt.core.model.IVariableDeclaration; import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility; import org.eclipse.cdt.internal.core.model.CoreModelMessages; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; +import org.eclipse.jface.resource.ColorRegistry; +import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.StyledString.Styler; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.TextStyle; +import org.eclipse.ui.PlatformUI; // Most parts of this file were previously located in CElementLabels. // FlexibleBuffer and sub-types are taken from JDTs JavaElementLabelComposer. @@ -214,6 +224,9 @@ public class CElementLabelComposer { case ICElement.C_MACRO: appendMacroLabel((IMacro) element, flags); break; + case ICElement.C_PRAGMA: + appendPragmaLabel((IPragma) element, flags); + break; case ICElement.C_METHOD: case ICElement.C_METHOD_DECLARATION: case ICElement.C_TEMPLATE_METHOD: @@ -312,6 +325,45 @@ public class CElementLabelComposer { } } + /** + * Appends the label for a pragma definition to a StringBuilder. + * @param pragma a pragma + * @param flags {@link CElementLabels#MF_POST_FILE_QUALIFIED}, or 0. + */ + public void appendPragmaLabel(IPragma pragma, long flags) { + Optional pragmaMarkInfo = pragma.getPragmaMarkInfo(); + String display = pragmaMarkInfo.map(PragmaMarkInfo::getMarkName).orElseGet(() -> pragma.getElementName()); + int displayOffset = fBuffer.length(); + fBuffer.append(display); + if (pragmaMarkInfo.isPresent()) { + if (getFlag(flags, CElementLabels.COLORIZE)) { + Styler styler = new Styler() { + @Override + public void applyStyles(TextStyle textStyle) { + textStyle.font = JFaceResources.getFont(PreferenceConstants.OUTLINE_MARK_TEXT_FONT); + ColorRegistry colorRegistry = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme() + .getColorRegistry(); + textStyle.foreground = new Color( + colorRegistry.getRGB(PreferenceConstants.OUTLINE_MARK_TEXT_COLOR)); + } + }; + fBuffer.setStyle(displayOffset, fBuffer.length() - displayOffset, styler); + } + } + + if (getFlag(flags, CElementLabels.MF_POST_FILE_QUALIFIED)) { + IPath path = pragma.getPath(); + if (path != null) { + int offset = fBuffer.length(); + fBuffer.append(CElementLabels.CONCAT_STRING); + fBuffer.append(path.toString()); + if (getFlag(flags, CElementLabels.COLORIZE)) { + fBuffer.setStyle(offset, fBuffer.length() - offset, QUALIFIER_STYLE); + } + } + } + } + /** * Appends the label for a method declaration to a StringBuilder. * @param method a method declaration diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCOutlineLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCOutlineLabelProvider.java new file mode 100644 index 00000000000..95825d28109 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCOutlineLabelProvider.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2021 Kichwa Coders Canada Inc. and others. + * + * 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 + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.viewsupport; + +import org.eclipse.cdt.internal.ui.cview.DividerLine; +import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.jface.resource.ColorRegistry; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Event; +import org.eclipse.ui.PlatformUI; + +/** + * Specialization of the C label provider that allows drawing divider lines used + * in Outline view and information control + */ +public class DecoratingCOutlineLabelProvider extends DecoratingCLabelProvider { + + private static final int MAXIMUM_REASONABLE_WIDTH = 4000; + + public DecoratingCOutlineLabelProvider(CUILabelProvider labelProvider) { + super(labelProvider, true); + } + + @Override + protected void measure(Event event, Object element) { + if (!isOwnerDrawEnabled()) + return; + if (element instanceof DividerLine) { + GC gc = event.gc; + if (gc == null) { + // If there is no gc (can this happen?) default to a reasonably wide measurement + event.width = MAXIMUM_REASONABLE_WIDTH; + } else { + // Use the clipping area of the event to know how wide the tree control + // is so that we can make a line exactly the right size. + // This has the side effect the tree can never become narrower than this + // width as the width of the tree is in part based on the width of its + // widest item. Therefore if the view becomes smaller, a horizontal + // scroll bar is created + // We use a max of MAXIMUM_REASONABLE_WIDTH here to ensure that we don't + // end up in a loop that the item asks for a wider width, so the tree gets wider, etc. + Rectangle clipping = gc.getClipping(); + event.width = Math.min(clipping.width - event.x, MAXIMUM_REASONABLE_WIDTH); + } + } else { + super.measure(event, element); + } + } + + @Override + protected void paint(Event event, Object element) { + if (!isOwnerDrawEnabled()) + return; + if (element instanceof DividerLine) { + int y = event.y + event.height / 2; + ColorRegistry colorRegistry = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme() + .getColorRegistry(); + event.gc.setForeground(new Color(colorRegistry.getRGB(PreferenceConstants.OUTLINE_MARK_DIVIDER_COLOR))); + // draw a line as wide as possible, we can't use event.width here as that doesn't take into account + // our declared width in measure. On Windows this is clipped to the size we measured above, but + // on GTK and macOS this is clipped to the containing tree control. + event.gc.drawLine(0, y, event.x + MAXIMUM_REASONABLE_WIDTH, y); + } else { + super.paint(event, element); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java index d309556f2db..08180632a8c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CDTSharedImages.java @@ -214,6 +214,9 @@ public class CDTSharedImages { public static final String IMG_VIEW_PIN_ACTION_B = "icons/obj16/toolbar_pinned_b.gif"; //$NON-NLS-1$ public static final String IMG_VIEW_PIN_ACTION_MULTI = "icons/obj16/toolbar_pinned_multi.gif"; //$NON-NLS-1$ + /** @since 7.3*/ + public static final String IMG_OUTLINE_MARK = "icons/obj16/outline_mark.png"; //$NON-NLS-1$ + private static SharedImagesFactory imagesFactory = new SharedImagesFactory(CUIPlugin.getDefault()); /** diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementContentProvider.java index 979f4f92984..6e567e6df84 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementContentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementContentProvider.java @@ -97,7 +97,7 @@ public class CElementContentProvider extends BaseCElementContentProvider * Creates a new content provider for C elements. */ public CElementContentProvider(boolean provideMembers, boolean provideWorkingCopy) { - super(provideMembers, provideWorkingCopy); + super(provideMembers, provideWorkingCopy, false, () -> false); } @Override diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java index 42d615b7390..25ad5dd52e0 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java @@ -560,6 +560,24 @@ public class PreferenceConstants { */ public final static String EDITOR_TEXT_FONT = "org.eclipse.cdt.ui.editors.textfont"; //$NON-NLS-1$ + /** + * The symbolic font name for the C/C++ outline pragma mark or pragma region text font. + * @since 7.3 + */ + public final static String OUTLINE_MARK_TEXT_FONT = "org.eclipse.cdt.ui.outline.mark.textfont"; //$NON-NLS-1$ + + /** + * The color preference for the C/C++ outline pragma mark or pragma region text font color. + * @since 7.3 + */ + public final static String OUTLINE_MARK_TEXT_COLOR = "org.eclipse.cdt.ui.outline.mark.textcolor"; //$NON-NLS-1$ + + /** + * The color preference for the C/C++ outline pragma mark or pragma region divider color. + * @since 7.3 + */ + public final static String OUTLINE_MARK_DIVIDER_COLOR = "org.eclipse.cdt.ui.outline.mark.dividercolor"; //$NON-NLS-1$ + /** * A named preference that controls whether the cview's selection is linked to the active * editor. @@ -766,6 +784,14 @@ public class PreferenceConstants { */ public static final String OUTLINE_LINK_TO_EDITOR = "org.eclipse.cdt.ui.outline.linktoeditor"; //$NON-NLS-1$ + /** + * A named preference that controls whether the Outline view should hide pragma mark directives. + *

+ * Value is of type {@code Boolean}. + * @since 7.3 + */ + public static final String OUTLINE_HIDE_PRAGMA_MARK = "org.eclipse.cdt.ui.outline.hidePragmaMark"; //$NON-NLS-1$ + /** * A named preference that controls whether include directives should be grouped in * the C/C++ Projects view and the Project Explorer view.