Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Prouvost2021-11-18 18:34:57 +0000
committerOlivier Prouvost2021-11-30 22:28:03 +0000
commitb23b559d77dc4024dafc98c7c9909de0cb0d5933 (patch)
treeb93219d3d50fb869051a6a0ad843404016a7fa3d
parentbeb6c75755ab57863243c4b4836e74270fda6748 (diff)
downloadeclipse.pde.ui-change/188307/20211130152446.tar.gz
eclipse.pde.ui-change/188307/20211130152446.tar.xz
eclipse.pde.ui-change/188307/20211130152446.zip
Bug 577208 - Migrate the context spychange/188307/20211130152446
Change-Id: I3de773697657b3b07efcb86e183fcb9c59ddee83 Signed-off-by: Olivier Prouvost <olivier.prouvost@opcoach.com>
-rw-r--r--pom.xml1
-rw-r--r--ui/org.eclipse.pde.spy.context/.classpath7
-rw-r--r--ui/org.eclipse.pde.spy.context/.project28
-rw-r--r--ui/org.eclipse.pde.spy.context/.settings/org.eclipse.jdt.core.prefs9
-rw-r--r--ui/org.eclipse.pde.spy.context/META-INF/MANIFEST.MF25
-rw-r--r--ui/org.eclipse.pde.spy.context/README.md13
-rw-r--r--ui/org.eclipse.pde.spy.context/about.html28
-rw-r--r--ui/org.eclipse.pde.spy.context/build.properties10
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/annotation_obj.pngbin0 -> 536 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/annotation_obj@2x.pngbin0 -> 1185 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/collapseall.pngbin0 -> 208 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/collapseall@2x.pngbin0 -> 349 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/contextfunction.pngbin0 -> 338 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/contextfunction@2x.pngbin0 -> 601 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/expandall.pngbin0 -> 239 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/expandall@2x.pngbin0 -> 440 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/field_public_obj.pngbin0 -> 217 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/field_public_obj@2x.pngbin0 -> 398 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/inher_co.pngbin0 -> 265 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/inher_co@2x.pngbin0 -> 505 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/letter-l-icon.pngbin0 -> 498 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/letter-l-icon@2x.pngbin0 -> 943 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/methpub_obj.pngbin0 -> 264 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/methpub_obj@2x.pngbin0 -> 503 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/refresh.pngbin0 -> 586 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/refresh@2x.pngbin0 -> 1249 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/splash.pngbin0 -> 39688 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/valueincontext.pngbin0 -> 247 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/icons/valueincontext@2x.pngbin0 -> 451 bytes
-rw-r--r--ui/org.eclipse.pde.spy.context/plugin.properties18
-rw-r--r--ui/org.eclipse.pde.spy.context/plugin.xml13
-rw-r--r--ui/org.eclipse.pde.spy.context/pom.xml30
-rw-r--r--ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataFilter.java165
-rw-r--r--ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataPart.java212
-rw-r--r--ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataProvider.java366
-rw-r--r--ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyHelper.java65
-rw-r--r--ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyProvider.java108
-rw-r--r--ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/spy/context/ContextSpyPart.java224
38 files changed, 1322 insertions, 0 deletions
diff --git a/pom.xml b/pom.xml
index 151460df14..328f87113b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,6 +77,7 @@
<module>ui/org.eclipse.pde.spy.bundle</module>
<module>ui/org.eclipse.pde.spy.css</module>
<module>ui/org.eclipse.pde.spy.model</module>
+ <module>ui/org.eclipse.pde.spy.context</module>
<module>ui/org.eclipse.pde.spy.preferences</module>
<module>ui/org.eclipse.tools.layout.spy</module>
<module>ui/org.eclipse.pde.ui.templates.tests</module>
diff --git a/ui/org.eclipse.pde.spy.context/.classpath b/ui/org.eclipse.pde.spy.context/.classpath
new file mode 100644
index 0000000000..e801ebfb46
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/ui/org.eclipse.pde.spy.context/.project b/ui/org.eclipse.pde.spy.context/.project
new file mode 100644
index 0000000000..7ee455081b
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.pde.spy.context</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/ui/org.eclipse.pde.spy.context/.settings/org.eclipse.jdt.core.prefs b/ui/org.eclipse.pde.spy.context/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..c9545f06a4
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
diff --git a/ui/org.eclipse.pde.spy.context/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.spy.context/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..b7328a1b85
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/META-INF/MANIFEST.MF
@@ -0,0 +1,25 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %name
+Bundle-SymbolicName: org.eclipse.pde.spy.context;singleton:=true
+Bundle-Version: 0.12.100.qualifier
+Bundle-Vendor: %provider-name
+Automatic-Module-Name: org.eclipse.pde.spy.context
+Bundle-RequiredExecutionEnvironment: JavaSE-11
+Require-Bundle: org.eclipse.jface;bundle-version="3.9.0",
+ org.eclipse.e4.core.contexts;bundle-version="1.2.0",
+ org.eclipse.e4.ui.model.workbench,
+ org.eclipse.core.runtime;bundle-version="3.9.0",
+ org.eclipse.e4.ui.workbench;bundle-version="1.0.0",
+ org.eclipse.e4.ui.di;bundle-version="1.0.0",
+ org.eclipse.e4.ui.services;bundle-version="1.0.0",
+ org.eclipse.e4.core.di;bundle-version="1.3.0",
+ org.eclipse.e4.core.services;bundle-version="1.1.0",
+ org.eclipse.e4.ui.workbench.swt,
+ org.eclipse.pde.spy.core;bundle-version="1.0.0"
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.annotation;version="1.2.0",
+ javax.inject;version="1.0.0"
+Bundle-Localization: plugin
+Export-Package: org.eclipse.pde.spy.context
+
diff --git a/ui/org.eclipse.pde.spy.context/README.md b/ui/org.eclipse.pde.spy.context/README.md
new file mode 100644
index 0000000000..ff41fc8394
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/README.md
@@ -0,0 +1,13 @@
+org.eclipse.pde.spy.context
+===================================
+
+
+For more information, refer to the [Eclipse e4 wiki page] [1].
+
+License
+-------
+
+[Eclipse Public License (EPL) v1.0][2]
+
+[1]: http://www.eclipse.org/e4/
+[2]: http://wiki.eclipse.org/EPL
diff --git a/ui/org.eclipse.pde.spy.context/about.html b/ui/org.eclipse.pde.spy.context/about.html
new file mode 100644
index 0000000000..824948673d
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>December 3, 2009</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/ui/org.eclipse.pde.spy.context/build.properties b/ui/org.eclipse.pde.spy.context/build.properties
new file mode 100644
index 0000000000..66df5a7990
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/build.properties
@@ -0,0 +1,10 @@
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ about.html,\
+ OSGI-INF/,\
+ icons/,\
+ plugin.properties
+source.. = src/
+src.includes = about.html
diff --git a/ui/org.eclipse.pde.spy.context/icons/annotation_obj.png b/ui/org.eclipse.pde.spy.context/icons/annotation_obj.png
new file mode 100644
index 0000000000..828da7aa31
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/annotation_obj.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/annotation_obj@2x.png b/ui/org.eclipse.pde.spy.context/icons/annotation_obj@2x.png
new file mode 100644
index 0000000000..a53f05ca69
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/annotation_obj@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/collapseall.png b/ui/org.eclipse.pde.spy.context/icons/collapseall.png
new file mode 100644
index 0000000000..92cc57892b
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/collapseall.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/collapseall@2x.png b/ui/org.eclipse.pde.spy.context/icons/collapseall@2x.png
new file mode 100644
index 0000000000..8769e04da0
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/collapseall@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/contextfunction.png b/ui/org.eclipse.pde.spy.context/icons/contextfunction.png
new file mode 100644
index 0000000000..7d9f913b4c
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/contextfunction.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/contextfunction@2x.png b/ui/org.eclipse.pde.spy.context/icons/contextfunction@2x.png
new file mode 100644
index 0000000000..118737c3db
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/contextfunction@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/expandall.png b/ui/org.eclipse.pde.spy.context/icons/expandall.png
new file mode 100644
index 0000000000..08cb513f1c
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/expandall.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/expandall@2x.png b/ui/org.eclipse.pde.spy.context/icons/expandall@2x.png
new file mode 100644
index 0000000000..fcbf24f455
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/expandall@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/field_public_obj.png b/ui/org.eclipse.pde.spy.context/icons/field_public_obj.png
new file mode 100644
index 0000000000..2b3e8e51b3
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/field_public_obj.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/field_public_obj@2x.png b/ui/org.eclipse.pde.spy.context/icons/field_public_obj@2x.png
new file mode 100644
index 0000000000..e2695fae0f
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/field_public_obj@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/inher_co.png b/ui/org.eclipse.pde.spy.context/icons/inher_co.png
new file mode 100644
index 0000000000..a33523364e
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/inher_co.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/inher_co@2x.png b/ui/org.eclipse.pde.spy.context/icons/inher_co@2x.png
new file mode 100644
index 0000000000..fb682c09d4
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/inher_co@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/letter-l-icon.png b/ui/org.eclipse.pde.spy.context/icons/letter-l-icon.png
new file mode 100644
index 0000000000..115dcefc3a
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/letter-l-icon.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/letter-l-icon@2x.png b/ui/org.eclipse.pde.spy.context/icons/letter-l-icon@2x.png
new file mode 100644
index 0000000000..37868fc9c3
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/letter-l-icon@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/methpub_obj.png b/ui/org.eclipse.pde.spy.context/icons/methpub_obj.png
new file mode 100644
index 0000000000..a9be929f67
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/methpub_obj.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/methpub_obj@2x.png b/ui/org.eclipse.pde.spy.context/icons/methpub_obj@2x.png
new file mode 100644
index 0000000000..fefe4e71a5
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/methpub_obj@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/refresh.png b/ui/org.eclipse.pde.spy.context/icons/refresh.png
new file mode 100644
index 0000000000..bee8fe7a32
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/refresh.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/refresh@2x.png b/ui/org.eclipse.pde.spy.context/icons/refresh@2x.png
new file mode 100644
index 0000000000..89d4d48575
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/refresh@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/splash.png b/ui/org.eclipse.pde.spy.context/icons/splash.png
new file mode 100644
index 0000000000..ba755f9e35
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/splash.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/valueincontext.png b/ui/org.eclipse.pde.spy.context/icons/valueincontext.png
new file mode 100644
index 0000000000..533cfcc3fd
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/valueincontext.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/icons/valueincontext@2x.png b/ui/org.eclipse.pde.spy.context/icons/valueincontext@2x.png
new file mode 100644
index 0000000000..de9d23daa5
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/icons/valueincontext@2x.png
Binary files differ
diff --git a/ui/org.eclipse.pde.spy.context/plugin.properties b/ui/org.eclipse.pde.spy.context/plugin.properties
new file mode 100644
index 0000000000..c8536c2a43
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/plugin.properties
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright (c) 2021 OPCoach.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Contributors:
+# Olivier Prouvost - initial API and implementation
+###############################################################################
+#
+#
+name = Context Spy
+description = Context Spy to understand what is behind the scene of injection
+provider-name = Eclipse.org
diff --git a/ui/org.eclipse.pde.spy.context/plugin.xml b/ui/org.eclipse.pde.spy.context/plugin.xml
new file mode 100644
index 0000000000..3558708fb0
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/plugin.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin>
+ <extension
+ point="org.eclipse.pde.spy.core.spyPart">
+ <spyPart
+ description="%description"
+ icon="$nl$/icons/annotation_obj.png"
+ name="%name"
+ part="org.eclipse.pde.spy.context.ContextSpyPart"
+ shortcut="M2+M3+F10">
+ </spyPart>
+ </extension>
+</plugin>
diff --git a/ui/org.eclipse.pde.spy.context/pom.xml b/ui/org.eclipse.pde.spy.context/pom.xml
new file mode 100644
index 0000000000..f4cbf14ddb
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012, 2019 Eclipse Foundation and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Distribution License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/org/documents/edl-v10.php
+
+ Contributors:
+ Igor Fedorenko - initial implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>eclipse.pde.ui</artifactId>
+ <groupId>eclipse.pde.ui</groupId>
+ <version>4.23.0-SNAPSHOT</version>
+ <relativePath>../../</relativePath>
+ </parent>
+
+ <properties>
+ <skipAPIAnalysis>true</skipAPIAnalysis>
+ </properties>
+
+
+ <groupId>eclipse.pde.ui</groupId>
+ <artifactId>org.eclipse.pde.spy.context</artifactId>
+ <version>0.12.100-SNAPSHOT</version>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataFilter.java b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataFilter.java
new file mode 100644
index 0000000000..9f922be266
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataFilter.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2014 OPCoach.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * OPCoach - initial API and implementation for bug #437478
+ *******************************************************************************/
+package org.eclipse.pde.internal.spy.context;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.core.internal.contexts.Computation;
+import org.eclipse.e4.core.internal.contexts.EclipseContext;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+@SuppressWarnings("restriction")
+@Creatable
+@Singleton
+public class ContextDataFilter extends ViewerFilter {
+
+ @Inject
+ Logger log;
+
+ private String pattern;
+
+ // Implements the filter for the data table content
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ if ((element == ContextDataProvider.LOCAL_VALUE_NODE)
+ || (element == ContextDataProvider.INHERITED_INJECTED_VALUE_NODE))
+ return true;
+
+ // Must only select objects matching the pattern or objects under a kept
+ // node (to see where it is injected)
+ TreeViewer tv = (TreeViewer) viewer;
+ ContextDataProvider lpkey = (ContextDataProvider) tv.getLabelProvider(0);
+ ContextDataProvider lpval = (ContextDataProvider) tv.getLabelProvider(1);
+
+ // If the text matches in one of the column, must keep it...
+ String skey = lpkey.getText(element);
+ String sval = lpval.getText(element);
+
+ // Must also keep the listener elements if the parent is selected ->
+ // Must compute parent keys
+ String sparentkey = lpkey.getText(parentElement);
+ String sparentval = lpval.getText(parentElement);
+
+ Set<Computation> listeners = lpkey.getListeners(parentElement);
+ boolean mustKeepParent = (matchText(sparentkey) || matchText(sparentval)) && (listeners != null)
+ && (listeners.size() > 0);
+ boolean mustKeepElement = matchText(skey) || matchText(sval);
+
+ return mustKeepElement || (!mustKeepElement && mustKeepParent);
+
+ }
+
+ /** Set the pattern and use it as lowercase */
+ public void setPattern(String newPattern) {
+ if ((newPattern == null) || (newPattern.length() == 0))
+ pattern = null;
+ else
+ pattern = newPattern.toLowerCase();
+ }
+
+ /**
+ * This method search for an object and check if it contains the text or a
+ * pattern matching this text
+ */
+ public boolean containsText(IEclipseContext ctx) {
+ // It is useless to store the values in a map, because context changes
+ // everytime and it should be tracked.
+ Collection<String> values = computeValues(ctx);
+
+ // Search if string is just in one of the values... manage ignore case
+ // and contain...
+ boolean found = false;
+ for (String s : values) {
+ if (matchText(s)) {
+ found = true;
+ break;
+ }
+ }
+ return found;
+ }
+
+ public boolean matchText(String text) {
+ return ((text == null) || (pattern == null)) ? false : text.toLowerCase().contains(pattern);
+ }
+
+ /**
+ * Extract all string values in context
+ *
+ * @param ctx
+ * @return
+ */
+ private Collection<String> computeValues(IEclipseContext ctx) {
+ Collection<String> result = new ArrayList<String>();
+ if (ctx instanceof EclipseContext) {
+ // Search for all strings in this context (values and context
+ // function)
+
+ EclipseContext currentContext = (EclipseContext) ctx;
+ extractStringsFromMap(currentContext.localData(), result);
+
+ // Search also in context functions
+ extractStringsFromMap(currentContext.localContextFunction(), result);
+
+ // Search for the inherited values injected using this context but
+ // defined in
+ // parent
+ // Keep only the names that are not already displayed in local
+ // values
+ Collection<String> localKeys = currentContext.localData().keySet();
+ Collection<String> localContextFunctionsKeys = currentContext.localContextFunction().keySet();
+
+ if (currentContext.getRawListenerNames() != null) {
+ for (String name : currentContext.getRawListenerNames()) {
+ if (!localKeys.contains(name) && !localContextFunctionsKeys.contains(name))
+ result.add(name);
+ }
+ }
+
+ } else {
+ log.warn("Warning : the received EclipseContext has not the expected type. It is a : "
+ + ctx.getClass().toString());
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * @param map
+ * the map to extract the strings (keys and values)
+ * @param result
+ * the result to fill with strings
+ */
+ private void extractStringsFromMap(Map<String, Object> map, Collection<String> result) {
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
+ result.add(entry.getKey().toString());
+ Object value = entry.getValue();
+ if (value != null) {
+ result.add(value.toString());
+ }
+ }
+ }
+
+}
diff --git a/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataPart.java b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataPart.java
new file mode 100644
index 0000000000..868ca355a5
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataPart.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2013 OPCoach.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * OPCoach - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.spy.context;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.internal.contexts.EclipseContext;
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.services.IServiceConstants;
+import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+
+/**
+ * This part listen to selection, and if it is an EclipseContext, it displays
+ * its information It is used in the integrated ContextSpyPart and (in the
+ * future) it could be used outside to display the context of focused part for
+ * instance
+ */
+@SuppressWarnings("restriction")
+public class ContextDataPart {
+ private TreeViewer contextDataViewer;
+
+ private ContextDataProvider dataProvider;
+
+ private ContextEntryComparator comparator;
+
+ /**
+ * Create contents of the view part.
+ */
+ @PostConstruct
+ public void createControls(Composite parent, IEclipseContext ctx) {
+
+ parent.setLayout(new GridLayout(1, false));
+
+ // TreeViewer on the top
+ contextDataViewer = new TreeViewer(parent);
+ dataProvider = ContextInjectionFactory.make(ContextDataProvider.class, ctx);
+ contextDataViewer.setContentProvider(dataProvider);
+ contextDataViewer.setLabelProvider(dataProvider);
+ // contextContentTv.setSorter(new ViewerSorter());
+
+ final Tree cTree = contextDataViewer.getTree();
+ cTree.setHeaderVisible(true);
+ cTree.setLinesVisible(true);
+ cTree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ // tv.setInput(a);
+ contextDataViewer.setInput("Foo"); // getElements starts alone
+
+ // Add columns in the tree
+ // Create the first column for the key
+ TreeViewerColumn keyCol = new TreeViewerColumn(contextDataViewer, SWT.NONE);
+ keyCol.getColumn().setWidth(400);
+ keyCol.getColumn().setText("Key");
+ ContextDataProvider keyLabelProvider = ContextInjectionFactory.make(ContextDataProvider.class, ctx);
+ keyLabelProvider.setDisplayKey(true);
+ keyCol.setLabelProvider(keyLabelProvider);
+ keyCol.getColumn().setToolTipText("Key in context");
+ keyCol.getColumn().addSelectionListener(
+ getHeaderSelectionAdapter(contextDataViewer, keyCol.getColumn(), 0, keyLabelProvider));
+
+ comparator = new ContextEntryComparator(0, keyLabelProvider);
+ contextDataViewer.setComparator(comparator);
+
+ // Create the second column for the value
+ TreeViewerColumn valueCol = new TreeViewerColumn(contextDataViewer, SWT.NONE);
+ valueCol.getColumn().setWidth(600);
+ valueCol.getColumn().setText("Value");
+ ContextDataProvider valueLabelProvider = ContextInjectionFactory.make(ContextDataProvider.class, ctx);
+ valueCol.setLabelProvider(dataProvider);
+ valueCol.getColumn().addSelectionListener(
+ getHeaderSelectionAdapter(contextDataViewer, valueCol.getColumn(), 1, valueLabelProvider));
+
+ // Open all the tree
+ contextDataViewer.expandAll();
+
+ ColumnViewerToolTipSupport.enableFor(contextDataViewer);
+
+ }
+
+ @PreDestroy
+ public void dispose() {
+ }
+
+ @Focus
+ public void setFocus() {
+ contextDataViewer.getControl().setFocus();
+ }
+
+ @Inject
+ @Optional
+ public void listenToContext(@Named(IServiceConstants.ACTIVE_SELECTION) EclipseContext ctx) {
+ // Must check if dataviewer is created or not (when we reopen the window
+ // @postconstruct has not been called yet)
+ if ((ctx == null) || (contextDataViewer == null)) {
+ return;
+ }
+ contextDataViewer.setInput(ctx);
+ contextDataViewer.expandToLevel(2);
+ }
+
+ /**
+ * An entry comparator for the table, dealing with column index, keys and
+ * values
+ */
+ public class ContextEntryComparator extends ViewerComparator {
+ private int columnIndex;
+ private int direction;
+ private ILabelProvider labelProvider;
+
+ public ContextEntryComparator(int columnIndex, ILabelProvider defaultLabelProvider) {
+ this.columnIndex = columnIndex;
+ direction = SWT.UP;
+ labelProvider = defaultLabelProvider;
+ }
+
+ public int getDirection() {
+ return direction;
+ }
+
+ /** Called when click on table header, reverse order */
+ public void setColumn(int column) {
+ if (column == columnIndex) {
+ // Same column as last sort; toggle the direction
+ direction = (direction == SWT.UP) ? SWT.DOWN : SWT.UP;
+ } else {
+ // New column; do a descending sort
+ columnIndex = column;
+ direction = SWT.DOWN;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ // For root elements at first level, we keep Local before Inherited
+ if ((e1 == ContextDataProvider.LOCAL_VALUE_NODE) || (e2 == ContextDataProvider.LOCAL_VALUE_NODE))
+ return -1;
+
+ // Now can compare the text from label provider.
+ String lp1 = labelProvider.getText(e1);
+ String lp2 = labelProvider.getText(e2);
+ String s1 = lp1 == null ? "" : lp1.toLowerCase();
+ String s2 = lp2 == null ? "" : lp2.toLowerCase();
+ int rc = s1.compareTo(s2);
+ // If descending order, flip the direction
+ return (direction == SWT.DOWN) ? -rc : rc;
+ }
+
+ public void setLabelProvider(ILabelProvider textProvider) {
+ labelProvider = textProvider;
+ }
+
+ }
+
+ private SelectionAdapter getHeaderSelectionAdapter(final TreeViewer viewer, final TreeColumn column,
+ final int columnIndex, final ILabelProvider textProvider) {
+ SelectionAdapter selectionAdapter = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ viewer.setComparator(comparator);
+ comparator.setColumn(columnIndex);
+ comparator.setLabelProvider(textProvider);
+ viewer.getTree().setSortDirection(comparator.getDirection());
+ viewer.getTree().setSortColumn(column);
+ viewer.refresh();
+ }
+ };
+ return selectionAdapter;
+ }
+
+ public void refresh(boolean refreshLabel) {
+ contextDataViewer.refresh(refreshLabel);
+ }
+
+ private static final ViewerFilter[] NO_FILTER = new ViewerFilter[0];
+
+ public void setFilter(ViewerFilter filter) {
+
+ contextDataViewer.setFilters((filter == null) ? NO_FILTER : new ViewerFilter[] { filter });
+ }
+
+}
diff --git a/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataProvider.java b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataProvider.java
new file mode 100644
index 0000000000..0913d26931
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextDataProvider.java
@@ -0,0 +1,366 @@
+/*******************************************************************************
+ * Copyright (c) 2013 OPCoach.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * OPCoach - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.spy.context;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.internal.contexts.Computation;
+import org.eclipse.e4.core.internal.contexts.EclipseContext;
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * The column Label and content Provider used to display information in context
+ * data TreeViewer. Two instances for label provider are created : one for key,
+ * one for values
+ *
+ * @see ContextDataPart
+ */
+@SuppressWarnings("restriction")
+public class ContextDataProvider extends ColumnLabelProvider implements ITreeContentProvider {
+
+ private static final String NO_VALUE_COULD_BE_COMPUTED = "No value could be yet computed";
+ private static final Color COLOR_IF_FOUND = Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
+ private static final Color COLOR_IF_NOT_COMPUTED = Display.getCurrent().getSystemColor(SWT.COLOR_MAGENTA);
+ private static final Object[] EMPTY_RESULT = new Object[0];
+ static final String LOCAL_VALUE_NODE = "Local values managed by this context";
+ static final String INHERITED_INJECTED_VALUE_NODE = "Inherited values injected or updated using this context";
+
+ private static final String NO_VALUES_FOUND = "No values found";
+ private static final String UPDATED_IN_CLASS = "Updated in class :";
+ private static final String INJECTED_IN_FIELD = "Injected in field :";
+ private static final String INJECTED_IN_METHOD = "Injected in method :";
+
+ // Image keys constants
+ private static final String PUBLIC_METHOD_IMG_KEY = "icons/methpub_obj.png";
+ private static final String PUBLIC_FIELD_IMG_KEY = "icons/field_public_obj.png";
+ private static final String VALUE_IN_CONTEXT_IMG_KEY = "icons/valueincontext.png";
+ private static final String INHERITED_VARIABLE_IMG_KEY = "icons/inher_co.png";
+ private static final String LOCAL_VARIABLE_IMG_KEY = "icons/letter-l-icon.png";
+ private static final String CONTEXT_FUNCTION_IMG_KEY = "icons/contextfunction.png";
+ private static final String INJECT_IMG_KEY = "icons/annotation_obj.png";
+
+ private ImageRegistry imgReg;
+
+ @Inject
+ private ContextDataFilter contextFilter;
+
+ /** Store the selected context (initialized in inputChanged) */
+ private static EclipseContext selectedContext;
+
+ private Font boldFont;
+
+ private boolean displayKey = false;
+
+ @Inject
+ public ContextDataProvider() {
+ super();
+ initFonts();
+ initializeImageRegistry();
+ }
+
+ @Override
+ public void dispose() {
+ selectedContext = null;
+ imgReg = null;
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ selectedContext = (newInput instanceof EclipseContext) ? (EclipseContext) newInput : null;
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ return new String[] { LOCAL_VALUE_NODE, INHERITED_INJECTED_VALUE_NODE };
+ }
+
+ @Override
+ public Object[] getChildren(Object inputElement) {
+ if (selectedContext == null)
+ return EMPTY_RESULT;
+
+ if (inputElement == LOCAL_VALUE_NODE) {
+ Collection<Object> result = new ArrayList<Object>();
+
+ result.addAll(selectedContext.localData().entrySet());
+
+ // For context function, we have to compute the value (if possible),
+ // and display it as a standard value
+ Map<String, Object> cfValues = new HashMap<String, Object>();
+ for (String key : selectedContext.localContextFunction().keySet())
+ try {
+ cfValues.put(key, selectedContext.get(key));
+ } catch (Exception e) {
+ cfValues.put(key, NO_VALUE_COULD_BE_COMPUTED + " (Exception : " + e.getClass().getName() + ")");
+ }
+ result.addAll(cfValues.entrySet());
+ return result.toArray();
+
+ } else if (inputElement == INHERITED_INJECTED_VALUE_NODE) {
+ // Search for all values injected using this context but defined in
+ // parent
+ Collection<Object> result = new ArrayList<Object>();
+
+ // Keep only the names that are not already displayed in local
+ // values
+ Collection<String> localKeys = selectedContext.localData().keySet();
+ Collection<String> localContextFunctionsKeys = selectedContext.localContextFunction().keySet();
+
+ if (selectedContext.getRawListenerNames() != null) {
+ for (String name : selectedContext.getRawListenerNames()) {
+ if (!localKeys.contains(name) && !localContextFunctionsKeys.contains(name))
+ result.add(name);
+ }
+ }
+ return result.size() == 0 ? new String[] { NO_VALUES_FOUND } : result.toArray();
+
+ } else if (inputElement instanceof Map.Entry) {
+ Set<Computation> listeners = getListeners(inputElement);
+ return (listeners == null) ? null : listeners.toArray();
+ } else if (inputElement instanceof String) {
+ // This is the name of a raw listener in the inherited injected
+ // value part
+ return selectedContext.getListeners((String) inputElement).toArray();
+ }
+
+ return EMPTY_RESULT;
+ }
+
+ public void setDisplayKey(boolean k) {
+ displayKey = k;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public String getText(Object element) {
+ if (selectedContext == null)
+ return null;
+
+ if (element instanceof Map.Entry) {
+ Map.Entry<String, Object> mapEntry = (Map.Entry<String, Object>) element;
+ Object o = displayKey ? mapEntry.getKey() : mapEntry.getValue();
+ return (o == null) ? "null" : o.toString();
+ } else if (element instanceof Computation) {
+ // For a computation : display field or method in key column and the
+ // value in value
+ String txt = super.getText(element);
+ if (displayKey) {
+ if (txt.contains("#"))
+ return INJECTED_IN_METHOD;
+ else if (txt.contains("@"))
+ return UPDATED_IN_CLASS;
+ else
+ return INJECTED_IN_FIELD;
+ } else
+ return txt;
+ }
+
+ return displayKey ? super.getText(element) : null;
+ }
+
+ @Override
+ public Color getForeground(Object element) {
+ // Return magenta color if the value could not be yet computed (for
+ // context functions)
+ String s = getText(element);
+ if ((s != null) && s.startsWith(NO_VALUE_COULD_BE_COMPUTED))
+ return COLOR_IF_NOT_COMPUTED;
+
+ // Return blue color if the string matches the search
+ return (contextFilter.matchText(s)) ? COLOR_IF_FOUND : null;
+ }
+
+ /** Get the bold font for keys that are computed with ContextFunction */
+ @Override
+ public Font getFont(Object element) {
+ return (element == LOCAL_VALUE_NODE || element == INHERITED_INJECTED_VALUE_NODE) ? boldFont : null;
+
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ if (!displayKey) // No image in value column, only in key column
+ return null;
+
+ if (element == LOCAL_VALUE_NODE) {
+ return selectedContext == null ? null : imgReg.get(LOCAL_VARIABLE_IMG_KEY);
+
+ } else if (element == INHERITED_INJECTED_VALUE_NODE) {
+ return selectedContext == null ? null : imgReg.get(INHERITED_VARIABLE_IMG_KEY);
+
+ } else if (element instanceof Computation) {
+ // For a computation : display field, method or class in key column
+ // and
+ // value in value column
+ String txt = super.getText(element);
+
+ if (txt.contains("#"))
+ return imgReg.get(PUBLIC_METHOD_IMG_KEY);
+ else if (txt.contains("@"))
+ return imgReg.get(CONTEXT_FUNCTION_IMG_KEY);
+ else
+ return imgReg.get(PUBLIC_FIELD_IMG_KEY);
+
+ } else if (element instanceof Map.Entry) {
+ if (isAContextKeyFunction(element))
+ return imgReg.get(CONTEXT_FUNCTION_IMG_KEY);
+ else {
+ // It is a value. If it is injected somewhere, display the
+ // inject image
+ return hasChildren(element) ? imgReg.get(INJECT_IMG_KEY) : imgReg.get(VALUE_IN_CONTEXT_IMG_KEY);
+ }
+
+ }
+
+ return imgReg.get(INJECT_IMG_KEY);
+
+ }
+
+ @Override
+ public String getToolTipText(Object element) {
+ if (element == LOCAL_VALUE_NODE) {
+ return "This part contains values set in this context and then injected here or in children\n\n"
+ + "If the value is injected using this context, you can expand the node to see where\n\n"
+ + "If the value is injected using a child context you can find it in the second part for this child ";
+ } else if (element == INHERITED_INJECTED_VALUE_NODE) {
+ return "This part contains the values injected or updated using this context, but initialized in a parent context\n\n"
+ + "Expand nodes to see where values are injected or updated";
+ } else if (isAContextKeyFunction(element)) {
+ String key = (String) ((Map.Entry<?, ?>) element).getKey();
+ String fname = selectedContext.localContextFunction().get(key).getClass().getCanonicalName();
+
+ return "This value is created by the Context Function : " + fname;
+ } else {
+ if (hasChildren(element))
+ return "Expand this node to see where this value is injected or updated";
+ else {
+ if (element instanceof Map.Entry)
+ return "This value is set here but not injected using this context (look in children context)";
+ }
+
+ }
+
+ return super.getToolTipText(element);
+ }
+
+ @Override
+ public Image getToolTipImage(Object object) {
+ return getImage(object);
+ }
+
+ @Override
+ public int getToolTipStyle(Object object) {
+ return SWT.SHADOW_OUT;
+ }
+
+ /**
+ * Compute it the current entry in context is a context function
+ *
+ * @param element
+ * @return true if element is a context function
+ */
+ @SuppressWarnings("unchecked")
+ boolean isAContextKeyFunction(Object element) {
+ if (selectedContext != null && element instanceof Map.Entry) {
+ // Just check if key in element is a key in the map of context
+ // functions.
+ Map.Entry<String, Object> mapEntry = (Map.Entry<String, Object>) element;
+ return (selectedContext.localContextFunction().containsKey(mapEntry.getKey()));
+ }
+ return false;
+
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ if (element == LOCAL_VALUE_NODE || element == INHERITED_INJECTED_VALUE_NODE)
+ return null;
+
+ // Not computed
+ return null;
+
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ if ((element == INHERITED_INJECTED_VALUE_NODE) || (element == LOCAL_VALUE_NODE)) {
+ return true; // Intermediate nodes returns true
+ }
+
+ Set<Computation> listeners = getListeners(element);
+ return (listeners != null) && (listeners.size() > 0);
+ }
+
+ @SuppressWarnings("unchecked")
+ Set<Computation> getListeners(Object element) {
+ if (selectedContext != null) {
+ if (element instanceof Map.Entry) {
+ // Ask the context to know if there are listeners for this value
+ Map.Entry<String, Object> mapEntry = (Map.Entry<String, Object>) element;
+ String key = mapEntry.getKey();
+ return selectedContext.getListeners(key);
+
+ } else if (element instanceof String) {
+ // Ask the context to know if there are listeners for this raw
+ // listener name
+ return selectedContext.getListeners((String) element);
+ }
+ }
+ return null;
+
+ }
+
+ private void initializeImageRegistry() {
+ Bundle b = FrameworkUtil.getBundle(this.getClass());
+ imgReg = new ImageRegistry();
+
+ imgReg.put(CONTEXT_FUNCTION_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(CONTEXT_FUNCTION_IMG_KEY)));
+ imgReg.put(INJECT_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(INJECT_IMG_KEY)));
+ imgReg.put(PUBLIC_METHOD_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(PUBLIC_METHOD_IMG_KEY)));
+ imgReg.put(PUBLIC_FIELD_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(PUBLIC_FIELD_IMG_KEY)));
+ imgReg.put(PUBLIC_FIELD_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(PUBLIC_FIELD_IMG_KEY)));
+ imgReg.put(LOCAL_VARIABLE_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(LOCAL_VARIABLE_IMG_KEY)));
+ imgReg.put(VALUE_IN_CONTEXT_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(VALUE_IN_CONTEXT_IMG_KEY)));
+ imgReg.put(INHERITED_VARIABLE_IMG_KEY, ImageDescriptor.createFromURL(b.getEntry(INHERITED_VARIABLE_IMG_KEY)));
+
+ }
+
+ private void initFonts() {
+ FontData[] fontData = Display.getCurrent().getSystemFont().getFontData();
+ String fontName = fontData[0].getName();
+ FontRegistry registry = JFaceResources.getFontRegistry();
+ boldFont = registry.getBold(fontName);
+ }
+
+}
diff --git a/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyHelper.java b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyHelper.java
new file mode 100644
index 0000000000..32b4aed72d
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyHelper.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2013 OPCoach.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * OPCoach - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.spy.context;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.eclipse.e4.core.contexts.EclipseContextFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.osgi.framework.BundleContext;
+
+/**
+ * A helper class to get information inside context management system. This
+ * class uses internal fields or methods defined in EclipseContext Could be
+ * updated in the future.
+ *
+ * @author olivier
+ *
+ */
+public class ContextSpyHelper {
+
+ /**
+ * Get all the contexts created by EclipseContextFactory. It get values from
+ * field introspection. Should be rewritten if internal structure changes
+ *
+ * @return a collection of contexts created by EclipseContextFactory
+ */
+ public static Collection<IEclipseContext> getAllBundleContexts() {
+ Collection<IEclipseContext> result = Collections.emptyList();
+ try {
+ // Must use introspection to get the weak hash map (no getter).
+ Field f = EclipseContextFactory.class.getDeclaredField("serviceContexts");
+ f.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ Map<BundleContext, IEclipseContext> ctxs = (Map<BundleContext, IEclipseContext>) f.get(null);
+ result = ctxs.values();
+
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ return result;
+
+ }
+
+}
diff --git a/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyProvider.java b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyProvider.java
new file mode 100644
index 0000000000..7440bdec68
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/internal/spy/context/ContextSpyProvider.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2013 OPCoach.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * OPCoach - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.spy.context;
+
+import java.util.Collection;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.internal.contexts.EclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+
+@SuppressWarnings("restriction")
+/**
+ * This label and treecontent provider is used by ContextSpyPart to display
+ * available contexts.
+ *
+ * @author olivier
+ *
+ */
+public class ContextSpyProvider extends LabelProvider implements ITreeContentProvider, IColorProvider {
+
+ @Inject
+ private ContextDataFilter contextFilter;
+
+ @Inject
+ public ContextSpyProvider() {
+
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof MApplication) {
+ return new Object[] { ((MApplication) inputElement).getContext().getParent() };
+ } else if (inputElement instanceof Collection<?>) {
+ return ((Collection<?>) inputElement).toArray();
+ }
+
+ return new Object[0];
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof EclipseContext) {
+ return ((EclipseContext) parentElement).getChildren().toArray();
+ }
+ return null;
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ if (element instanceof EclipseContext) {
+ return ((EclipseContext) element).getParent();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ return ((element instanceof EclipseContext) && !(((EclipseContext) element).getChildren().isEmpty()));
+ }
+
+ @Override
+ public String getText(Object element) {
+ return super.getText(element);
+ }
+
+ @Override
+ public Color getForeground(Object element) {
+ // Return a color if a text contained in this node contains the text.
+ if (element instanceof IEclipseContext && contextFilter.containsText((IEclipseContext) element)) {
+ return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
+ }
+ return null;
+ }
+
+ @Override
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+}
diff --git a/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/spy/context/ContextSpyPart.java b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/spy/context/ContextSpyPart.java
new file mode 100644
index 0000000000..e07666ec1f
--- /dev/null
+++ b/ui/org.eclipse.pde.spy.context/src/org/eclipse/pde/spy/context/ContextSpyPart.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2013 OPCoach.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Olivier Prouvost <olivier.prouvost@opcoach.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.spy.context;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.pde.internal.spy.context.ContextDataFilter;
+import org.eclipse.pde.internal.spy.context.ContextDataPart;
+import org.eclipse.pde.internal.spy.context.ContextSpyHelper;
+import org.eclipse.pde.internal.spy.context.ContextSpyProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * This class is the main part of the context spy. It creates a treeviewer and
+ * the context data part listening to context selection
+ */
+public class ContextSpyPart {
+
+ private static final String ICON_COLLAPSEALL = "icons/collapseall.png";
+ private static final String ICON_EXPANDALL = "icons/expandall.png";
+ private static final String ICON_REFRESH = "icons/refresh.png";
+
+ // The ID for this part descriptor
+ static final String CONTEXT_SPY_VIEW_DESC = "org.eclipse.e4.tools.context.spy.view";
+
+ private TreeViewer contextTreeViewer;
+
+ @Inject
+ private ESelectionService selService;
+
+ private ContextSpyProvider treeContentProvider;
+
+ private ImageRegistry imgReg;
+
+ @Inject
+ private ContextDataFilter contextFilter;
+
+ private ContextDataPart contextDataPart;
+ private Button showOnlyFilteredElements;
+ private Text filterText;
+
+ /** Store the values to set it when it is reopened */
+ private static String lastFilterText = null;
+ private static boolean lastShowFiltered = false;
+
+ @Inject
+ private void initializeImageRegistry() {
+ Bundle b = FrameworkUtil.getBundle(this.getClass());
+ imgReg = new ImageRegistry();
+ imgReg.put(ICON_COLLAPSEALL, ImageDescriptor.createFromURL(b.getEntry(ICON_COLLAPSEALL)));
+ imgReg.put(ICON_EXPANDALL, ImageDescriptor.createFromURL(b.getEntry(ICON_EXPANDALL)));
+ imgReg.put(ICON_REFRESH, ImageDescriptor.createFromURL(b.getEntry(ICON_REFRESH)));
+ }
+
+ /**
+ * Create contents of the view part.
+ */
+ @PostConstruct
+ public void createControls(Composite parent, MApplication a, IEclipseContext ctx) {
+ parent.setLayout(new GridLayout(1, false));
+
+ final Composite comp = new Composite(parent, SWT.NONE);
+ comp.setLayout(new GridLayout(7, false));
+
+ Button refreshButton = new Button(comp, SWT.FLAT);
+ refreshButton.setImage(imgReg.get(ICON_REFRESH));
+ refreshButton.setToolTipText("Refresh the contexts");
+ refreshButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ contextTreeViewer.refresh(true);
+ contextDataPart.refresh(true);
+ }
+ });
+
+ Button expandAll = new Button(comp, SWT.FLAT);
+ expandAll.setImage(imgReg.get(ICON_EXPANDALL));
+ expandAll.setToolTipText("Expand context nodes");
+ expandAll.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ contextTreeViewer.expandAll();
+ }
+ });
+ Button collapseAll = new Button(comp, SWT.FLAT);
+ collapseAll.setImage(imgReg.get(ICON_COLLAPSEALL));
+ collapseAll.setToolTipText("Collapse context nodes");
+ collapseAll.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ contextTreeViewer.collapseAll();
+ }
+
+ });
+
+ filterText = new Text(comp, SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
+ GridDataFactory.fillDefaults().hint(200, SWT.DEFAULT).applyTo(filterText);
+ filterText.setMessage("Search data");
+ filterText.setToolTipText("Highlight the contexts where the contained objects contains this string pattern.\n"
+ + "Case is ignored.");
+ if (lastFilterText != null)
+ filterText.setText(lastFilterText);
+ contextFilter.setPattern(lastFilterText);
+ filterText.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyReleased(KeyEvent e) {
+ String textToSearch = filterText.getText();
+ lastFilterText = textToSearch;
+ boolean enableButton = textToSearch.length() > 0;
+ // Enable/disable button for filtering
+ showOnlyFilteredElements.setEnabled(enableButton);
+
+ // Then update filters and viewers
+ contextFilter.setPattern(textToSearch);
+ setFilter();
+ contextTreeViewer.refresh(true);
+ contextDataPart.refresh(true);
+ }
+
+ });
+
+ showOnlyFilteredElements = new Button(comp, SWT.CHECK);
+ showOnlyFilteredElements.setText("Show Only Filtered");
+ showOnlyFilteredElements.setToolTipText("Show only the filtered items in the table view");
+ showOnlyFilteredElements.setEnabled((lastFilterText != null) && (lastFilterText.length() > 0));
+ showOnlyFilteredElements.setSelection(lastShowFiltered);
+ showOnlyFilteredElements.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ lastShowFiltered = showOnlyFilteredElements.getSelection();
+ setFilter();
+ }
+ });
+
+ SashForm sashForm = new SashForm(parent, SWT.VERTICAL | SWT.V_SCROLL | SWT.H_SCROLL);
+ sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ // TreeViewer on the top
+ contextTreeViewer = new TreeViewer(sashForm);
+ treeContentProvider = ContextInjectionFactory.make(ContextSpyProvider.class, ctx);
+ contextTreeViewer.setContentProvider(treeContentProvider);
+ contextTreeViewer.setLabelProvider(treeContentProvider);
+ contextTreeViewer.setComparator(new ViewerComparator());
+
+ // tv.setInput(a);
+ contextTreeViewer.setInput(ContextSpyHelper.getAllBundleContexts());
+
+ contextTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection ss = (IStructuredSelection) event.getSelection();
+ selService.setSelection((ss.size() == 1) ? ss.getFirstElement() : ss.toArray());
+ }
+ });
+
+ IEclipseContext subCtx = ctx.createChild("Context for ContextDataPart");
+ subCtx.set(Composite.class, sashForm);
+ contextDataPart = ContextInjectionFactory.make(ContextDataPart.class, subCtx);
+ setFilter();
+
+ // Set the correct weight for SashForm
+ sashForm.setWeights(new int[] { 35, 65 });
+
+ // Open all the tree
+ contextTreeViewer.expandAll();
+
+ }
+
+ /** Set the filter on context data part */
+ public void setFilter() {
+ if (showOnlyFilteredElements.isEnabled() && showOnlyFilteredElements.getSelection())
+ contextDataPart.setFilter(contextFilter);
+ else
+ contextDataPart.setFilter(null);
+ }
+
+ @PreDestroy
+ public void dispose() {
+ }
+
+ @Focus
+ public void setFocus() {
+ contextTreeViewer.getControl().setFocus();
+ }
+
+}

Back to the top