From 003975782e211a39d04450e4719a5acbde37eaf2 Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Thu, 29 Jan 2009 09:30:15 +0000 Subject: [PATCH] Bug 225944 - Organize items by namespace in Outline, fixes also bug 262785 --- .../model/tests/CModelBuilderBugsTest.java | 5 + .../resources/cmodel/CModelBuilderTest.cpp | 3 + .../core/model/util/CElementBaseLabels.java | 42 ++- .../internal/core/model/CModelBuilder2.java | 41 ++- .../eclipse/cdt/ui/tests/AutomatedSuite.java | 6 +- .../ui/tests/outline/BasicOutlineTest.java | 280 ++++++++++++++++++ .../ui/tests/outline/OutlineTestSuite.java | 25 ++ .../ui/BaseCElementContentProvider.java | 135 +++++++-- .../cdt/internal/ui/MembersGrouping.java | 114 +++++++ .../ui/editor/AbstractCModelOutlinePage.java | 59 +++- .../ui/editor/CContentOutlinerProvider.java | 17 +- .../preferences/AppearancePreferencePage.java | 34 ++- .../ui/preferences/PreferencesMessages.java | 3 +- .../PreferencesMessages.properties | 3 +- .../AppearanceAwareLabelProvider.java | 37 +-- .../viewsupport/DecoratingCLabelProvider.java | 8 +- .../org/eclipse/cdt/ui/CElementGrouping.java | 11 +- .../org/eclipse/cdt/ui/CElementSorter.java | 32 +- .../org/eclipse/cdt/ui/IncludesGrouping.java | 11 +- .../eclipse/cdt/ui/NamespacesGrouping.java | 134 +++++++-- .../eclipse/cdt/ui/PreferenceConstants.java | 10 +- .../images/view_appearance_prefs.png | Bin 21671 -> 25793 bytes .../reference/cdt_u_appearance_pref.htm | 6 +- 23 files changed, 871 insertions(+), 145 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/BasicOutlineTest.java create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/OutlineTestSuite.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/MembersGrouping.java diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderBugsTest.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderBugsTest.java index 86d8dd49b44..d2f8524ea15 100644 --- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderBugsTest.java +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/model/tests/CModelBuilderBugsTest.java @@ -69,4 +69,9 @@ public class CModelBuilderBugsTest extends BaseTestCase { assertEquals("decl", functions[1].getElementName()); } + public void testModelBuilderBug262785() throws Exception { + assertNotNull(fTU.getElement("Unknown1::method")); + assertNotNull(fTU.getElement("Unknown2::method")); + } + } diff --git a/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderTest.cpp b/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderTest.cpp index 35a7f1f8086..2ed0521c160 100644 --- a/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderTest.cpp +++ b/core/org.eclipse.cdt.core.tests/resources/cmodel/CModelBuilderTest.cpp @@ -10,3 +10,6 @@ namespace nsTest { void nsTest::inlined2() {}; // wrong label in outline: nsTest::inlined(): void void nsTest::decl2(); // label in outline (ok): decl(): void } +//http://bugs.eclipse.org/262785 +void Unknown1::method() {} // no qualifier in outline +void Unknown2::method() {} // no qualifier in outline diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/util/CElementBaseLabels.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/util/CElementBaseLabels.java index f4f8596f853..fe99de3cbc4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/util/CElementBaseLabels.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/util/CElementBaseLabels.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2008 IBM Corporation and others. + * Copyright (c) 2003, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -46,6 +46,13 @@ public class CElementBaseLabels { */ public final static int M_PARAMETER_TYPES= 1 << 0; + /** + * Method definition names without qualifier. + * e.g. foo(int) + * @since 5.1 + */ + public final static int M_SIMPLE_NAME= 1 << 1; + /** * Method names contain thrown exceptions. * e.g. foo throw( IOException ) @@ -82,6 +89,13 @@ public class CElementBaseLabels { */ public final static int TEMPLATE_PARAMETERS= 1 << 7; + /** + * Static field names without qualifier. + * e.g. fHello + * @since 5.1 + */ + public final static int F_SIMPLE_NAME= 1 << 8; + /** * Field names contain the declared type (appended) * e.g. fHello: int @@ -349,7 +363,11 @@ public class CElementBaseLabels { } } - buf.append( method.getElementName() ); + if (getFlag(flags, M_SIMPLE_NAME)) { + buf.append(getSimpleName(method.getElementName())); + } else { + buf.append(method.getElementName()); + } //template parameters if (method instanceof ITemplate) { @@ -413,6 +431,20 @@ public class CElementBaseLabels { } } + /** + * Strip any qualifier from the given name. + * + * @param elementName + * @return a "simple" name + */ + private static String getSimpleName(String elementName) { + int idx = elementName.indexOf("::"); //$NON-NLS-1$ + if (idx >= 0) { + return elementName.substring(idx+2); + } + return elementName; + } + private static void getTemplateParameters(ITemplate template, int flags, StringBuffer buf) { if (getFlag(flags, TEMPLATE_PARAMETERS)) { String[] types = template.getTemplateParameterTypes(); @@ -452,7 +484,11 @@ public class CElementBaseLabels { } } - buf.append( field.getElementName() ); + if (getFlag(flags, F_SIMPLE_NAME)) { + buf.append(getSimpleName(field.getElementName())); + } else { + buf.append(field.getElementName()); + } if( getFlag( flags, F_APP_TYPE_SIGNATURE ) && field.exists()) { buf.append( DECL_STRING ); 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 4fad7fbcd5c..0f796abe767 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 @@ -72,6 +72,7 @@ import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.IContributedModelBuilder; +import org.eclipse.cdt.core.model.INamespace; import org.eclipse.cdt.core.model.IProblemRequestor; import org.eclipse.cdt.core.model.IStructure; import org.eclipse.cdt.core.model.ITranslationUnit; @@ -812,7 +813,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { final IASTDeclSpecifier declSpecifier= functionDeclaration.getDeclSpecifier(); - final String functionName= ASTStringUtil.getSimpleName(name); + final String simpleName= ASTStringUtil.getSimpleName(name); final String[] parameterTypes= ASTStringUtil.getParameterSignatureArray(declarator); final String returnType= ASTStringUtil.getReturnTypeString(declSpecifier, declarator); @@ -822,12 +823,12 @@ public class CModelBuilder2 implements IContributedModelBuilder { if (declarator instanceof ICPPASTFunctionDeclarator) { final ICPPASTFunctionDeclarator cppFunctionDeclarator= (ICPPASTFunctionDeclarator)declarator; - final IASTName simpleName; + final IASTName simpleAstName; if (name instanceof ICPPASTQualifiedName) { final ICPPASTQualifiedName quName= (ICPPASTQualifiedName)name; - simpleName= quName.getLastName(); + simpleAstName= quName.getLastName(); } else { - simpleName= name; + simpleAstName= name; } IScope scope= null; // try to avoid expensive resolution of scope and binding @@ -843,8 +844,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { } } if (!isMethod) { - scope= CPPVisitor.getContainingScope(simpleName); - isMethod= scope instanceof ICPPClassScope || simpleName.resolveBinding() instanceof ICPPMethod; + scope= CPPVisitor.getContainingScope(simpleAstName); + isMethod= scope instanceof ICPPClassScope || simpleAstName.resolveBinding() instanceof ICPPMethod; } } if (isMethod) { @@ -870,7 +871,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { info= methodInfo; ICPPMethod methodBinding= null; if (scope != null) { - final IBinding binding= simpleName.resolveBinding(); + final IBinding binding= simpleAstName.resolveBinding(); if (binding instanceof ICPPMethod) { methodBinding= (ICPPMethod)binding; } @@ -897,19 +898,34 @@ public class CModelBuilder2 implements IContributedModelBuilder { final boolean isConstructor; if (scope != null) { isConstructor= CPPVisitor.isConstructor(scope, declarator); + } else if (parent instanceof IStructure) { + isConstructor= parent.getElementName().equals(simpleName); + } else if (name instanceof ICPPASTQualifiedName) { + final ICPPASTQualifiedName quName= (ICPPASTQualifiedName)name; + final IASTName[] names= quName.getNames(); + isConstructor= names.length >= 2 && simpleName.equals(ASTStringUtil.getSimpleName(names[names.length-2])); } else { - isConstructor= parent.getElementName().equals(functionName); + isConstructor= false; } methodElement.setConstructor(isConstructor); - methodElement.setDestructor(functionName.charAt(0) == '~'); + methodElement.setDestructor(simpleName.charAt(0) == '~'); } } else { + String functionName= ASTStringUtil.getQualifiedName(name); + // strip namespace qualifier if parent is same namespace + if (name instanceof ICPPASTQualifiedName && parent instanceof INamespace) { + final ICPPASTQualifiedName quName= (ICPPASTQualifiedName)name; + final IASTName[] names= quName.getNames(); + if (names.length >= 2 && parent.getElementName().equals(ASTStringUtil.getSimpleName(names[names.length-2]))) { + functionName= simpleName; + } + } if (isTemplate) { // template function - element= new FunctionTemplate(parent, ASTStringUtil.getSimpleName(name)); + element= new FunctionTemplate(parent, functionName); } else { // function - element= new Function(parent, ASTStringUtil.getSimpleName(name)); + element= new Function(parent, functionName); } element.setParameterTypes(parameterTypes); element.setReturnType(returnType); @@ -918,6 +934,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { } } else { + final String functionName= ASTStringUtil.getQualifiedName(name); element= new Function(parent, functionName); element.setParameterTypes(parameterTypes); element.setReturnType(returnType); @@ -1205,7 +1222,7 @@ public class CModelBuilder2 implements IContributedModelBuilder { * @return the scope or null */ private static IScope getScope(IASTName astName) { - IBinding binding= astName.getBinding(); + IBinding binding= astName.resolveBinding(); if (binding != null) { try { return binding.getScope(); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java index 26869e31473..6e44a45fdda 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/AutomatedSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -19,6 +19,7 @@ import org.eclipse.cdt.ui.tests.buildconsole.BuildConsoleTests; import org.eclipse.cdt.ui.tests.callhierarchy.CallHierarchyTestSuite; import org.eclipse.cdt.ui.tests.chelp.CHelpTest; import org.eclipse.cdt.ui.tests.includebrowser.IncludeBrowserTestSuite; +import org.eclipse.cdt.ui.tests.outline.OutlineTestSuite; import org.eclipse.cdt.ui.tests.quickfix.AssistQuickFixTest; import org.eclipse.cdt.ui.tests.refactoring.RefactoringTestSuite; import org.eclipse.cdt.ui.tests.search.SearchTestSuite; @@ -51,6 +52,9 @@ public class AutomatedSuite extends TestSuite { // tests from package org.eclipse.cdt.ui.tests.text addTest(TextTestSuite.suite()); + // tests from package org.eclipse.cdt.ui.tests.outline + addTest(OutlineTestSuite.suite()); + // tests for package org.eclipse.cdt.ui.tests.viewsupport addTest(ViewSupportTestSuite.suite()); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/BasicOutlineTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/BasicOutlineTest.java new file mode 100644 index 00000000000..c9c2db95c52 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/BasicOutlineTest.java @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.ui.tests.outline; + +import junit.framework.TestSuite; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IPageLayout; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.ide.IDE; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.cdt.ui.tests.BaseUITestCase; +import org.eclipse.cdt.ui.tests.text.EditorTestHelper; + +import org.eclipse.cdt.internal.ui.editor.CEditor; + +/** + * Basic outline view tests. + */ +public class BasicOutlineTest extends BaseUITestCase { + + private static final int INDEXER_WAIT_TIME = 10000; + + public static TestSuite suite() { + return suite(BasicOutlineTest.class); + } + + private ICProject fCProject; + + @Override + protected void setUp() throws Exception { + super.setUp(); + restoreAllParts(); + fCProject = CProjectHelper.createCCProject(getName()+System.currentTimeMillis(), "bin", IPDOMManager.ID_FAST_INDEXER); + } + + @Override + protected void tearDown() throws Exception { + closeAllEditors(); + PreferenceConstants.getPreferenceStore().setToDefault(PreferenceConstants.OUTLINE_GROUP_MEMBERS); + PreferenceConstants.getPreferenceStore().setToDefault(PreferenceConstants.OUTLINE_GROUP_NAMESPACES); + if(fCProject != null) { + CProjectHelper.delete(fCProject); + } + super.tearDown(); + } + + protected CEditor openEditor(IFile file) throws PartInitException { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + CEditor editor= (CEditor) IDE.openEditor(page, file); + EditorTestHelper.joinReconciler(EditorTestHelper.getSourceViewer(editor), 100, 1000, 10); + runEventQueue(500); + return editor; + } + + protected ICProject getProject() { + return fCProject; + } + + private void waitForIndexer(IProject project, IFile source) throws Exception, CoreException { + waitForIndexer(CCorePlugin.getIndexManager().getIndex(fCProject), source, INDEXER_WAIT_TIME); + } + + private void checkTreeItems(TreeItem[] items, String... labels) { + assertEquals(items.length, labels.length); + int i=0; + for (TreeItem treeItem : items) { + assertEquals(labels[i++], treeItem.getText()); + } + } + + //#include "user.h" + //#include + //#define MACRO + //int main(int argc, char** argv) {} + public void testSimpleOutlineContent() throws Exception { + StringBuffer[] contents= getContentsForTest(1); + IProject project= getProject().getProject(); + IFile source= createFile(project, "source.cpp", contents[0].toString()); + waitForIndexer(project, source); + + final IViewPart outline= activateView(IPageLayout.ID_OUTLINE); + openEditor(source); + + Tree tree= checkTreeNode(outline, 0, "user.h").getParent(); + checkTreeNode(tree, 1, "system.h"); + checkTreeNode(tree, 2, "MACRO"); + checkTreeNode(tree, 3, "main(int, char**) : int"); + } + + //class Foo { + // static int field; + // void bar(); + // void foo(); + //}; + + //#include "header.h" + //void Foo::bar() {} + //int Foo::field = 5; + //void Foo::foo() {} + public void testGroupedMembers() throws Exception { + StringBuffer[] contents= getContentsForTest(2); + IProject project= getProject().getProject(); + IFile header= createFile(project, "header.h", contents[0].toString()); + IFile source= createFile(project, "source.cpp", contents[1].toString()); + waitForIndexer(project, source); + + final IViewPart outline= activateView(IPageLayout.ID_OUTLINE); + openEditor(source); + + Tree tree= checkTreeNode(outline, 0, "header.h").getParent(); + checkTreeNode(tree, 1, "Foo::bar() : void"); + checkTreeNode(tree, 2, "Foo::field : int"); + checkTreeNode(tree, 3, "Foo::foo() : void"); + + PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.OUTLINE_GROUP_MEMBERS, true); + runEventQueue(500); + + tree= checkTreeNode(outline, 0, "header.h").getParent(); + expandTreeItem(checkTreeNode(outline, 1, "Foo")); + checkTreeNode(tree, 1, 0, "bar() : void"); + checkTreeNode(tree, 1, 1, "field : int"); + checkTreeNode(tree, 1, 2, "foo() : void"); + } + + //namespace ns { + //class Foo { + // static int field; + // void bar(); + // void foo(); + //}; + //}; + + //#include "header.h" + //namespace ns { + //void Foo::bar() {} + //} + //namespace ns { + //int Foo::field = 5; + //void Foo::foo() {} + //} + public void testGroupedMembersInNamespace() throws Exception { + StringBuffer[] contents= getContentsForTest(2); + IProject project= getProject().getProject(); + IFile header= createFile(project, "header.h", contents[0].toString()); + IFile source= createFile(project, "source.cpp", contents[1].toString()); + waitForIndexer(project, source); + + final IViewPart outline= activateView(IPageLayout.ID_OUTLINE); + openEditor(source); + + TreeItem item= checkTreeNode(outline, 0, "header.h"); + Tree tree= item.getParent(); + expandTreeItem(checkTreeNode(tree, 1, "ns")); + checkTreeNode(tree, 1, 0, "Foo::bar() : void"); + expandTreeItem(checkTreeNode(tree, 2, "ns")); + checkTreeNode(tree, 2, 0, "Foo::field : int"); + checkTreeNode(tree, 2, 1, "Foo::foo() : void"); + + PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.OUTLINE_GROUP_MEMBERS, true); + runEventQueue(500); + + checkTreeNode(outline, 0, "header.h"); + expandTreeItem(checkTreeNode(tree, 1, "ns")); + expandTreeItem(item= checkTreeNode(tree, 1, 0, "Foo")); + checkTreeItems(item.getItems(), "bar() : void"); + expandTreeItem(checkTreeNode(tree, 2, "ns")); + expandTreeItem(item= checkTreeNode(tree, 2, 0, "Foo")); + checkTreeItems(item.getItems(), "field : int", "foo() : void"); + } + + //namespace ns { + //class Foo { + // static int field; + // void bar(); + // void foo(); + //}; + //}; + + //#include "header.h" + //namespace ns { + //void Foo::bar() {} + //} + //namespace ns { + //int Foo::field = 5; + //void Foo::foo() {} + //} + public void testGroupedNamespaces() throws Exception { + StringBuffer[] contents= getContentsForTest(2); + IProject project= getProject().getProject(); + IFile header= createFile(project, "header.h", contents[0].toString()); + IFile source= createFile(project, "source.cpp", contents[1].toString()); + waitForIndexer(project, source); + + final IViewPart outline= activateView(IPageLayout.ID_OUTLINE); + openEditor(source); + + TreeItem item= checkTreeNode(outline, 0, "header.h"); + Tree tree= item.getParent(); + expandTreeItem(checkTreeNode(tree, 1, "ns")); + checkTreeNode(tree, 1, 0, "Foo::bar() : void"); + expandTreeItem(checkTreeNode(tree, 2, "ns")); + checkTreeNode(tree, 2, 0, "Foo::field : int"); + checkTreeNode(tree, 2, 1, "Foo::foo() : void"); + + PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.OUTLINE_GROUP_NAMESPACES, true); + runEventQueue(500); + + checkTreeNode(outline, 0, "header.h"); + expandTreeItem(checkTreeNode(tree, 1, "ns")); + checkTreeNode(tree, 1, 0, "Foo::bar() : void"); + checkTreeNode(tree, 1, 1, "Foo::field : int"); + checkTreeNode(tree, 1, 2, "Foo::foo() : void"); + } + + //namespace ns { + //class Foo { + // static int field; + // void bar(); + // void foo(); + //}; + //}; + + //#include "header.h" + //namespace ns { + //void Foo::bar() {} + //} + //namespace ns { + //int Foo::field = 5; + //void Foo::foo() {} + //} + public void testGroupedMembersInGroupedNamespaces() throws Exception { + StringBuffer[] contents= getContentsForTest(2); + IProject project= getProject().getProject(); + IFile header= createFile(project, "header.h", contents[0].toString()); + IFile source= createFile(project, "source.cpp", contents[1].toString()); + waitForIndexer(project, source); + + final IViewPart outline= activateView(IPageLayout.ID_OUTLINE); + openEditor(source); + + TreeItem item= checkTreeNode(outline, 0, "header.h"); + Tree tree= item.getParent(); + expandTreeItem(checkTreeNode(tree, 1, "ns")); + checkTreeNode(tree, 1, 0, "Foo::bar() : void"); + expandTreeItem(checkTreeNode(tree, 2, "ns")); + checkTreeNode(tree, 2, 0, "Foo::field : int"); + checkTreeNode(tree, 2, 1, "Foo::foo() : void"); + + PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.OUTLINE_GROUP_MEMBERS, true); + PreferenceConstants.getPreferenceStore().setValue(PreferenceConstants.OUTLINE_GROUP_NAMESPACES, true); + runEventQueue(500); + + checkTreeNode(outline, 0, "header.h"); + expandTreeItem(checkTreeNode(tree, 1, "ns")); + expandTreeItem(item= checkTreeNode(tree, 1, 0, "Foo")); + checkTreeItems(item.getItems(), "bar() : void", "field : int", "foo() : void"); + } + +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/OutlineTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/OutlineTestSuite.java new file mode 100644 index 00000000000..14c3df6ca31 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/outline/OutlineTestSuite.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems, Inc. 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: + * Anton Leherbauer (Wind River Systems) - initial implementation + *******************************************************************************/ +package org.eclipse.cdt.ui.tests.outline; + +import junit.framework.TestSuite; + +public class OutlineTestSuite extends TestSuite { + + public static TestSuite suite() { + return new OutlineTestSuite(); + } + + public OutlineTestSuite() { + super(OutlineTestSuite.class.getName()); + addTest(BasicOutlineTest.suite()); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java index 76a4b053328..f956f763505 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -38,6 +38,7 @@ import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICModel; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.IInclude; +import org.eclipse.cdt.core.model.IMember; import org.eclipse.cdt.core.model.INamespace; import org.eclipse.cdt.core.model.IParent; import org.eclipse.cdt.core.model.ISourceReference; @@ -77,6 +78,7 @@ public class BaseCElementContentProvider implements ITreeContentProvider { protected boolean fProvideWorkingCopy= false; protected boolean fIncludesGrouping= false; protected boolean fNamespacesGrouping= false; + protected boolean fMemberGrouping= false; public BaseCElementContentProvider() { this(false, false); @@ -89,7 +91,7 @@ public class BaseCElementContentProvider implements ITreeContentProvider { /** * Returns whether the members are provided when asking - * for a TU's or ClassFile's children. + * for a TU's children. */ public boolean getProvideMembers() { return fProvideMembers; @@ -97,7 +99,7 @@ public class BaseCElementContentProvider implements ITreeContentProvider { /** * Returns whether the members are provided when asking - * for a TU's or ClassFile's children. + * for a TU's children. */ public void setProvideMembers(boolean b) { fProvideMembers= b; @@ -149,6 +151,21 @@ public class BaseCElementContentProvider implements ITreeContentProvider { fNamespacesGrouping = b; } + /** + * @return whether grouping of members is enabled + */ + public boolean isMemberGroupingEnabled() { + return fMemberGrouping; + } + + /** + * Enable/disable member grouping by common namespace. + * @param enable + */ + public void setMemberGrouping(boolean enable) { + fMemberGrouping = enable; + } + /* (non-Cdoc) * Method declared on IContentProvider. */ @@ -205,6 +222,8 @@ public class BaseCElementContentProvider implements ITreeContentProvider { return ((IArchive)element).getChildren(); } else if (element instanceof IBinaryModule) { return ((IBinaryModule)element).getChildren(); + } else if (element instanceof INamespace) { + return getNamespaceChildren((INamespace) element); } else if (element instanceof ISourceReference && element instanceof IParent) { return ((IParent)element).getChildren(); } else if (element instanceof IProject) { @@ -265,6 +284,11 @@ public class BaseCElementContentProvider implements ITreeContentProvider { return true; } } + + if (element instanceof CElementGrouping) { + return true; + } + Object[] children= getChildren(element); return (children != null) && children.length > 0; } @@ -317,7 +341,28 @@ public class BaseCElementContentProvider implements ITreeContentProvider { } } } - + if (parent instanceof INamespace && fNamespacesGrouping) { + final INamespace namespace = (INamespace)parent; + final NamespacesGrouping grouping = new NamespacesGrouping(namespace.getTranslationUnit(), namespace, fMemberGrouping); + if (grouping.getNamespaces().length > 2) { + parent = grouping; + } + } + if (parent instanceof IMember && fMemberGrouping) { + final IMember member = (IMember)parent; + final String ns = getElementNamespace(member); + if (ns != null) { + Object parentParent = member.getParent(); + if (parentParent instanceof INamespace && fNamespacesGrouping) { + final INamespace namespace = (INamespace)parent; + final NamespacesGrouping grouping = new NamespacesGrouping(namespace.getTranslationUnit(), namespace); + if (grouping.getNamespaces().length > 2) { + parentParent = grouping; + } + } + return new MembersGrouping(parentParent, ns); + } + } // if we are doing grouping for the includes return the grouping container. if (element instanceof IInclude && fIncludesGrouping) { parent = new IncludesGrouping(((IInclude)element).getTranslationUnit()); @@ -382,31 +427,21 @@ public class BaseCElementContentProvider implements ITreeContentProvider { } children = list.toArray(); } + Map nsmap = new HashMap(); if (fNamespacesGrouping) { // check if there is another namespace with the same name for the same parent List list = new ArrayList(children.length); - Map map = new HashMap(); for (int i = 0; i < children.length; ++i) { if (children[i] instanceof INamespace) { INamespace n1 = (INamespace)children[i]; - NamespacesGrouping namespacesGrouping = map.get(n1.getElementName()); + NamespacesGrouping namespacesGrouping = nsmap.get(n1.getElementName()); if (namespacesGrouping == null) { - for (int j = i + 1; j < children.length; ++j) { - if (children[j] instanceof INamespace) { - INamespace n2 = (INamespace)children[j]; - if (n1.getElementName().equals(n2.getElementName())) { - if (namespacesGrouping == null) { - namespacesGrouping = new NamespacesGrouping(unit, n1); - map.put(n1.getElementName(), namespacesGrouping); - } - namespacesGrouping.addNamespace(n2); - } - } - } - if (namespacesGrouping == null) { - list.add(n1); - } else { + namespacesGrouping = new NamespacesGrouping(unit, n1, fMemberGrouping); + if (namespacesGrouping.getNamespaces().length > 1) { + nsmap.put(n1.getElementName(), namespacesGrouping); list.add(namespacesGrouping); + } else { + list.add(children[i]); } } } else { @@ -415,9 +450,67 @@ public class BaseCElementContentProvider implements ITreeContentProvider { } children = list.toArray(); } + if (fMemberGrouping) { + // check if there is another member with the same namespace for the same parent + List list = new ArrayList(children.length); + Map map = new HashMap(); + for (int i = 0; i < children.length; ++i) { + if (children[i] instanceof IMember) { + final ICElement member = (ICElement)children[i]; + String namespace = getElementNamespace(member); + MembersGrouping memberGrouping = map.get(namespace); + if (memberGrouping == null) { + memberGrouping = new MembersGrouping(unit, namespace); + map.put(namespace, memberGrouping); + list.add(memberGrouping); + } + } else if (fNamespacesGrouping && children[i] instanceof INamespace) { + if (!nsmap.containsKey(((INamespace) children[i]).getElementName())) { + list.add(children[i]); + } + } else { + list.add(children[i]); + } + } + children = list.toArray(); + } return children; } + protected Object[] getNamespaceChildren(IParent element) throws CModelException { + Object[] children = element.getChildren(); + if (fMemberGrouping) { + // check if there is another member with the same namespace for the same parent + List list = new ArrayList(children.length); + Map map = new HashMap(); + for (int i = 0; i < children.length; ++i) { + if (children[i] instanceof IMember) { + final ICElement member = (ICElement)children[i]; + String namespace = getElementNamespace(member); + MembersGrouping memberGrouping = map.get(namespace); + if (memberGrouping == null) { + memberGrouping = new MembersGrouping(element, namespace); + map.put(namespace, memberGrouping); + list.add(memberGrouping); + } + } else { + list.add(children[i]); + } + } + children = list.toArray(); + } + return children; + } + + private static String getElementNamespace(ICElement member) { + String name = member.getElementName(); + int idx = name.lastIndexOf("::"); //$NON-NLS-1$ + if (idx < 0) { + return null; + } + return name.substring(0, idx); + } + protected Object[] getCResources(ICContainer container) throws CModelException { Object[] objects = null; Object[] children = container.getChildren(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/MembersGrouping.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/MembersGrouping.java new file mode 100644 index 00000000000..96f89d9e0d8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/MembersGrouping.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IMember; +import org.eclipse.cdt.core.model.INamespace; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.ui.CElementGrouping; +import org.eclipse.cdt.ui.NamespacesGrouping; + +/** + * Grouping for members in the same namespace. + */ +public class MembersGrouping extends CElementGrouping { + + private final Object fParent; + private final String fNamespace; + + public MembersGrouping(Object parent, String namespace) { + super(CElementGrouping.CLASS_GROUPING); + assert parent instanceof ICElement || parent instanceof NamespacesGrouping; + fParent= parent; + fNamespace= namespace; + } + + @Override + public String getLabel(Object object) { + return fNamespace; + } + + @Override + public Object[] getChildren(Object object) { + List nsMembers = new ArrayList(); + if (fParent instanceof IParent) { + try { + nsMembers.addAll(getNamespaceChildren(((IParent)fParent).getChildren())); + } catch (CModelException exc) { + } + } else if (fParent instanceof NamespacesGrouping) { + NamespacesGrouping nsGrouping = (NamespacesGrouping) fParent; + INamespace[] namespaces = nsGrouping.getNamespaces(); + for (INamespace iNamespace : namespaces) { + try { + nsMembers.addAll(getNamespaceChildren(iNamespace.getChildren())); + } catch (CModelException exc) { + } + } + } + return nsMembers.toArray(); + } + + /** + * @param iNamespace + * @return + */ + private Collection getNamespaceChildren(ICElement[] icElements) { + List members = new ArrayList(icElements.length); + for (ICElement icElement : icElements) { + if (icElement instanceof IMember) { + String name = icElement.getElementName(); + int idx = name.lastIndexOf("::"); //$NON-NLS-1$ + if (idx < 0) { + continue; + } + String namespace = name.substring(0, idx); + if (fNamespace.equals(namespace)) { + members.add(icElement); + } + } + } + return members; + } + + @Override + public Object getParent(Object object) { + return fParent; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof MembersGrouping) { + final MembersGrouping other= (MembersGrouping)obj; + return fParent.equals(other.fParent) && fNamespace.equals(other.fNamespace); + } + return false; + } + + @Override + public int hashCode() { + return fParent.hashCode() * 17 + fNamespace.hashCode(); + } + + @Override + public String toString() { + return fNamespace; + } +} 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 759e285d98e..9f9724ad880 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, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -22,6 +22,7 @@ import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; @@ -60,8 +61,8 @@ import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.util.CElementBaseLabels; -import org.eclipse.cdt.ui.CElementGrouping; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.IncludesGrouping; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.actions.OpenViewActionGroup; @@ -79,6 +80,7 @@ import org.eclipse.cdt.internal.ui.dnd.TransferDropTargetListener; import org.eclipse.cdt.internal.ui.search.actions.SelectionSearchGroup; import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; import org.eclipse.cdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; +import org.eclipse.cdt.internal.ui.viewsupport.CUILabelProvider; import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCLabelProvider; /** @@ -88,6 +90,49 @@ import org.eclipse.cdt.internal.ui.viewsupport.DecoratingCLabelProvider; */ public abstract class AbstractCModelOutlinePage extends Page implements IContentOutlinePage, ISelectionChangedListener, IAdaptable { + /** + * The default label provider for the outline. + */ + protected static class COutlineLabelProvider extends AppearanceAwareLabelProvider { + + /** + * Flag whether to show member definitions with qualified or simple names. + */ + private boolean fSimpleName; + + public COutlineLabelProvider(int textFlags, int imageFlags) { + super(textFlags, imageFlags); + PreferenceConstants.getPreferenceStore().addPropertyChangeListener(this); + fSimpleName= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS); + } + + @Override + public void dispose() { + PreferenceConstants.getPreferenceStore().removePropertyChangeListener(this); + super.dispose(); + } + + @Override + protected int evaluateTextFlags(Object element) { + if (fSimpleName) { + return super.evaluateTextFlags(element) | CElementBaseLabels.M_SIMPLE_NAME | CElementBaseLabels.F_SIMPLE_NAME; + } + return super.evaluateTextFlags(element); + } + + @Override + public void propertyChange(PropertyChangeEvent event) { + if (PreferenceConstants.OUTLINE_GROUP_MEMBERS.equals(event.getProperty())) { + final Object newValue = event.getNewValue(); + if (newValue instanceof Boolean) { + fSimpleName= ((Boolean) newValue).booleanValue(); + } else { + fSimpleName= PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS); + } + } + } + } + /** * A specialized tree viewer for outline content. * @@ -106,8 +151,8 @@ public abstract class AbstractCModelOutlinePage extends Page implements IContent if (node instanceof Item) { Item i= (Item) node; final Object data = i.getData(); - // don't expand groupings by default - if (data instanceof CElementGrouping) { + // don't expand include grouping by default + if (data instanceof IncludesGrouping) { return; } else if (data instanceof ICElement) { if (!shouldExpandElement((ICElement)data)) { @@ -375,13 +420,17 @@ public abstract class AbstractCModelOutlinePage extends Page implements IContent protected ProblemTreeViewer createTreeViewer(Composite parent) { fTreeViewer = new OutlineTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); fTreeViewer.setContentProvider(createContentProvider(fTreeViewer)); - fTreeViewer.setLabelProvider(new DecoratingCLabelProvider(new AppearanceAwareLabelProvider(TEXT_FLAGS, IMAGE_FLAGS), true)); + fTreeViewer.setLabelProvider(new DecoratingCLabelProvider(createLabelProvider(), true)); fTreeViewer.setAutoExpandLevel(3); fTreeViewer.setUseHashlookup(true); fTreeViewer.addSelectionChangedListener(this); return fTreeViewer; } + private CUILabelProvider createLabelProvider() { + return new COutlineLabelProvider(TEXT_FLAGS, IMAGE_FLAGS); + } + @Override public void createControl(Composite parent) { fTreeViewer = createTreeViewer(parent); 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 4b96133a9db..256f632e02b 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2008 QNX Software Systems and others. + * Copyright (c) 2002, 2009 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 @@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.ui.editor; import java.util.ArrayList; import java.util.Iterator; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; @@ -72,7 +73,10 @@ public class CContentOutlinerProvider extends BaseCElementContentProvider { public CContentOutlinerProvider(TreeViewer viewer, IWorkbenchPartSite site) { super(true, true); treeViewer = viewer; - setIncludesGrouping(PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); + 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)); } /** @@ -349,6 +353,15 @@ public class CContentOutlinerProvider extends BaseCElementContentProvider { contentUpdated(); } } + } else if (prop.equals(PreferenceConstants.OUTLINE_GROUP_MEMBERS)) { + Object newValue = event.getNewValue(); + if (newValue instanceof Boolean) { + boolean value = ((Boolean) newValue).booleanValue(); + if (isMemberGroupingEnabled() != value) { + setMemberGrouping(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 5dd58801765..9c2018192e9 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,22 +12,21 @@ package org.eclipse.cdt.internal.ui.preferences; import org.eclipse.core.runtime.IStatus; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - +import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.resource.JFaceResources; - +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.PlatformUI; +import org.osgi.service.prefs.BackingStoreException; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; @@ -47,6 +46,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben private SelectionButtonDialogField fOutlineGroupNamespaces; private SelectionButtonDialogField fCViewGroupIncludes; private SelectionButtonDialogField fCViewSeparateHeaderAndSource; + private SelectionButtonDialogField fOutlineGroupMembers; public AppearancePreferencePage() { setPreferenceStore(PreferenceConstants.getPreferenceStore()); @@ -70,6 +70,10 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fOutlineGroupNamespaces.setDialogFieldListener(listener); fOutlineGroupNamespaces.setLabelText(PreferencesMessages.AppearancePreferencePage_outlineGroupNamespaces_label); + fOutlineGroupMembers= new SelectionButtonDialogField(SWT.CHECK); + fOutlineGroupMembers.setDialogFieldListener(listener); + fOutlineGroupMembers.setLabelText(PreferencesMessages.AppearancePreferencePage_outlineGroupMethods_label); + fCViewGroupIncludes= new SelectionButtonDialogField(SWT.CHECK); fCViewGroupIncludes.setDialogFieldListener(listener); fCViewGroupIncludes.setLabelText(PreferencesMessages.AppearancePreferencePage_cviewGroupIncludes_label); @@ -86,6 +90,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fCViewSeparateHeaderAndSource.setSelection(prefs.getBoolean(PreferenceConstants.CVIEW_SEPARATE_HEADER_AND_SOURCE)); fOutlineGroupIncludes.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); fOutlineGroupNamespaces.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)); + fOutlineGroupMembers.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)); } /* @@ -116,6 +121,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fCViewGroupIncludes.doFillIntoGrid(result, nColumns); fOutlineGroupIncludes.doFillIntoGrid(result, nColumns); fOutlineGroupNamespaces.doFillIntoGrid(result, nColumns); + fOutlineGroupMembers.doFillIntoGrid(result, nColumns); new Separator().doFillIntoGrid(result, nColumns); @@ -164,9 +170,14 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben prefs.setValue(PreferenceConstants.CVIEW_SEPARATE_HEADER_AND_SOURCE, fCViewSeparateHeaderAndSource.isSelected()); prefs.setValue(PreferenceConstants.OUTLINE_GROUP_INCLUDES, fOutlineGroupIncludes.isSelected()); prefs.setValue(PreferenceConstants.OUTLINE_GROUP_NAMESPACES, fOutlineGroupNamespaces.isSelected()); - CUIPlugin.getDefault().savePluginPreferences(); + prefs.setValue(PreferenceConstants.OUTLINE_GROUP_MEMBERS, fOutlineGroupMembers.isSelected()); + try { + new InstanceScope().getNode(CUIPlugin.PLUGIN_ID).flush(); + } catch (BackingStoreException exc) { + CUIPlugin.log(exc); + } return super.performOk(); - } + } /* * @see PreferencePage#performDefaults() @@ -179,6 +190,7 @@ public class AppearancePreferencePage extends PreferencePage implements IWorkben fCViewSeparateHeaderAndSource.setSelection(prefs.getDefaultBoolean(PreferenceConstants.CVIEW_SEPARATE_HEADER_AND_SOURCE)); fOutlineGroupIncludes.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); fOutlineGroupNamespaces.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)); + fOutlineGroupMembers.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)); super.performDefaults(); } } 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 92efa6b1e90..f40d3933436 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -136,6 +136,7 @@ public final class PreferencesMessages extends NLS { public static String AppearancePreferencePage_cviewGroupIncludes_label; public static String AppearancePreferencePage_cviewSeparateHeaderAndSource_label; public static String AppearancePreferencePage_outlineGroupIncludes_label; + public static String AppearancePreferencePage_outlineGroupMethods_label; public static String AppearancePreferencePage_outlineGroupNamespaces_label; public static String AppearancePreferencePage_note; public static String AppearancePreferencePage_preferenceOnlyForNewViews; 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 70888aa5123..1dbc739f33c 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 @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2008 IBM Corporation and others. +# Copyright (c) 2000, 2009 IBM Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -150,6 +150,7 @@ AppearancePreferencePage_showTUChildren_label= Show translation unit members AppearancePreferencePage_cviewGroupIncludes_label= Group include directives in Project Explorer and C/C++ Projects view AppearancePreferencePage_cviewSeparateHeaderAndSource_label= Sort header files before source files in Project Explorer and C/C++ Projects view AppearancePreferencePage_outlineGroupIncludes_label= Group include directives in the Outline view +AppearancePreferencePage_outlineGroupMethods_label=Group method definitions in the Outline view AppearancePreferencePage_outlineGroupNamespaces_label= Group namespaces in the Outline view AppearancePreferencePage_note=Note: AppearancePreferencePage_preferenceOnlyForNewViews=This preference does not affect open views diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/AppearanceAwareLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/AppearanceAwareLabelProvider.java index a8f7ebec1f0..26a8f9b7b27 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/AppearanceAwareLabelProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/AppearanceAwareLabelProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -25,17 +25,12 @@ public class AppearanceAwareLabelProvider extends CUILabelProvider implements IP public final static int DEFAULT_TEXTFLAGS= CElementBaseLabels.M_PARAMETER_TYPES | CElementBaseLabels.PROJECT_POST_QUALIFIED; public final static int DEFAULT_IMAGEFLAGS= CElementImageProvider.OVERLAY_ICONS; - - private int fTextFlagMask; - private int fImageFlagMask; /** * Constructor for AppearanceAwareLabelProvider. */ public AppearanceAwareLabelProvider(int textFlags, int imageFlags) { super(textFlags, imageFlags); - initMasks(); -// PreferenceConstants.getPreferenceStore().addPropertyChangeListener(this); } /** @@ -45,40 +40,10 @@ public class AppearanceAwareLabelProvider extends CUILabelProvider implements IP this(DEFAULT_TEXTFLAGS, DEFAULT_IMAGEFLAGS); } - private void initMasks() { - fTextFlagMask= -1; - fImageFlagMask= -1; - } - /* * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event) { } - /* - * @see IBaseLabelProvider#dispose() - */ - @Override - public void dispose() { -// PreferenceConstants.getPreferenceStore().removePropertyChangeListener(this); - super.dispose(); - } - - /* - * @see CUILabelProvider#evaluateImageFlags() - */ - @Override - protected int evaluateImageFlags(Object element) { - return getImageFlags() & fImageFlagMask; - } - - /* - * @see CUILabelProvider#evaluateTextFlags() - */ - @Override - protected int evaluateTextFlags(Object element) { - return getTextFlags() & fTextFlagMask; - } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCLabelProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCLabelProvider.java index 97e48632c95..dbf72819054 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCLabelProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/DecoratingCLabelProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2008 IBM Corporation and others. + * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,8 +18,8 @@ import org.eclipse.ui.PlatformUI; public class DecoratingCLabelProvider extends DecoratingLabelProvider { /** - * Decorating label provider for Java. Combines a JavaUILabelProvider - * with problem and override indicuator with the workbench decorator (label + * Decorating label provider for C/C++. Combines a CUILabelProvider + * with problem and override indicator with the workbench decorator (label * decorator extension point). */ public DecoratingCLabelProvider(CUILabelProvider labelProvider) { @@ -27,7 +27,7 @@ public class DecoratingCLabelProvider extends DecoratingLabelProvider { } /** - * Decorating label provider for Java. Combines a JavaUILabelProvider + * Decorating label provider for C/C++. Combines a CUILabelProvider * (if enabled with problem indicator) with the workbench * decorator (label decorator extension point). */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementGrouping.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementGrouping.java index c5ee694fc79..978bdc9ceaa 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementGrouping.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementGrouping.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 QNX Software Systems and others. + * Copyright (c) 2000, 2009 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 @@ -60,6 +60,8 @@ public abstract class CElementGrouping extends WorkbenchAdapter implements IAdap return CPluginImages.DESC_OBJS_INCCONT; case NAMESPACE_GROUPING: return CPluginImages.DESC_OBJS_NAMESPACE; + case CLASS_GROUPING: + return CPluginImages.DESC_OBJS_CLASS; } return super.getImageDescriptor(object); } @@ -74,4 +76,11 @@ public abstract class CElementGrouping extends WorkbenchAdapter implements IAdap return null; } + /* + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getLabel(null); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementSorter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementSorter.java index 603d8f9092c..aff59bf3d7a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementSorter.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CElementSorter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -47,6 +47,8 @@ import org.eclipse.cdt.core.model.ISourceRoot; * 6 Source roots * 5 C Elements * 6 non C Elements + * + * @noextend This class is not intended to be subclassed by clients. */ public class CElementSorter extends ViewerSorter { @@ -66,12 +68,16 @@ public class CElementSorter extends ViewerSorter { protected static final int BINARIES = 23; protected static final int ARCHIVES = 24; - protected static final int INCLUDES = 30; - protected static final int MACROS = 31; + protected static final int INCLUDES = 28; + protected static final int MACROS = 29; + protected static final int USINGS = 30; protected static final int NAMESPACES = 32; protected static final int NAMESPACES_RESERVED = 33; protected static final int NAMESPACES_SYSTEM = 34; - protected static final int USINGS = 35; + /** + * @since 5.1 + */ + protected static final int TYPES = 35; protected static final int VARIABLEDECLARATIONS = 36; protected static final int FUNCTIONDECLARATIONS = 37; protected static final int VARIABLES = 38; @@ -179,8 +185,7 @@ public class CElementSorter extends ViewerSorter { case ICElement.C_TEMPLATE_UNION: case ICElement.C_TEMPLATE_UNION_DECLARATION: case ICElement.C_ENUMERATION: - // TODO need own categories - return NAMESPACES; + return TYPES; case ICElement.C_FUNCTION_DECLARATION: case ICElement.C_TEMPLATE_FUNCTION_DECLARATION: return FUNCTIONDECLARATIONS; @@ -223,7 +228,7 @@ public class CElementSorter extends ViewerSorter { case CElementGrouping.INCLUDES_GROUPING: return INCLUDES; case CElementGrouping.CLASS_GROUPING: - return VARIABLES; + return TYPES; case CElementGrouping.NAMESPACE_GROUPING: return NAMESPACES; case CElementGrouping.LIBRARY_REF_CONTAINER: @@ -289,17 +294,6 @@ public class CElementSorter extends ViewerSorter { return compareWithLabelProvider(viewer, e1, e2); } - if (cat1 == NAMESPACES) { - // workaround for missing category for classes, structs, etc. - int type1 = ((ICElement) e1).getElementType(); - int type2 = ((ICElement) e2).getElementType(); - if (type1 != type2) { - if (type1 == ICElement.C_NAMESPACE || type2 == ICElement.C_NAMESPACE) { - return type1 - type2; - } - } - } - String ns1 = ""; //$NON-NLS-1$ String ns2 = ns1; @@ -327,7 +321,7 @@ public class CElementSorter extends ViewerSorter { name2 = name2.substring(idx + 2); } if (name2.length() > 0 && name2.charAt(0) == '~') { - name2 = name1.substring(1); + name2 = name2.substring(1); } } else { name2 = e2.toString(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IncludesGrouping.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IncludesGrouping.java index 96cf6caad6b..584a053181e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IncludesGrouping.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/IncludesGrouping.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 QNX Software Systems and others. + * Copyright (c) 2000, 2009 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 @@ -52,9 +52,12 @@ public class IncludesGrouping extends CElementGrouping { */ @Override public boolean equals(Object obj) { - if (obj instanceof IncludesGrouping) { - return tu.equals(((IncludesGrouping)obj).getParent(obj)) ; + if (this == obj) { + return true; } - return super.equals(obj); + if (obj instanceof IncludesGrouping) { + return tu.equals(((IncludesGrouping)obj).tu) ; + } + return false; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/NamespacesGrouping.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/NamespacesGrouping.java index 58e8cb7c503..cb51edea7ea 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/NamespacesGrouping.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/NamespacesGrouping.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2006 QNX Software Systems and others. + * Copyright (c) 2002, 2009 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 @@ -13,27 +13,49 @@ package org.eclipse.cdt.ui; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IMember; import org.eclipse.cdt.core.model.INamespace; import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.ui.MembersGrouping; + /** * NamespacesGrouping + * + * @noextend This class is not intended to be subclassed by clients. */ public class NamespacesGrouping extends CElementGrouping { protected ITranslationUnit fUnit; protected String fName; - protected INamespace[] fNamespaces; + private final boolean fMemberGrouping; public NamespacesGrouping(ITranslationUnit unit, INamespace namespace) { + this(unit, namespace, false); + } + + /** + * Create new namespace grouping and optional member grouping. + * + * @param unit the parent translation unit + * @param namespace the namespace + * @param memberGrouping whether member grouping is enabled + * @since 5.1 + */ + public NamespacesGrouping(ITranslationUnit unit, INamespace namespace, boolean memberGrouping) { super(CElementGrouping.NAMESPACE_GROUPING); fUnit = unit; - fNamespaces = new INamespace[] { namespace }; fName = namespace.getElementName(); + fMemberGrouping = memberGrouping; } @Override @@ -46,17 +68,68 @@ public class NamespacesGrouping extends CElementGrouping { */ @Override public Object[] getChildren(Object object) { - List list = new ArrayList(); - for (int i = 0; i < fNamespaces.length; ++i) { - INamespace nspace = fNamespaces[i]; - try { - ICElement[] objs = nspace.getChildren(); - list.addAll(Arrays.asList(objs)); - } catch (CModelException e) { - // + Set list = new LinkedHashSet(); + try { + INamespace[] namespaces = getNamespaces(); + for (INamespace iNamespace : namespaces) { + list.addAll(getNamespaceChildren(iNamespace)); + } + } catch (CModelException exc) { + // ignore at this point + } + + return list.toArray(); + } + + + /** + * @since 5.1 + */ + public INamespace[] getNamespaces() { + List list = new ArrayList(); + try { + List namespaces = fUnit.getChildrenOfType(ICElement.C_NAMESPACE); + for (ICElement icElement : namespaces) { + if (fName.equals(icElement.getElementName())) { + INamespace nspace = (INamespace) icElement; + list.add(nspace); + } + } + } catch (CModelException exc) { + // ignore at this point + } + + return list.toArray(new INamespace[list.size()]); + } + + private Collection getNamespaceChildren(INamespace nspace) throws CModelException { + Object[] children = nspace.getChildren(); + if (!fMemberGrouping) { + return Arrays.asList(children); + } + List list = new ArrayList(children.length); + // check if there is another member with the same namespace for the same parent + Map map = new HashMap(); + for (int i = 0; i < children.length; ++i) { + if (children[i] instanceof IMember) { + final ICElement member = (ICElement)children[i]; + String name = member.getElementName(); + int idx = name.lastIndexOf("::"); //$NON-NLS-1$ + if (idx < 0) { + continue; + } + String namespace = name.substring(0, idx); + MembersGrouping memberGrouping = map.get(namespace); + if (memberGrouping == null) { + memberGrouping = new MembersGrouping(this, namespace); + map.put(namespace, memberGrouping); + list.add(memberGrouping); + } + } else { + list.add(children[i]); } } - return list.toArray(); + return list; } /* (non-Javadoc) @@ -67,11 +140,12 @@ public class NamespacesGrouping extends CElementGrouping { return fUnit; } + /** + * @param nspace + * @deprecated + */ + @Deprecated public void addNamespace(INamespace nspace) { - INamespace[] newNS = new INamespace[fNamespaces.length + 1]; - System.arraycopy(fNamespaces, 0, newNS, 0, fNamespaces.length); - newNS[fNamespaces.length] = nspace; - fNamespaces = newNS; } /* (non-Javadoc) @@ -79,13 +153,29 @@ public class NamespacesGrouping extends CElementGrouping { */ @Override public boolean equals(Object obj) { - if (obj instanceof IncludesGrouping) { - return fUnit.equals(((IncludesGrouping)obj).getParent(obj)) ; - } else if (obj instanceof NamespacesGrouping) { - NamespacesGrouping other = (NamespacesGrouping)obj; - return fUnit.equals(other.getParent(obj)) && fName.equals(other.getLabel(obj)); + if (this == obj) { + return true; } - return super.equals(obj); + if (obj instanceof NamespacesGrouping) { + NamespacesGrouping other = (NamespacesGrouping)obj; + return fUnit.equals(other.fUnit) && fName.equals(other.fName); + } + return false; } + /* + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return fUnit.hashCode() * 17 + fName.hashCode(); + } + + /* + * @see org.eclipse.cdt.ui.CElementGrouping#toString() + */ + @Override + public String toString() { + return fName; + } } 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 f913c500c3f..9b66b1bf81d 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -747,6 +747,14 @@ public class PreferenceConstants { */ public static final String OUTLINE_GROUP_NAMESPACES= "org.eclipse.cdt.ui.outline.groupnamespaces"; //$NON-NLS-1$ + /** + * A named preference that controls whether the Outline view should group member definitions. + *

+ * Value is of type Boolean. + *

+ * @since 5.1 + */ + public static final String OUTLINE_GROUP_MEMBERS= "org.eclipse.cdt.ui.outline.groupmembers"; //$NON-NLS-1$ /** * A named preference that controls whether the Outline view diff --git a/doc/org.eclipse.cdt.doc.user/images/view_appearance_prefs.png b/doc/org.eclipse.cdt.doc.user/images/view_appearance_prefs.png index 2fb57f4637a17430229c7d0d7146c1c462f38c6c..f1093d876122278d995f7e0d403410fa55dbf7ca 100644 GIT binary patch literal 25793 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 literal 21671 zcmZ^L1z1#HxA!1|3W9)iDuQ%(qYU7HbV&_#L^D9k|WduvXl+@|4|cLfxUEa`SiZEZB8-cUi#N9U+gIc#95txajx2 z6~F}P*CRD?ycod}7@*vZV)C?41>7c?CT-9m?l|jEHb?%4nAqt$^^Ok-mM!BYK!r@^ zaT0e5IUY1^C;EF$PgkG#k#ghrv?8!UJuU8-q@a6_Z`nZPkJB+gRxPBJQQc%|gj^gD<#rQ5$$ z|NNv5YWO@y1bVCxf}7KUaX?JZ8e5(1^(<4k3o#u3^HZWJVq7HHe;b)P~=cpAtJeAWnPrqn!+fbWupH#~Tf&i5TtnN{PUAzIPr42exKJ zcrumaFtc!xYFteJA*VWjvg^i^&9C^RH+2X_a~0hoySFR`HbhLiq+cgDD8@#c4T7qz3!Vw#dHWD=WB}T(0xQBu!Ku9e$%AXWE*ue?ut)u1xve=x?a#ht zq_Io%nT0mNWNoSnHP2lv9&qvs3v`kmyyrN9mI$*?V0awgveega^^Om3j<7r2RG~ zgqrpnm`ELbnp34RbmDVniIAkIk0veUpy16r1VvaNcu`6Ghz+OxjPKm8-)R`KzjozD z0tD*r^2Y6YK;3M-*o$%;$1m2md@Xp`H9`;PRZ`0Yw|?m_8Hoh#k%qG6MeE(&*9)@5 z3dwg2M`SI{PS~F&yced*Ghw!_$}w++E{f9M;n-^{DS8SQ)-#aTudd{nbr3}IxV5XK z`HYYegU+N@uaASKE$y}N9^>}#HiuW^^^leJa0?fiTL(M|Q;>SZPyq$ba z7Jp8{iX1M+&&hnL;_*-|-5<%IDzgj45f7exS!e^LgE9QIVK5j-H8OqCyvFG9Gw*Z# zKls=inDas*7l1KUyGfV{Wx#h~q#T)G;#drKLR;ui5;dRpfRvd7 zgi~1KTdqwaxovRKQ@tsFmOGgA1Zo64{I6vM9#Zh}SS*zz6GT_PG-|p-;n04pZhjL% zO|ys7Bpi-*gc=wGgfg+xu^3q+T~^^7G(N>6zfQ^R$UGm1KVIvNd}_wsWx|R;m%R>8 z9)wM`_)X8A50I6l2+aMUu007->D6;6+P+4JT+hb!J=(Nqiug6+WbkN!Nh9qvBw~Nj zxc?`?8`5dghm7&hsxgrPn{6(OHV95|*yhVY-An;+tU4^?p>*roOqZ9FEUC^Qw|Ndn zpWrkpyFUB9YD^TNPP-Er)Dy7X=Gr;N{V;Lvfng2bK`eXPsA5>*(3kPh%H&~(F!K=m z5c@E*FxSp%5FzTLE%57R8~4MJyP$6%P%+4#Cvxm8-}LfCQKjjR?#k)tVXN7Xo3EW{ zdwX4F)Q@p7#e^O-)vVIVI#VBoe$aX4W5S{7Eb5XZ(uY_*F#C3>3YMX~8*MOiNd`tR z5n;~5c7D+EiK$4UG3iK)6Yg%U3B6B3!cC3&kSVjkxN7UNslKN*EsUja`G~8|Vn5VJ z-Vc3L#$m6&RB3`*s?0bNp}U$MCX*C#JE#YT@je_Q51UoQ>>>@1YQ-4zFGzow<2ZI4 zx0z~Mf~qW+5V0OW#cXy>$J^^_7ui=$YgbH3W_hfMHx3)zY{m1qOfNV{^mq+cFE4~& zsLb13t;};BpTDEKETUO;u%$M3bh}P4YjjWq+Y+xfQ_(2YcRQtnCf0vfwNlp{NI%I0 zr$6z>XveLAxiu4lP_0h5FbuZ#SX87o4vxa-_%QpPZr;~2)8oHMEsLxh%eEvB|kn{Q{H(v0|RRd3Co#C!0O6=Oa=hGFHRO9vg>w~(~ z)b-uVKgZ5B0&^GT@?4V#I|cI1V_nXK31taNRkOHIHnF;NrphBv@H-0Vo8@n zhfNWgmCSgI3J*Z$(gn&)(kRj%n0ageo^`P^TUqdvSafxjIRr(7k~|ih@WLJNypd{i zNjF49k~v^dH+ep)ECORv8nxarqXx}DZlLHxA4)4}7IE{6MqZR;1O0Kw*JlSM z)w4FbecE0*V@B3hNqxr(6%y;>#nna*f(xOzIv-!0_(U00pH-A38%Z5)G{!XVH$59a z%niS>;gs-u*y49{?4jeX2pV{d3U39*agc;9@Ie=Uh z@DTJkdB~o4Mwq%DuD{NWQO}R;?G~r(?KY>JZC3sEA@@DZk?M2|X%|z*J8sO7dPW#V z$zq-S{P_moycd;!h1BI|x|_CxfwRepM!_Jz6_!EDOcTM_yZZ(d_w;;q0)oXPBOhRy zBNUXP3h1QHK0?!(uK3A2@=OT1QNeizDT-gv*^OnIHhim&&}l#2``W`xSk2y#nm&xZY0w+rOPUPSizmtoQ@(jjiE#G(_b zI@80|IVR^L7WW^vd{Lg!P$2I3%#77?^s$P3I&2EN;Q^hCZD-{)Hx)tfc;@e)e)Z?Y zH!foS&ezv$bCI<5u2Ckz?lqdYv62Gz#2`Cve@MOyh?3m+kr_2QMis{aGxts`XtUY# zW;L=}rFu)dzH!(_C|SE=OwYPnN3SH#qJGLoKz}@xw*6opyG7HH3P(A;?n{A#_b zy6d&OTjtIEJCB+VT57tgl_U=1N`3Y%IVDP=$cdFmiOV&vt4qG-i=B1F`612H$LfTP)SYsn~?G8mZK`?U;1|cD%zbnSu zVvP3B68M!1>}Gc8b;~%V&#;&6Z)|=IAEX|Ozc+$#O!qjLInVgfVJ>)fx?|RG&YVUU zB>OrP+V{*~&eptJmA&2?eDB?pmtxsSx+?BGp!?ik$M_;)htK#(Q7S5||68K?b>Mhp z-l;_K>y8VuwE~&VUM7>hI@2*^a~F-J)*-Mep~`osLeEJEjX?9>{Q24U~{j9f4mRI z1&81=%d~$|=N5ZUUya*CII{Mx+$g^IuEGlss1Bxri-nTlVja#M`OAZ0G^nGx%8VlS zL6v86d_cwZzOrALel3iXZ|m6#w;Y6VP=H|WGYCxdTYZ!qttyp8V) z=nM(l_4=*W zA2-nHB6{aS>Uz(3o@Z73O62>?V-U!8^PZ`aj#PAHoyj-u_#YU8aGFD%MjCj%Ll*V1lqVY6Ado5!QW5#tR>^o=W1Zr}}Z z!;g>l`nMt)_QG$}@~vRE=XG6{I;KQ&K0MmHa6|YV7R03ah8=|ZST><;&{2{u!;t(# zX-tO8w=!prcfyBE5T?R)e6@SYsUzXlrz7=Dpk>2B66TUB*!s&>?lQftey42vEE8Aw zb=}fz=)>LDKlb4+q5FmOR#-Xb&;?lC2MLRSwm~+9;cv@5lXNMpMIvZ5#QS>XNou9txuVx#lK#k{Cf7Q zao6b`-IF@#{OUHFQQQYrer~k+BmdxT^WdyFHpfP>Xf%r4p9oK_`?Hla*g8=ayG!i- zsZpeuh3gKrt3l4wY24xAT0wT4xf1ni82Y8yk~@>)>vl0)dTssUYW^;e%lN&WJx||D z4la%10$qORD;2vN)Go&4pMqydV-MJ(=#rJYWgL>}i6D0*p0qP%o-$)pZK4%OwVOYd z=<_29*YQV5n{$rGL#qyy)$ z8j{CT&tjNJjrUWT0KdB-LuPnFtpWVykL+2?#V+itt14KN6Y7rJlCKKKZ6_tC&v<`v zTFKkFHY1)BccS!ErajG^0>plg0~c?kK87N#)|%Hm4bF`GjBYzB+~@DgXsGCpuhbv5 z0==o-j9f1=`g4lMg;5!tRf)SD>S}3p6T404Q+71f9O&8!eJi%4bEsw}O|`>N`~ZX} zjQi&kP#I8%K^K_2-UD!3T%4eYhs(^N!DVp44HqkO!U_oA1Xo zKa!3JT1AAyJ^$Q8c123rT&_ut4&7V+*fSees*X0xu+W`;XHDuoV|_V!wej`+MMRdw z<>fr(d+&L*1LGTPe}hBsRb43>31<4j`)Un6KAPlnovP%S;NO0;6&T+Y5%hP+x<3#5 z<604J`&g2}j+?@Zh`U5zOhbn%-zE|K)M~D}!(0Mpv%=D6!7bz{yBi-EpJgCVO$KKh z4nY(hu!=>#QL;~h{hSH9cHC+AyFY|8$4@3$iG_sO-kQi84yXZ?20Gg>l+;C8MiWk9 zb;pcS8uPe-Ysi&oX3V$`#!SBC!>CXK(+9!S{oPRlpcem+BejvkzI|dHAvYuM4KJi# zDsIuNnjz2D`+ijZ8fHI5jGTUxikk~;w9ccMA|%xM!qX*|C-<3`y2KuD`Q=^MQ=Gv} zkQF0kW(IWtTld(YUL|Qsqhci`Z1INiP5hW0Rj&H9Y`dmH>*tRjZCljJGS~xh;+ET> z3vZV6;MLTKqJ+0p&q1i_4@K6@8rCJfFka#hc~p#%8TN>HCw5^{J9#@~xglyOZ)xKV zrXYx_Th6_oMLLW;61QULn@snoVWNxAc;+t+66xV?&venF34xk{e&?|o!$<*oy=Qv( zg3471`UH4L)#sOD5gCmS@?sZp01{+K&zh{v5V74Cu=}1<=t!4}%#!p8>9m@qEbB*%m!6L zINIkJLhYA@mk^O0xPqhbgG*)Q2uO`e7{auEj;6urOrLCe^iI3xcfR%S9Lu8HCNm;JH3wrqaPyAr2;IfZP-jlHNn$sf8Ls=phaA4ztl>4X<(3W(o9fdA9=7JHipZ|i}7G|@$29XW|46;q4c0l&jg+0uJ>feJIoe}i18pJ z%d4%XK8bCQ+5)MYzD}VlL-YenYW#lk3duu7<$mSsJ1YECWi-JNvMqIV_immMKqE+> zi(10P=KJi)zraMAJiRUUN*oR3o35T$7j$4e39pT%d&aqpc76YnxCevsIdv&R6mH2= z3rl=ULMuEb$7OzZn@Q+f+%95DJmIwznaFWgy|TvO`nvT?UO`Nx1&;&k*taE_D5X1& z7*(QXv59zy=dY!(6|GXq7Av{HnxTTg=mOX+59j2)LpMK2_MEZB!Ax54-rdt{XXE^B zs5y2=rj^wFL@Y|>&iAPp-8ZtGR=4UzkNoo=5xKQ~ z%x7ylQuTH4COO0B+nXP3Qw>~j(Qn>UvL#{*vvRKx$9X$ zNz(VA$jGZb1pO#hf`C4ga?!|1k zgTbqONz^bq<@~jq^$q8%@{0)-~6*r1C(y?)>rXroB%%Cat?T&NrH# zypDPy$@PMmkPC7|=BapT(W;ffxNeA*ATM;{M!Zq7`Mebhn|@5F=CUQ_xFs^+6F<)B zfA%HeYlQ1r0L8V%8SpwH=BBl1%hGZh0IvS zU1bXj-aQ{J^!5sIm=k!@smUptnI6=@~e&=P9$wTeqiu<`Ati? zB3I)iwD>SByD!kB)a(9TyQ1&c&YdI)jNgrRT#TFM`dLp32ZR&MoaM$99;_q`@ss^} zV5$;grhpzS+~T;PCL&y3m<+)X2xI!*jLwjcvV0g&vZ8KsvA-OJkXVlNvG^t;_~?7E zMUs9dhDAWRq4}<#>N67~MSe%J-Kn#{E2+A*g4N>@$T7jBz>?(Q&!I!b+D4fEAu;rd z?-wM4?Zbrno@-(F5GNumJUQ?E(mg$?HCG87N<=nW`qhVJ#oE`&_2!W#1Zp>&a}~}v z0WvCe3$J%4O6RU}zFQg-+w-N<(BN^1A5UTq_$sfe?_?lXf?QTLT{DtH>*pSh9UU{@ zZF3$jq;AY91-3_yx$Ws{)&8tPy z_NGY1Sk7aMg~?^#%AGoK$Z>r6_DIkRaG(>Q8h{Rpoow~xZ27n^lKL1SmCoXr1&PfY z;#hjBMJP{1vr}Qfl}lK&ODAHZj<_obz+_&?M0lHT^XSWZl8P|V({HGp1Yh(U`|4t# z)2l3=%mXG-_;sI+f`E{)1S=f4;eVLPe^?);KO%)Q6d*zn!mGr~e>(kc)Td;g&=-E* zyp#u6Y$RaFGJj75MzNniqJXkQJx0TSpUJKR)?E0^FVgEGVYlA$ zCSz@%jZ5-m!zY2kp5$Q=`<^@)Y%6~q>@{#Lv+H}nmf16Z-6|GM4_6OWiw_PS&uxOE z>)_~|;#`pxVZkTWW6Cxu#12=*6Z%xicjZyR!Sg0o9Dsde9g#roQFlQ1K|MAoZD(r} zcpmLXlSw~nJtEX|1a}=UR=&-7owI_ir43LE8ubK?jBEB>aQuD9cM7ap7fhqt2+{eD1SnJ8@)b z7enu9?>zSp8QhO8F_p0xE*S4VB$o_1MJZc@Q$*HuQ*u0;9D_JOPs!xzbU&;CY;wK3APTkGtD$K;MC=$F-KHi=N>7P+xrqkiV2N($ z7*f`tq%qb8(fa{l++t%5=*XaB_7t|j!C|Z_9S|n1@HP&Le~3v*ZPp!+m()kniOo2` zE47t9i!zU(jn18|FAsaofy=j<;gX!nQii=mUSM!#F0me+5N`7v2j5$IdP+v%IT0nM z$vKoj03Evj*5_|5E^`H3hZ>=9Devu9;_Zw`0!03X*nbW(Hbgj?x}VTz4yhVM7TxjO zmU4ZJZAK5cou-wPee+&umib5Cr4(|P4^t5}@2ro%KQa*7`bt2k)%uox2e3rv$j3lk z7gc5IU}e9j(}nIn-|+Hl^-7Ojn>-Lub1q< z(@h?YW@TiVp_EIIYPJ_UA?9lfFBD9DK{1A=FHCv?_|NmwfvAL9uGal&`|S=Gsz=hN zwuXJw9k9OZfplzDY2gPurmyM`>ddVe3akF!u$#X3+G(5Nvp&cuiOQ}4u8rgOlrl&pr7TbPN%Wh9 zYl}XK9mPiXJcG5{de%mjvmffMlo3-#SB66j_G7(dei)p?tVT&hl)gK2&?`>nL_*fg z(vx3lI_1p4++&Kv-_mcTd-rmy=E~7)q3$A1J%d_^-1_q5j}wbdJ$}ex~4tGdCZ2cU}%gT@JqmTWm zUg9y~U{;}@!~0!}HdU394E6jN>=2K~mYJ5G_``nq%${CBr`97*qlpGwh4v#{Yf8JI zrC)S?LMW6tZSmUKdCRnnhV*^eFSzC1RMO0kTAaunwI#pZaqeFDqTupe=EA|fla6>Nj8XSz{9vrFv zZtT|N+^v#?UIxH9xa$AJU)=0WG&pX~ext^#sV{8|sSqa`x{q?b;wZ9Em%yh-KsfZXCk;J!y?n7V<;Pri*&Q~}=sC{_(eI4M z-Y5XbQ#Bd@shn&{9qtG<)7M>Y(=|L}S#sqFLsb>4MoQiW!SvEi1bp+9qCki(*1jr+ z(hcuh_;)avzwJB}QEiU_YG5HZ(eKOoT>B#YHs+2Vx~#^I_m7U&6%-t4Xl&-?O}w9O znEjzQS2%f&5IL3I;*)$1m{qRi0BilhK?U44jI?Cd)j6liX;@z%{~XcUhTZDi59zsm zc0p-yy|B=T4P3aIF;ljqoMWOqhSIC^NIlbR0$Y zUnHLKyJD?r65d-w^$XQAlvQwq;F_hoW*yh{FWbg@*IV7WQ`|}wLsssx_^H=jC-Gu0 z=`-7YMwx1oWF)khOQYxD_W0pCN&VdRvKcu_Uu1R)%-C4_$BhiR#li$$RrvLDU1@U22_zVdKW# zKahp%=h=80yR{2Cmap{HejTv#$0C4Qd1jP+Gr z?%sd;yx_%fVXP94uZzN#_os4K0z5TO1fJ|n_G{)hmXey^1d_0Fv+uCrWnvkd9rRd{ zpx9;KW!;PZAY6Vgc+94%70*mQ&PiA|H7y^m;=2Zo$6T+g56_CYQhaqI7IGcXiO;(( ztu9AZ?>(uz@WtqRtW;|Fg_5Tmt*S!q867-kS6Q~maOv_F{HVZ`1EkQy?RGP6Cs(<678}(89vsEQB5Dw1E=N_ z*@NWptKVUAJI1Q$f=+x2mY07x``-)l6_?Hu@n?Jf>n##5*h7{{n_kAx>j~K5!3jO0lq()Uj z(~<%_s>f06b|zM){ew(bp6kxPr-W1>G@f;GVhmSOj{>jw$mfhTC!pGUyCP`!Xn1G# zYO!w$erl#=5|w%~wa~n!E33}2<0ix}1_zFJ9fL2RD9V!1h?-0tNdQ0YgYP=52R&{e zPH=iMr0gki8O}>VOXzIp^gb3eLMcceqy(6pB;ZLV)>irZ$x>`vvb>+_$NDYV>KG=A^CV?Z`zqquu|!zj4{$VE zG;YTi#f102Vz%OTQ(lG#Qn6=IUA?~npe6b$oBe_8;NUcM{S$in&_Zxz@}coS_1G@- zqWRdf!mF$(b{F&aMKwrD5#VJ=<9i7Z zO-0ink{TS$TiDvzJye>|$vIHNa8U}mFi&Ts&twMx|80EVfYJ!DDvI9b;xqz4u0rDW zH)v~jPq>Bzhw7|vBC>>Jm-G%gr94Vb-nzh$j_eUur#;jMFeW3x3!hT7x?%Pw{dR63r4(tvzK%55(f5vQ3|dj3ItHC{ zRZbjfDY6`nuEH;NKjnj-xzOmaFw(Cp!m`U~#uPmf5i1Cp@5yyDUYqALUN?bU#XnV~ zD%zIY>z@~J+I&G5`o{`Rxh3VuPzE15QiUSQcSnarBm+Y<`Eg%EzG_f*aE3_s|1cRY zTnKo#JLpF}&5g{jlay+mJ^E0FA_{HG4HxXmA2vn~u9PQdi$7tNm2fhU@_DVmSh1S$ zS}rV>)`8CmIZLXu%)%QulRde#%2F#dd(dMV$V7noIs?PWY2a=K43{cJgg11%HQ~kJ|^yZ`3Es^Jcou8 zN(gQ%dp20)1nK82J%gv+Ar+exS7;Wc+GaT2!V~NwrY?8disXr7g%eFc>&KCCT8uyu z0%2?P6kp*{O@<|lB4bGR#y=)I@$vh^3(11DFCT61)t{`zj0jjBNjaYOC9bHGXwoB< zN~83#TKRshe`7nCPTyJ_k7-0`DDdQ~Cc{l}rDeU8jfs@_>#>Ip+aGA>Du{fsVrr!I ztt`q8n`e3b3b$_ z?$xG8ZnJ)%5xP2bQn8g`DvB|E*A4oZ{BGSwX^|lk3~r*FDN0%1l+HkX_mucUh0?bh zFcdOLKZ;Y&^nbufs73l0ag$^aov=P8B#aQh&9H%lIr1+z_0Pc`y+iY31|B3pH7R8K zSH++$(p-6_onC1Ol2$(h!t+N;Z@P)cN!9d?4JuY1axzJbHkwRn8yi2U-v1gdjxF5= zP;9B7vvN-F3qsb@7_l}y7EXAd%&2=ED^SbQniWI;t)Z<&Le)Rg~F4>?C1f8x;z}9P7cAHu3GmE0*Ke;9mvHozQon}x>6T#>3 zX};kxHig~0L;_5H!>dYT$A5;F*!N+zdHwcv-Or_uk^HCOX z>w%X)MIKE&?M(j2mGFF_#gmN8vvmwoO?Ao=drI( zXcUcDPS8BvPkAJs9Nv^}=&XH%DZlqye8hkfuj&`HAo53$zKZ7{9vrWUEGUU_wt8f9 zXV`7_XeZlhHADHw;WxEI$oL>)MG(VHA6oU_*=Y}T0xUR2n27Lf z16s;ErpCgE)2+b&ZGlKl2OG40p_p161=vMw`eSqX1Eb}D0b;fK0;XHqMFH{uV}If# z&7t^1AM1~zsKV(qJTb;nVAQ47JB^FgWeT*90Ai&^Rx_|vc z1i2V`ZH^lPOpt?+jvgCRpdsD{?MgsiMlXZoAR928>B=sF`ufx5WEwo}- zh-KV8b+YOS+8@Nr+s?p)D|2IG(2_jP@2sKy<;7gHXXW3Jk3xg31^rzh+gV4@EHcxq z0Fh(U5~g#*XU$Nc?e;vr5D+@8RzqOU?1I;v$(?b>^j15Z~CUH%jJG3fTaX zD-y2_HpUrB7=_JNqlQ;q6QSl}AH6VaF(MB~KFRQA05VbHc`mkY%~0O=vA(D2FYsS> z*FM;0c8!@S?f+6u84WBF;0PJv|HTmkLEW(qz4j?AgR#8xD3OPZMPdf#G^23U{xf4d zkS^ML01{u~iMQd?Bd7P@)-j;rGJTmvKej3-7O|p4uS7z27+u?~qw!{3dCJi(>YXG0HpI}t_xcc?CzagCY4XF(H4D}2_CK~n>*~{E z{f;py9EV%f``2(xHX^UnwBvag@FWp}=THXgN)e;dL#c`_ zzxFuZJ)OLXwZuP;5q^cnUW2B%AnkR}Xs55>^x^&?~V50EZePakA> z-!rrN?V~A0>ol}|W7;Z1LD6B9v2NEFS-bna5~qg~Y!bi8o+FS872hkxT~QfLq7XWz zx>TlMSM@g!Ihl}#DaqCXI@G9J^C&aZhnrbWaUXx+d7oEUeCSv-y0EJiNpcmGz(}=r zVElH=@_^lv{bI)DoGC6GbInqIN@(5kRqdmU;@{69@qc2Yo1gn!(hMV)jD&jsAT>TG zG^L2-r6!6vUH*KAr1R=1irS3pQL--8#wuEoC43X|CR^YMBgkgxE({Z$LgA#LlV15}ZaG;oEfy zhc&aR7t{kPDgzKH^{#l|(N?sA$kT6!x9N(nQQxG++4QGzIn39UFV1(Is78xMZqkfd zZb?LsmC>&MA`#z=3*$V#QYJj=xcK1m|G_{@>`|KjCYIccbKx;6IoJjTtq*6aH{DD; zuwF8SewEVkweW4_{NSd8QlsedOwr5@Ow;GJQ2{-UyG*HJZ+^dj5nuG3 zGRePA;>|6cn18?bZ&mIs=u1;GlZI(z57!w1p&G|%u_PyvgW$16;0pcr!uCZLA(V+I=qL4)riTJL2bGX%wPmB8Sfe0iUlL-m8!_;N<4 zz~!}XctDx#*4tLO=H`woDV5ygmT2@HS=o*s!*M0qP}M#XQHG(a()~rIYPM%Ic6xV7 zQrza~)Ynz;)y&5blAKxwR&uAYwKL}|PsvK82~ZaP2h+vhA?v)f);oIh<`OZst0dWl zEPoa8n}nzP%Fm}DfSDiYlT0-#iQ2H8T#wXIV>o?M-KUC_K5A>e$EqkI0@op!C}%H~ zga;>DV7^Hhm2@v37i*;U!i;SeAB8c+^pGg9M2CLF;+wTfPTgOy(n7>~+LT`?l(vzI zjk2SOE$H_^{Y zka(N}>e30Y?otRv!_S}=DucaQ?)7akq)5wTObW{t7zL)gOP6;tKT}({_S{)VPk_>7^eWzn1&0paT#Qy@_^f89 zeLYOtvM>fNj~3*TP>xOB%1twrf0BefpcW*^awU>Y*g~Cvv)uUg^N!2|&J+pPC!^Sb ziv7`^in=7P2k+GjRx5QsAJV`Y>KbC4dVdC4=OA|Hg$=;lH>dshzbT9MQvYykL*-hj z-kM9ft>;J_itI1v{^r;{f1}|Mgeg)=^;jAkmaxVe$we?W{of|R{tv)!1;X9+^g|#W z_2Ka=6mF8%^eQ}Pru>cA_(0*s*(66$1cX+#P^XoY4VQN67#+tZTmag~0vD(a#R?@F zV{b0NY?kC|6!bohC~jL!3D!LzB>Y-RE8_40_Ipwk0YP^a`N!aQ?w*8dN7c`CBK@tQY)(=!cA1EVb6%(^fC3?Z4&J z5DI$E1L+23>MaG){gCzwC*G3vD;ghc!V`6y=P#>P0FWQe4wWKtuCSvj?oWOXglYaZ zAS3Qx|6*`g=v>%SNyuG7ILBuz@X-EB&@d_(sI)y9$EODX)Jr_4Tb}=ROa9yL|KmUv zO`X7}2AF?@J7LZIpq8W0OnA9q-BUn9x*I&JnoUc0hoWBqi!?7-c9~IaOOgoFf|`Gb z>7L2udJ0q|ArekAu^w?Tg_!0Ejp?`51P4GG6%)va2=A%KgR#7I>omOe0A7*wID+O0 z?aUh0pCc$952^-ciz0@!hJ0JlTr$~TPoRq7XRdyOUBe^ryag`pG#GJVE07;T&BmS4=h!}l>q$&1}u?FUH z6!H%?8aMcxRSbYA!M|G*}O>=)a(=-eNvEVf37`rdm2+GaQC)O6X6diEO7kH|KIW7e-v;2 zbpWV}wzG2nq>b#=pn~ zc^g^P6w+ALzt;@h>Vo;$TchQCs|V?DS?7ww$FmAK@l@Rs4U>!_FklV>>Ok5xagGR7 z*#B`DGxxk&c%jT$)dDDfxo8HSBZi!-CE|Y4j7DdxeWpFE$YSTXLNc#!aNU}#c@1m> zjjyVZq`&v7dm88&Im)7)fNG`3+pC+Lr5|S2p2fdw4yK|ps*DMrmGjzk5eFg@p}mBF6Rk3i*$ewlJs{9|=2is5HuQZ28yuaD^ z0qOz7hQ7<4t458x(QEsI;V?$!zvJsam`64O)o{1wGm@d@_cseP<+t4}R(E5aX(s+h zro*z$sLwdPuz!dR$PJ6lvY!Q24ZP{u@?*Ms%s?-(r+j{)U}X*MJqEPj2g5S{m$YUG z|8|sc2sf}bt^aF6W4_L<$3^X*G zwC81y_W=9`tE`B~&SO6Lc+yqsp7Y`Fbjco<>3;*|ga%XjR{?~AXDRTe3t$V3-gGBG z)#PeT=n=-_7O<6v-Nm6oC4?i3#1fddg67LeucIc#(?)%IdOh2Jl^5k~jLZRN)NT6j zjLZL}Uu+3iF`v@28gT%&bijdnTlSzYgYY{aZ>9JNZN=f>2(+9VlTdBDxa1sB9>7Z3 zla&*6&J#ZP(@_zuDFz@FD&j)i*!`9p0SVQd*Hjd<)>d2)5|6AXnYhSk$~?N*oB2sv z-pB}G&ou!}WgKr(V(FlwiKFYxD#~o%Ibt?dWHP7LR}lkdcs*7u>EH;l>mp@+s~R5u zmDerwo3CnyD&;iRfYf6`EpWspdYm)4qyTmJw!N_oIZtQ7fBUAUwhT|lhUcnjAG2Z?SbQa@VRJt_~CnoE{W!-$v}m|>truGK#Ix`-GY#pc>8fd>l?#?g*CNBCOAi^<73*Jne*H9l&5AlFsz znjGaTFh7S~nYjWR81FfX+?L{_dgVa2!H@*Dm|}fX#++1vo$yGUPH9>ISY5jE5%gZB zZFGXulAC{h|C>bSI+Gi6AXQgT1GckiGP)Az)9UgcS>daXh2M%c%Ki6zc*>~M(VG+{$jNL8`OoVk0E(8mMT6AHugdEg~kra<+ARszBjXo}9a+gSSSZ-HEk;2)RqkN;@1T0x}r0I{nu z7h41_YS=`B*T4oSRB9~Ws-_B+oZ{7Q!4^2+cRbYr->z-?dKF_~zLu~dFPQ||+{ zfO~9yHjiRbV?KKA87^Jhn4O+Hr!~Z(ZT(?)RT~aic#rtL6^-%o0w|pu@s|apl{@0J%dIUP*+{mr>q2R_mfQU%p5tALHxjNuGBi zmy>-O_zdfaTeVh5b-pbyN8~F-CO?W1sbXYv0fC5L-2PtxAQs;L2l9~r`3nH)|D(f$ zH398}{}R|l$eCpe;;QFlw&F(h!x_+LbnCk_d(2kldmG&V_4WKk_dnP?yW3_=y`J-= zZuXDNOM!R-hQoAlANUX=&h&cRc;@OqiDG#l*5@yjO9;@EfT;vTB>Q5akFP< zx)W734zn(olZ*eViZ9PLrYzH1tds&Q9O)qmlx)>Pua5*-eH+@gCgV3JYrW7@K&uL+ z$-foBk8;GM1P@MM5c2e4mvMSMiZ%cY%>a;i?Efrvo1x^{8jdSd09zm5m!By*F>KqN z1?FR}Iph%s@T7!8!38r7x2>tq3NmjYxwzX!H_^TEIK^CTVY&QPjETUV6c;h!#rCBEeC zvQ4v(KJNhmexr`HQqn;+|I(h{2ER<(p}WZxv*bkBHShJvEoTX|6y++`h7|Zy)~(mS zB{Zg|?^eOk%8%L%NrgxX^dn+Fl-2Eg^tkmO1uu`FP|rV2HcPrdOzzG@oFlFitYUV2 z_i0ZjRIj{+Bp%)qdsy|l?hVy8w>iWLblb@kt0Dq0no(I_*$aHSpHGn;*ZpM&&O6Tk zR#Nh>8oCWDRB{3QtBF94{{gdzb?C_cdK%j|fCvZ+yn*h)O4nEo zpu)ltOvMq3ymg6kGS)}XuO%BCxFdkbt(Yq$9rD+Tjk%x1ZvEf}Rx*~j0j?b0KwA`e z>Pws7!Z%aRa!JksTHqbyHI_O_&gigFIjv@C2>>a{Esr9V^oR_9dIRW84)dREG2ma( z^M4Pb-M!GF8$;Aa6yVr5G66}ou8j@U*wrg52;|d{z((wDyDu35n$eHvc@L~u7*Gi< z4GSLw6;E9Q@XO+f=VtU&DfzW&P7Oo$GG0;I(xKyTUx`!>J_jPYXLoT_GK1N#^i-m$ z$`fEg zwmFc#6j33;a&H(n(7DB-u(`DoISR#%6=r0z`6mcROmzf}h#3daC{ttwWP}ue`l=af zelRlE6_|9mm-7Sj*)5RU28!32^qTy);F*%=A6DsK*(Ffh@H&Ta=4mqg3m#36H33)c zj{?LFlM--}lBHJCp)%1>{cLhlH%)zG`dAZ>tT*u%SropZtC?UIG{c)dEIFqW1RfoF ziw{BttN={DM7dXZyc}IBxx>9gKk(qT6+0w7_8h^YW$hJhbaC4nstz>VZQh$@&vBG_ z!Ed&W8jLp4Tm&B84X->$NW?`c=?+)Lus8A?0vc7O1y~f%o6mqo;AjMT#08Pz|DQgt zJgSK-{RR=SMWhkgchGSG1VsUX5Es-&G$@G362OiaXagEq!e)XX1eIL{Wf!DTfe6Gv zSVDlP5mW*qYakKAra%&8Ng&%4-7~-Qn{(#OUv=u#JFniWdiCA!es%9N@m)VVee9`k4Tmw# z-}+<w$aR;i+VHC!oTIP)ZU#Dv{8(G1*4X#$%KD8o22{(cvyJh|Hh5@}zTb89BO`or z-~dXu{JJw>dnmbsB7(y2lX`o#L6wziUh~7G>(0t3n8D!*yaQy{#!*vTw~2Dk_#dBv zsb4gp^<_ZcJS}9-nEQEpej21MExn&hb+hfLoo#KYm4|${I*!W6^BtYi?NX<8uW?-l zT8+t-lCU07@fS!ckf2$mnUs8!&!3#^@_?3?Td$=zX?-}?tcf0-Z4q_8+N-EDN_5fu z7VNgV?MmEL_h^&#u&iZ3>nSn#@>JGPuzwEXOTiHM{y{+w5gm=;c_P{~_t}9PzFxU} z2~Z#iLpwV!&h`hN`GXbiC)rG<`PT3C4mS$T8wz=;qK{p=VmMBYoqPKbCBP>w1;85fx#6?i-^`n z>{%#J>Avx85C*N;wsYKw69u(xojLXnqtOXYNiob>@6%t$!=y|UNw`8)0!(l%g7P2B}FNJ3q=kol<=?f6#M_aK7Fe!gUq zo1fUYC2i-*Kwu1I=zXfUm?(*RxWX|{*KKB>Sqqw!gpQ+NW3?GmM=rUpfhkPg2&zfp4hb!z>-L4!4$py29?nOBL4DmC*l zqaI;Vfjnk9J8-}$og|ikE?>48lRj6niMYoviKKrj#x$<;=|dKHZQHiNsOoBqrl8*b z#6(Z-9m=m6=kn_0u*=$Stv2u}43oU; z*$H0u-4&w}m>JcfB7dPFb^n5Q2(uad)hWa%7Yzlnp3i;0qfhQ!g)Z+L|3i_QH)V*a zmCrn@d8K6(aXBl%-9@;g$Lkw;X+2+f@hdYAAI#V?bFgo0&-Ua9T}6UhhryWUO(erP zUS4SWxl0Fy+`Ih6MqrE;e*GwU z9s0iT!phAvD>qn?QaWt;Dpg0pj9*v=X;_|p%|N%Qs)yVgt@GWuAyZ!$yeh%2UYRqL zKL8k;6pzA@b4r-iPJZD6*;_J?$41W;{VQN%J}VTi;jCLeS$yh#)kRqP&J}ZL+}pgG zN|kdSex3jBp!7h<6Znm$5Eg^Q`@L+dyKkxnRmVJlGE5X1?vYat!sl-$?v;3I{UBui zU&M86f-=H~1C*YB=@$^*{$1Mom+4A2?yHcA1aNwbTftG_um3uCEgwCyd@r5l({J%0t= zdb#2)(ExMrw{7aP+RA>-i4@c|>BaJD5^Hgm7It-K{T4+EH=?PNF#QOAtqCtg(2xBo-D%x#v)<-jhl+}w0cT1sQCj?u;M=K0be#GJdAs@hIK+h>8* zlh`RdT3mf4Z6V{~(qpzmY~;$FgwI^2lvj#Nm$AX} zyPS(6#!gP3gOOsqApkQ--M0=li52_7evS`78krT*Mn6Z&IlzGBs5+qq5rKVPb`v`R zp9PrznYGGgMR6?oqIRM=*`E(pwqIkzSxwS0igXF>D|twd=2%)ybDjbyzqbrT!s|V4 zl?DCEs6|#J_Q`JbO2FmsM7$Lb^QZM41cDnat9?y$=7LyOi6v=xEfd+%@)0Y^Rp-WZ zS%yeQJmg4O$8wVQr1f+5B~e}erH4xfV+ zD87z|2ZIh(*M8aVFJ5|7FD)7j9fQRFTzoxJZ+BYi=vWF(3RCI<@GCpV zjulk^;3;HfWxDF|F}mXztA$aedQ1Nnk0ff@WaQ^DwC#wg%UiI34R4|k?Ty z_ADV?nhqgpwt7oHR*+@#n_{NhsI*&QP@r&b+lJ`Qydhru3}7Lq{%=6^0swMF)ywXv zXNe00mw)Kz@~jA780+FHD}Dr_$ehT=McIiN#V3HF28r#fAuE zt|du3P;lW=cBLO>b)uu;%AE4h_7(@FBN0>pDVyb)JtuRJgVpZi{zUoaqYmBf~FWmS{FbNK);C48erOfP2YWw0I@Oz zo;-9DKqgmV`Vc!w(R`T&{Rv{x=fJG#|4N+WVIQbE^I8qVY zA?L;tb=^rw*Byx4)Dp?Bzp?sNozo;$=9Z8^^7?j?RIUzbBL1aLfeIkX%X}s>HO&VQ zw?aA#z^b|$Gz>3$s(%|B@f%LZ?x%mzQU0!He&lUJtXXu{ZW{R}zpkQ?D6}k+{xI=d zYaT_+3tr}crSPJ)b{9^Q&IU!1;KKqvR#IUe*&l+@1ipi|>aKm}rk_HF-}GU1Y|G}V zV3(ihE`{JQmySgGFkb^I6U5^a^i%B*-R23MAm3(w306ET%N5Qt@FXOCmpV*Pk6nex zjG(_|3iTod-mD|Mc*Hzrf%)L)@>yVEB%v>9wu(e&Z<;f+25AXKCAiy{H1Du~3V$)X z2maJeP!=ENdQNh1I*+lwlj>aZOnhh^Mw&TgRwNNUqtfD}6tWPVYLvXeMsf|ULVb28 zK|_VN(M4IoPFpplplYvUwQHrR$i&pKdizG{rm8uSJhF1bpO!KwOE%JgWX_SjIU%Q@hoL?;tY*6oS2qw3@@k4v>gv{K@8Kz}=%lD? z;{7`r^FiF=Yw+ho8QLnQp)#ONL0KY&5nLzlE$Vq+VKHvCG8HXPK7w^83Xc65hgVo!1C zomsAPD|vH!+xR9rK|n|4tGL6wVIRIkhUNj282V6v3aX!AYkP{{gZG03rNAVuotuQZ z$q?1E4LPHgN92G#&R&o}Ai>dha-dfEefvQmhw~^I5bq8!pE#w9J|IwR@%RSNH(6D6 z5J>;8rqwl_a9fI%{Uyk%{{=SuPsu1Jb3+Nx=6qoN)$hG))YSWVZy2isHi6}+>89Yy zN*3(C)r;X__0NsPb-8vL3~x;~sy{M?tu9{ks_%RA-fc()8_~HIxp0|f zv;`s!&}N<4CE1(%K;h)hthp12D-DEdjK9)k_0`^*tAtSp?=zR~RQ__=e4qq!;IgU% zc23@+$aPUUW!u`}YwmTCTOzv6$J$^1wkOM3?ZIz5qnw9Lgt{sq5N^c0r;zUHnT$sO QJCA~#PC^~=$Nl5~2~NzrHUIzs diff --git a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_appearance_pref.htm b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_appearance_pref.htm index 2493c35eca1..9b5b99c36ef 100644 --- a/doc/org.eclipse.cdt.doc.user/reference/cdt_u_appearance_pref.htm +++ b/doc/org.eclipse.cdt.doc.user/reference/cdt_u_appearance_pref.htm @@ -13,7 +13,7 @@

Appearance preferences

Use the Appearance panel of the Preferences window to customize the appearance of C elements in the viewers.

-

+

+ + + +
@@ -40,6 +40,10 @@
Group namespaces in the Outline view Select this option to group namespace declarations in the Outline view.
Group method definitions in the Outline view Select this option to group method definitions for the same type in the Outline view.
Sort header files before source files in Project Explorer and C/C++ Projects view Select this option to separate header and source files in Project Explorer and C/C++ Projects view.