Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Rolka2013-08-14 09:24:48 -0400
committerGerrit Code Review @ Eclipse.org2013-08-14 11:05:59 -0400
commit0b5f24fa4c7134bf901e387289303c75678784ca (patch)
treec2b217fc35cdd919df8a7c4e2f898faf81341788
parentdcf95dc4cde7496c927bb5842d9e76065c573fe5 (diff)
downloadorg.eclipse.e4.tools-0b5f24fa4c7134bf901e387289303c75678784ca.tar.gz
org.eclipse.e4.tools-0b5f24fa4c7134bf901e387289303c75678784ca.tar.xz
org.eclipse.e4.tools-0b5f24fa4c7134bf901e387289303c75678784ca.zip
Bug 414853 - [tools] Create tool for monitoring e4 events
Signed-off-by: Daniel Rolka <daniel.rolka@pl.ibm.com>
-rw-r--r--build/org.eclipse.e4.core.tools.update/category.xml9
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/.classpath7
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/.project28
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/META-INF/MANIFEST.MF26
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/build.properties5
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/plugin.xml14
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/pom.xml16
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/BindingDescriptor.java32
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/CommandDescriptor.java32
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Constants.java22
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Installer.java137
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/CapturedEventFilterMatcher.java124
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/EventMonitor.java125
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/handlers/OpenSpyDialogHandler.java23
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEvent.java70
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventFilter.java56
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventTreeSelection.java30
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/ItemToFilter.java43
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Operator.java49
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Parameter.java29
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/SpecialValue.java28
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventFilters.java265
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventTree.java155
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/SpyDialog.java238
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/ToggleLink.java69
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/LoggerWrapper.java111
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PDEUtils.java87
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/ParameterFormatter.java20
-rw-r--r--bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PluginUtils.java33
-rw-r--r--features/org.eclipse.e4.tools.event.spy.feature/.project17
-rw-r--r--features/org.eclipse.e4.tools.event.spy.feature/build.properties2
-rw-r--r--features/org.eclipse.e4.tools.event.spy.feature/feature.properties147
-rw-r--r--features/org.eclipse.e4.tools.event.spy.feature/feature.xml27
-rw-r--r--features/org.eclipse.e4.tools.event.spy.feature/forceQualifierUpdate.txt2
-rw-r--r--features/org.eclipse.e4.tools.event.spy.feature/license.html79
-rw-r--r--features/org.eclipse.e4.tools.event.spy.feature/pom.xml48
-rw-r--r--pom.xml2
38 files changed, 2213 insertions, 1 deletions
diff --git a/build/org.eclipse.e4.core.tools.update/category.xml b/build/org.eclipse.e4.core.tools.update/category.xml
index 59f94280..e98a904c 100644
--- a/build/org.eclipse.e4.core.tools.update/category.xml
+++ b/build/org.eclipse.e4.core.tools.update/category.xml
@@ -21,12 +21,19 @@
<feature url="features/org.eclipse.e4.tools.e3x.bridge.feature_0.14.0.qualifier.jar" id="org.eclipse.e4.tools.e3x.bridge.feature" version="0.14.0.qualifier">
<category name="org.eclipse.e4.tools.e3x.bridge"/>
</feature>
- <feature url="features/org.eclipse.e4.tools.e3x.bridge.feature.source_0.14.0.qualifier.jar" id="org.eclipse.e4.tools.e3x.bridge.feature.source" version="0.14.0.qualifier">
+ <feature url="features/org.eclipse.e4.tools.e3x.bridge.feature.source_0.14.0.qualifier.jar" id="org.eclipse.e4.tools.e3x.bridge.feature.source" version="0.14.0.qualifier">
<category name="org.eclipse.e4.tools.e3x.bridge"/>
</feature>
+ <feature url="features/org.eclipse.e4.tools.event.spy.feature_0.15.0.qualifier.jar" id="org.eclipse.e4.tools.event.spy.feature" version="0.15.0.qualifier">
+ <category name="org.eclipse.e4.tools.event.spy"/>
+ </feature>
+ <feature url="features/org.eclipse.e4.tools.event.spy.feature.source_0.15.0.qualifier.jar" id="org.eclipse.e4.tools.event.spy.feature.source" version="0.15.0.qualifier">
+ <category name="org.eclipse.e4.tools.event.spy"/>
+ </feature>
<category-def name="org.eclipse.e4.tools.core" label="Eclipse 4 core tools"/>
<category-def name="org.eclipse.e4.tools.css.spy" label="CSS spy for Eclipse 4"/>
<category-def name="org.eclipse.e4.tools.e3x.bridge" label="Eclipse 3.x bridge"/>
<category-def name="org.eclipse.e4.tools.css.editor" label="CSS file editor"/>
+ <category-def name="org.eclipse.e4.tools.event.spy" label="Eclipse 4 event spy"/>
</site>
diff --git a/bundles/org.eclipse.e4.tools.event.spy/.classpath b/bundles/org.eclipse.e4.tools.event.spy/.classpath
new file mode 100644
index 00000000..64c5e31b
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/.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/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.e4.tools.event.spy/.project b/bundles/org.eclipse.e4.tools.event.spy/.project
new file mode 100644
index 00000000..d26d07f7
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.e4.tools.event.spy</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/bundles/org.eclipse.e4.tools.event.spy/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.e4.tools.event.spy/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..af0f20f9
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/bundles/org.eclipse.e4.tools.event.spy/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.tools.event.spy/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..8b49e598
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/META-INF/MANIFEST.MF
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.e4.tools.event.spy;singleton:=true
+Bundle-Version: 0.15.0.qualifier
+Bundle-Vendor: %Bundle-Vendor
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.e4.core.di;bundle-version="1.3.0",
+ org.eclipse.e4.ui.workbench,
+ org.eclipse.e4.core.contexts;bundle-version="1.3.0",
+ org.eclipse.e4.ui.model.workbench;bundle-version="1.0.0",
+ org.eclipse.e4.core.services;bundle-version="1.1.0",
+ javax.inject;bundle-version="1.0.0",
+ org.eclipse.e4.ui.bindings;bundle-version="0.10.100",
+ org.eclipse.core.resources;bundle-version="3.8.100",
+ org.eclipse.jdt.core;bundle-version="3.9.0",
+ org.eclipse.jdt.ui;bundle-version="3.9.0",
+ org.eclipse.pde.core;bundle-version="3.9.0",
+ org.eclipse.pde.ui;bundle-version="3.8.0",
+ org.eclipse.pde.runtime;bundle-version="3.4.400",
+ org.eclipse.osgi.services;bundle-version="3.3.100",
+ org.eclipse.e4.ui.services;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Bundle-ActivationPolicy: lazy
+Import-Package: javax.annotation;version="1.1.0"
diff --git a/bundles/org.eclipse.e4.tools.event.spy/build.properties b/bundles/org.eclipse.e4.tools.event.spy/build.properties
new file mode 100644
index 00000000..e9863e28
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/bundles/org.eclipse.e4.tools.event.spy/plugin.xml b/bundles/org.eclipse.e4.tools.event.spy/plugin.xml
new file mode 100644
index 00000000..e9395f19
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/plugin.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ id="org.eclipse.e4.tools.event.spy"
+ name="E4 Event spy"
+ point="org.eclipse.e4.workbench.model">
+ <processor
+ beforefragment="false"
+ class="org.eclipse.e4.tools.event.spy.Installer">
+ </processor>
+ </extension>
+
+</plugin>
diff --git a/bundles/org.eclipse.e4.tools.event.spy/pom.xml b/bundles/org.eclipse.e4.tools.event.spy/pom.xml
new file mode 100644
index 00000000..84fb6caf
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/pom.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <groupId>org.eclipse.e4.tools</groupId>
+ <artifactId>e4-tools-aggregator</artifactId>
+ <version>0.15.0-SNAPSHOT</version>
+ <relativePath>../../</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.e4</groupId>
+ <artifactId>org.eclipse.e4.tools.event.spy</artifactId>
+ <version>0.15.0.qualifier</version>
+ <packaging>eclipse-plugin</packaging>
+
+</project>
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/BindingDescriptor.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/BindingDescriptor.java
new file mode 100644
index 00000000..a24513c1
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/BindingDescriptor.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy;
+
+public enum BindingDescriptor {
+ OpenSpyDialogInDialogAndWindow("M2+M3+F8", "org.eclipse.ui.contexts.dialogAndWindow");
+
+ private String bindingContextId;
+
+ private String keySequence;
+
+ private BindingDescriptor(String keySequence, String bindingContextId) {
+ this.keySequence = keySequence;
+ this.bindingContextId = bindingContextId;
+ }
+
+ public String getBindingContextId() {
+ return bindingContextId;
+ }
+
+ public String getKeySequence() {
+ return keySequence;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/CommandDescriptor.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/CommandDescriptor.java
new file mode 100644
index 00000000..866ddf47
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/CommandDescriptor.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy;
+
+public enum CommandDescriptor {
+ OpenSpyDialog("org.eclipse.e4.tools.event.spy.openSpyDialog.cmd", "Open event spy dialog");
+
+ private String id;
+
+ private String name;
+
+ private CommandDescriptor(String id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Constants.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Constants.java
new file mode 100644
index 00000000..61c8a3e2
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Constants.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy;
+
+import org.eclipse.e4.tools.event.spy.util.PluginUtils;
+import org.eclipse.e4.ui.bindings.EBindingService;
+
+public class Constants {
+ public static final String PLUGIN_ID = PluginUtils.getBundleId(Constants.class);
+
+ public static final String BINDING_MODIFIED_BY_USER_TAG = EBindingService.TYPE_ATTR_TAG + ":user";
+
+ public static final String BINDING_DELETED_BY_USER_TAG = EBindingService.DELETED_BINDING_TAG;
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Installer.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Installer.java
new file mode 100644
index 00000000..d175ba4b
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/Installer.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy;
+
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.tools.event.spy.handlers.OpenSpyDialogHandler;
+import org.eclipse.e4.tools.event.spy.util.LoggerWrapper;
+import org.eclipse.e4.tools.event.spy.util.PluginUtils;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.commands.MBindingTable;
+import org.eclipse.e4.ui.model.application.commands.MCommand;
+import org.eclipse.e4.ui.model.application.commands.MCommandsFactory;
+import org.eclipse.e4.ui.model.application.commands.MHandler;
+import org.eclipse.e4.ui.model.application.commands.MKeyBinding;
+
+@SuppressWarnings("restriction")
+public class Installer {
+ @Inject
+ private MApplication application;
+
+ @Inject
+ private LoggerWrapper logger;
+
+ @Execute
+ public void execute() {
+ logger.info("installing ...");
+
+ registerCommand(CommandDescriptor.OpenSpyDialog, BindingDescriptor.OpenSpyDialogInDialogAndWindow, OpenSpyDialogHandler.class);
+
+ logger.info("installed");
+ }
+
+ private void registerCommand(CommandDescriptor commandDesc, BindingDescriptor bindingDesc, Class<?> handlerCls) {
+ MCommand command = getCommand(application, commandDesc);
+ if (command == null) {
+ command = createCommand(commandDesc);
+ application.getCommands().add(command);
+ }
+
+ Object binding = getBindingOrBindingTable(application, command, bindingDesc);
+ if (binding == null) {
+ logger.warn("binding context ''{0}'' for command ''{1}'' not found",
+ bindingDesc.getBindingContextId(), commandDesc.getName());
+ return;
+ }
+
+ if (binding instanceof MKeyBinding) {
+ MKeyBinding keyBinding = (MKeyBinding) binding;
+ if (keyBinding.getTags().contains(Constants.BINDING_MODIFIED_BY_USER_TAG)) {
+ logger.info("key binding for command ''{0}'' changed to {1}", commandDesc.getName(), keyBinding.getKeySequence());
+
+ } else if (keyBinding.getTags().contains(Constants.BINDING_DELETED_BY_USER_TAG)) {
+ logger.info("key binding for command ''{0}'' has been deleted. The command is disabled", commandDesc.getName());
+ }
+ return; //command already processed
+ }
+
+ ((MBindingTable) binding).getBindings().add(createKeyBinding(command, bindingDesc));
+ logger.info("key binding for command ''{0}'' is {1}", commandDesc.getName(), bindingDesc.getKeySequence());
+
+ MHandler handler = getHandler(application, commandDesc);
+ if (handler == null) {
+ handler = createHandler(command, handlerCls);
+ application.getHandlers().add(handler);
+ }
+ }
+
+ private MCommand getCommand(MApplication application, CommandDescriptor descriptor) {
+ for (MCommand command: application.getCommands()) {
+ if (descriptor.getId().equals(command.getElementId())) {
+ return command;
+ }
+ }
+ return null;
+ }
+
+ private MCommand createCommand(CommandDescriptor descriptor) {
+ MCommand command = MCommandsFactory.INSTANCE.createCommand();
+ command.setElementId(descriptor.getId());
+ command.setCommandName(descriptor.getName());
+ command.setContributorURI(PluginUtils.getContributorURI());
+ return command;
+ }
+
+ private MHandler getHandler(MApplication application, CommandDescriptor descriptor) {
+ for (MHandler handler: application.getHandlers()) {
+ if (descriptor.getId().equals(handler.getElementId())) {
+ return handler;
+ }
+ }
+ return null;
+ }
+
+ private MHandler createHandler(MCommand command, Class<?> handlerCls) {
+ MHandler handler = MCommandsFactory.INSTANCE.createHandler();
+ handler.setElementId(command.getElementId());
+ handler.setCommand(command);
+ handler.setContributionURI(PluginUtils.getContributionURI(handlerCls));
+ handler.setContributorURI(PluginUtils.getContributorURI());
+ return handler;
+ }
+
+ private Object getBindingOrBindingTable(MApplication application, MCommand command, BindingDescriptor descriptor) {
+ MBindingTable result = null;
+ for (MBindingTable bindingTable: application.getBindingTables()) {
+ for (MKeyBinding keyBinding : bindingTable.getBindings()) {
+ if (keyBinding.getCommand() == command) {
+ return bindingTable;
+ }
+ }
+ if (descriptor.getBindingContextId().equals(bindingTable.getBindingContext().getElementId())) {
+ result = bindingTable;
+ }
+ }
+ return result;
+ }
+
+ private MKeyBinding createKeyBinding(MCommand command, BindingDescriptor descriptor) {
+ MKeyBinding keyBinding = MCommandsFactory.INSTANCE.createKeyBinding();
+ keyBinding.setElementId(command.getElementId());
+ keyBinding.setCommand(command);
+ keyBinding.setKeySequence(descriptor.getKeySequence());
+ keyBinding.setContributorURI(PluginUtils.getContributorURI());
+ return keyBinding;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/CapturedEventFilterMatcher.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/CapturedEventFilterMatcher.java
new file mode 100644
index 00000000..a360cd33
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/CapturedEventFilterMatcher.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.e4.tools.event.spy.model.CapturedEvent;
+import org.eclipse.e4.tools.event.spy.model.CapturedEventFilter;
+import org.eclipse.e4.tools.event.spy.model.ItemToFilter;
+import org.eclipse.e4.tools.event.spy.model.Operator;
+import org.eclipse.e4.tools.event.spy.model.Parameter;
+import org.eclipse.e4.tools.event.spy.model.SpecialValue;
+
+public class CapturedEventFilterMatcher {
+ public boolean matches(CapturedEvent event, CapturedEventFilter filter) {
+ Object value = getItemToFilterValue(event, filter.getItemToFilter());
+
+ if (value instanceof List) {
+ List<?> list = (List<?>) value;
+ for (Object item: list) {
+ if (matches(filter.getValue(), item, filter.getOperator())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return matches(filter.getValue(), value, filter.getOperator());
+ }
+
+ private Object getItemToFilterValue(CapturedEvent event, ItemToFilter itemToFilter) {
+ if (itemToFilter.equals(ItemToFilter.Topic)) {
+ return event.getTopic();
+ }
+ if (itemToFilter.equals(ItemToFilter.Publisher)) {
+ return event.getPublisherClassName();
+ }
+ if (itemToFilter.equals(ItemToFilter.ChangedElement)) {
+ return event.getChangedElementClassName();
+ }
+ if (itemToFilter.equals(ItemToFilter.ParameterName)) {
+ List<String> names = new ArrayList<String>();
+ for (Parameter parameter: event.getParameters()) {
+ names.add(parameter.getName());
+ }
+ return names;
+ }
+ if (itemToFilter.equals(ItemToFilter.ParameterValue)) {
+ List<Object> values = new ArrayList<Object>();
+ for (Parameter parameter: event.getParameters()) {
+ values.add(parameter.getValue());
+ }
+ return values;
+ }
+ if (itemToFilter.equals(ItemToFilter.ParameterNameAndValue)) {
+ List<String> nameAndValues = new ArrayList<String>();
+ for (Parameter parameter: event.getParameters()) {
+ String nameAndValue = String.format(SpecialValue.NameAndValue.toString(), parameter.getName().trim(),
+ (parameter.getValue() == null? SpecialValue.Null: parameter.getValue().toString().trim()));
+ nameAndValues.add(nameAndValue);
+ }
+ return nameAndValues;
+ }
+
+ throw new IllegalArgumentException("Not supported item to filter found: " + itemToFilter.toString());
+ }
+
+ private boolean matches(String expected, Object current, Operator operator) {
+ if (SpecialValue.Null.toString().equalsIgnoreCase(expected)) {
+ return operator.isPositive()? matchesToNull(current): !matchesToNull(current);
+ }
+ if ( SpecialValue.EmptyString.toString().equalsIgnoreCase(expected)) {
+ return operator.isPositive()? matchesToEmptyString(current): !matchesToEmptyString(current);
+ }
+ if (Operator.Equals.equals(operator)) {
+ return equalsTo(expected, current);
+ }
+ if (Operator.NotEquals.equals(operator)) {
+ return !equalsTo(expected, current);
+ }
+ if (Operator.Contains.equals(operator)) {
+ return contains(expected, current);
+ }
+ if (Operator.NotContains.equals(operator)) {
+ return !contains(expected, current);
+ }
+ if (Operator.StartsWith.equals(operator)) {
+ return startsWith(expected, current);
+ }
+ if (Operator.NotStartsWith.equals(operator)) {
+ return !startsWith(expected, current);
+ }
+
+ throw new IllegalArgumentException("Not supported operator found: " + operator);
+ }
+
+ private boolean matchesToEmptyString(Object current) {
+ return current != null && current instanceof String && current.toString().isEmpty();
+ }
+
+ private boolean matchesToNull(Object current) {
+ return current == null || current.toString().equalsIgnoreCase(SpecialValue.Null.toString());
+ }
+
+ private boolean equalsTo(String expected, Object current) {
+ return current != null && expected.equalsIgnoreCase(current.toString());
+ }
+
+ private boolean contains(String expected, Object current) {
+ return current != null && current.toString().toLowerCase().contains(expected.toLowerCase());
+ }
+
+ private boolean startsWith(String expected, Object current) {
+ return current != null && current.toString().toLowerCase().startsWith(expected.toLowerCase());
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/EventMonitor.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/EventMonitor.java
new file mode 100644
index 00000000..6d0f900a
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/core/EventMonitor.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.core;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.tools.event.spy.model.CapturedEvent;
+import org.eclipse.e4.tools.event.spy.model.CapturedEventFilter;
+import org.eclipse.e4.ui.internal.workbench.UIEventPublisher;
+import org.eclipse.e4.ui.services.internal.events.EventBroker;
+import org.eclipse.e4.ui.workbench.UIEvents;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+public class EventMonitor {
+
+ public interface NewEventListener {
+ void newEvent(CapturedEvent event);
+ }
+
+ private final static String TOPIC = UIEvents.UITopicBase + UIEvents.TOPIC_SEP + UIEvents.ALL_SUB_TOPICS;
+
+ @SuppressWarnings({"serial", "restriction"})
+ private static Set<Integer> EVENT_HELPER_CLASSES = new HashSet<Integer>() {{
+ add(UIEvents.class.getName().hashCode());
+ add(UIEventPublisher.class.getName().hashCode());
+ }};
+
+ private Collection<CapturedEventFilter> filters;
+
+ private IEventBroker eventBroker;
+
+ private NewEventListener listener;
+
+ private CapturedEventFilterMatcher eventFilterMatcher;
+
+ private EventHandler eventHandler = new EventHandler() {
+ public void handleEvent(Event event) {
+ if (listener == null) {
+ return;
+ }
+
+ CapturedEvent capturedEvent = new CapturedEvent();
+ capturedEvent.setTopic(event.getTopic());
+ capturedEvent.setPublisherClassName(getPublisherClassName());
+
+ for (String propertyName: event.getPropertyNames()) {
+ Object value = event.getProperty(propertyName);
+ capturedEvent.addParameter(propertyName, value);
+ if (value != null && UIEvents.EventTags.ELEMENT.equals(propertyName)) {
+ capturedEvent.setChangedElementClassName(value.getClass().getName());
+ }
+ }
+
+ if (shouldBeCaptured(capturedEvent)) {
+ listener.newEvent(capturedEvent);
+ }
+ }
+ };
+
+ public EventMonitor(IEventBroker eventBroker) {
+ this.eventBroker = eventBroker;
+ }
+
+ public void start(Collection<CapturedEventFilter> filters) {
+ this.filters = filters;
+ eventBroker.subscribe(TOPIC, eventHandler);
+ }
+
+ public void stop() {
+ eventBroker.unsubscribe(eventHandler);
+ }
+
+ public void setNewEventListener(NewEventListener listener) {
+ this.listener = listener;
+ }
+
+ private boolean shouldBeCaptured(CapturedEvent event) {
+ if (filters != null) {
+ Iterator<CapturedEventFilter> iter = filters.iterator();
+ while (iter.hasNext()) {
+ if (!getEventFilterMatcher().matches(event, iter.next())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private String getPublisherClassName() {
+ StackTraceElement items[] = Thread.currentThread().getStackTrace();
+ boolean foundEventBroker = false;
+
+ for (int i=0; i<items.length; i++) {
+ String clsName = items[i].getClassName();
+ if (!foundEventBroker && clsName.equals(EventBroker.class.getName())) {
+ foundEventBroker = true;
+ } else if (foundEventBroker) {
+ if (!EVENT_HELPER_CLASSES.contains(clsName.hashCode())) {
+ return String.format("%s (%s:%d)", clsName, items[i].getMethodName(), items[i].getLineNumber());
+ }
+ }
+ }
+ return "";
+ }
+
+ private CapturedEventFilterMatcher getEventFilterMatcher() {
+ if (eventFilterMatcher == null) {
+ eventFilterMatcher = new CapturedEventFilterMatcher();
+ }
+ return eventFilterMatcher;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/handlers/OpenSpyDialogHandler.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/handlers/OpenSpyDialogHandler.java
new file mode 100644
index 00000000..2d059763
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/handlers/OpenSpyDialogHandler.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.handlers;
+
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.tools.event.spy.ui.SpyDialog;
+
+public class OpenSpyDialogHandler {
+ @Execute
+ public void execute(IEclipseContext context) {
+ ContextInjectionFactory.make(SpyDialog.class, context).open();
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEvent.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEvent.java
new file mode 100644
index 00000000..060b8f57
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEvent.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CapturedEvent {
+ private String topic;
+
+ private String publisherClassName = "";
+
+ private String changedElementClassName = "";
+
+ private List<Parameter> parameters;
+
+ public void setTopic(String topic) {
+ this.topic = topic;
+ }
+
+ public String getTopic() {
+ return topic;
+ }
+
+ public void setPublisherClassName(String publisherClassName) {
+ this.publisherClassName = publisherClassName;
+ }
+
+ public String getPublisherClassName() {
+ return publisherClassName;
+ }
+
+ public void setChangedElementClassName(String changedElementClassName) {
+ this.changedElementClassName = changedElementClassName;
+ }
+
+ public String getChangedElementClassName() {
+ return changedElementClassName;
+ }
+
+ public void addParameter(String name, Object value) {
+ if (parameters == null) {
+ parameters = new ArrayList<Parameter>();
+ }
+ parameters.add(new Parameter(name, value));
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<Parameter> getParameters() {
+ return parameters != null? parameters: Collections.EMPTY_LIST;
+ }
+
+ public boolean hasParameters() {
+ return parameters != null;
+ }
+
+ @Override
+ public String toString() {
+ return topic;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventFilter.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventFilter.java
new file mode 100644
index 00000000..e7706fd5
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventFilter.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.model;
+
+public class CapturedEventFilter {
+ private final static String FILTER_AS_STRING_PATTERN = "Capture event when '%s' %s '%s'";
+
+ private final ItemToFilter itemToFilter;
+
+ private final Operator operator;
+
+ private final String value;
+
+ public CapturedEventFilter(ItemToFilter itemToFilter, Operator operator, String value) {
+ this.itemToFilter = itemToFilter;
+ this.operator = operator;
+ this.value = normalize(itemToFilter, value);
+ }
+
+ public ItemToFilter getItemToFilter() {
+ return itemToFilter;
+ }
+
+ public Operator getOperator() {
+ return operator;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ private String normalize(ItemToFilter itemToFilter, String value) {
+ if (ItemToFilter.ParameterNameAndValue.equals(itemToFilter)) {
+ String[] splitted = value.split("=");
+ if (splitted.length != 2) {
+ throw new IllegalArgumentException("Invalid value format, it should be: " +
+ String.format(SpecialValue.NameAndValue.toString(), "Name", "Value"));
+ }
+ return String.format(SpecialValue.NameAndValue.toString(), splitted[0].trim(), splitted[1].trim());
+ }
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(FILTER_AS_STRING_PATTERN, itemToFilter, operator, value);
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventTreeSelection.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventTreeSelection.java
new file mode 100644
index 00000000..6dddc176
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/CapturedEventTreeSelection.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.model;
+
+public class CapturedEventTreeSelection {
+ private String selection;
+
+ private boolean parameter;
+
+ public CapturedEventTreeSelection(String selection, boolean parameter) {
+ this.selection = selection;
+ this.parameter = parameter;
+ }
+
+ public String getSelection() {
+ return selection;
+ }
+
+ public boolean isParameter() {
+ return parameter;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/ItemToFilter.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/ItemToFilter.java
new file mode 100644
index 00000000..1565bebd
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/ItemToFilter.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.model;
+
+
+public enum ItemToFilter {
+ NotSelected("-- item to filter --"),
+ Topic("Topic"),
+ ParameterName("Parameter name"),
+ ParameterNameAndValue("Parameter name and value"),
+ ParameterValue("Some parameter value"),
+ Publisher("Event publisher"),
+ ChangedElement("Changed element");
+
+ private String text;
+
+ private ItemToFilter(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+
+ public static ItemToFilter toItem(String text) {
+ for (ItemToFilter item: values()) {
+ if (item.text.equals(text)) {
+ return item;
+ }
+ }
+ throw new IllegalArgumentException(String.format("%s not found for: %s",
+ ItemToFilter.class.getSimpleName(), text));
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Operator.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Operator.java
new file mode 100644
index 00000000..135a1898
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Operator.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.model;
+
+public enum Operator {
+ NotSelected("-- operator --", false),
+ Equals("equals to", true),
+ NotEquals("not equals to", false),
+ Contains("contains", true),
+ NotContains("not contains", false),
+ StartsWith("starts with", true),
+ NotStartsWith("not starts with", false);
+
+ private String text;
+
+ private boolean positive;
+
+ private Operator(String text, boolean positive) {
+ this.text = text;
+ this.positive = positive;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+
+ public boolean isPositive() {
+ return positive;
+ }
+
+ public static Operator toOperator(String text) {
+ for (Operator operator: values()) {
+ if (operator.text.equals(text)) {
+ return operator;
+ }
+ }
+ throw new IllegalArgumentException(String.format("%s not found for: %s",
+ Operator.class.getSimpleName(), text));
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Parameter.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Parameter.java
new file mode 100644
index 00000000..2de4d103
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/Parameter.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.model;
+
+public class Parameter {
+ private String name;
+ private Object value;
+
+ public Parameter(String name, Object value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/SpecialValue.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/SpecialValue.java
new file mode 100644
index 00000000..30145559
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/model/SpecialValue.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.model;
+
+public enum SpecialValue {
+ Null("null"),
+ EmptyString("empty"),
+ NameAndValue("%s=%s");
+
+ private String text;
+
+ private SpecialValue(String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventFilters.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventFilters.java
new file mode 100644
index 00000000..5ddd7187
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventFilters.java
@@ -0,0 +1,265 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.ui;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.e4.tools.event.spy.model.CapturedEventFilter;
+import org.eclipse.e4.tools.event.spy.model.ItemToFilter;
+import org.eclipse.e4.tools.event.spy.model.Operator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolTip;
+
+public class CapturedEventFilters {
+ private final static String NOT_SELECTED_VALUE = "-- expected value --";
+
+ private Composite control;
+
+ private Text valueText;
+
+ private Combo itemToFilterCombo;
+
+ private Combo operatorCombo;
+
+ private ToolTip validationErrorToolTip;
+
+ private List filters;
+
+ private Map<Integer, CapturedEventFilter> rawFilters;
+
+
+ /* Layout scheme:
+ *
+ * +-- control --------------------------------------------+
+ * | +-- New filter group -------------------------------+ |
+ * | | | |
+ * | | Capture event when|combo|combo|text|add filter | |
+ * | | | |
+ * | +---------------------------------------------------+ |
+ * | +-- Defined filter group ---------------------------+ |
+ * | | | |
+ * | | List | +-- composite -----------------+ | |
+ * | | | | remove selected | remove all | | |
+ * | | | +------------------------------+ | |
+ * | | | |
+ * | +---------------------------------------------------+ |
+ * +-------------------------------------------------------+
+ *
+ * */
+
+ //TODO: Fix layout data for groups
+ public CapturedEventFilters(Composite outer) {
+ control = new Composite(outer, SWT.NONE);
+ RowLayout layout = new RowLayout(SWT.VERTICAL);
+ layout.marginLeft = 0;
+ layout.fill = true;
+ control.setLayout(layout);
+
+ createNewFilterGroup(control);
+
+ createDefinedFiltersGroup(control);
+ }
+
+ private void createNewFilterGroup(Composite parent) {
+ Group newFilterGroup = new Group(parent, SWT.NONE);
+ newFilterGroup.setText("New filter:");
+ newFilterGroup.setLayout(new RowLayout(SWT.HORIZONTAL));
+
+ Label label = new Label(newFilterGroup, SWT.CENTER);
+ label.setText("Capture event when:");
+
+ itemToFilterCombo = new Combo(newFilterGroup, SWT.READ_ONLY);
+ for (ItemToFilter item: ItemToFilter.values()) {
+ itemToFilterCombo.add(item.toString());
+ }
+ itemToFilterCombo.select(0);
+
+ operatorCombo = new Combo(newFilterGroup, SWT.READ_ONLY);
+ for (Operator operator: Operator.values()) {
+ operatorCombo.add(operator.toString());
+ }
+ operatorCombo.select(0);
+
+ valueText = new Text(newFilterGroup, SWT.BORDER);
+ valueText.setLayoutData(new RowData(130, SWT.DEFAULT));
+ valueText.setText(NOT_SELECTED_VALUE);
+ valueText.addFocusListener(new FocusListener() {
+ public void focusLost(FocusEvent e) {
+ if (valueText.getText().trim().isEmpty()) {
+ valueText.setText(NOT_SELECTED_VALUE);
+ }
+ }
+ public void focusGained(FocusEvent e) {
+ if (NOT_SELECTED_VALUE.equals(valueText.getText())) {
+ valueText.setText("");
+ }
+ }
+ });
+
+ Link link = new Link(newFilterGroup, SWT.NONE);
+ link.setText("<a>Add filter</a>");
+ link.addListener (SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ addNewFilter();
+ }
+ });
+ }
+
+ private void createDefinedFiltersGroup(Composite parent) {
+ Group definedFiltersGroup = new Group(parent, SWT.NONE);
+ definedFiltersGroup.setText("Defined filters (relation between filters is AND):");
+ definedFiltersGroup.setLayout(new RowLayout(SWT.HORIZONTAL));
+
+ filters = new List(definedFiltersGroup, SWT.BORDER);
+ filters.setLayoutData(new RowData(403, 84));
+
+
+ Composite composite = new Composite(definedFiltersGroup, SWT.NONE);
+ composite.setLayout(new RowLayout(SWT.VERTICAL));
+
+ Link link = new Link(composite, SWT.NONE);
+ link.setText("<a>Remove selected</a>");
+ link.addListener (SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ removeFilterAt(filters.getSelectionIndex());
+ }
+ });
+
+ link = new Link(composite, SWT.NONE);
+ link.setText("<a>Remove all</a>");
+ link.addListener (SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ removeAllFilters();
+ }
+ });
+ }
+
+ public Control getControl() {
+ return control;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Collection<CapturedEventFilter> getFilters() {
+ return rawFilters == null || rawFilters.isEmpty()? Collections.EMPTY_LIST: rawFilters.values();
+ }
+
+ public boolean hasFilters() {
+ return rawFilters != null && !rawFilters.isEmpty();
+ }
+
+ public int getFiltersCount() {
+ return rawFilters == null? 0: rawFilters.size();
+ }
+
+ private void addNewFilter() {
+ ItemToFilter selectedItemToFilter =
+ ItemToFilter.toItem(itemToFilterCombo.getItem(itemToFilterCombo.getSelectionIndex()));
+ if (ItemToFilter.NotSelected.equals(selectedItemToFilter)) {
+ getTooltip().setText(String.format("%s is not selected", getFieldName(ItemToFilter.NotSelected)));
+ getTooltip().setVisible(true);
+ return;
+ }
+
+ Operator selectedOperator = Operator.toOperator(operatorCombo.getItem(operatorCombo.getSelectionIndex()));
+ if (Operator.NotSelected.equals(selectedOperator)) {
+ getTooltip().setText(String.format("%s is not selected", getFieldName(Operator.NotSelected)));
+ getTooltip().setVisible(true);
+ return;
+ }
+
+ String value = valueText.getText();
+ if (value.isEmpty() || value.equals(NOT_SELECTED_VALUE)) {
+ getTooltip().setText(String.format("%s is empty", getFieldName(NOT_SELECTED_VALUE)));
+ getTooltip().setVisible(true);
+ return;
+ }
+
+ CapturedEventFilter eventFilter = null;
+ try {
+ eventFilter = new CapturedEventFilter(selectedItemToFilter, selectedOperator, value);
+ } catch(IllegalArgumentException exc) {
+ getTooltip().setText(exc.getMessage());
+ getTooltip().setVisible(true);
+ return;
+ }
+
+ if (rawFilters == null) {
+ rawFilters = new HashMap<Integer, CapturedEventFilter>();
+ }
+
+ String filterAsString = eventFilter.toString();
+ if (rawFilters.containsKey(filterAsString.hashCode())) {
+ getTooltip().setText(String.format("Filter has been already added: %s", filterAsString));
+ getTooltip().setVisible(true);
+ return;
+ }
+
+ filters.add(filterAsString);
+ rawFilters.put(filterAsString.hashCode(), eventFilter);
+
+ itemToFilterCombo.select(0);
+ operatorCombo.select(0);
+ valueText.setText(NOT_SELECTED_VALUE);
+ }
+
+ private ToolTip getTooltip() {
+ if (validationErrorToolTip == null) {
+ validationErrorToolTip = new ToolTip(Display.getCurrent().getActiveShell(), SWT.BALLOON | SWT.ICON_WARNING);
+ }
+ return validationErrorToolTip;
+ }
+
+ private void removeFilterAt(int index) {
+ if (index < 0) {
+ getTooltip().setText("Filter to remove is not selected");
+ getTooltip().setVisible(true);
+ return;
+ }
+
+ String filterAsString = filters.getItem(index);
+ filters.remove(index);
+ rawFilters.remove(filterAsString.hashCode());
+ }
+
+ private void removeAllFilters() {
+ if (rawFilters == null || rawFilters.isEmpty()) {
+ getTooltip().setText("Filter list is empty");
+ getTooltip().setVisible(true);
+ return;
+ }
+
+ filters.removeAll();
+ rawFilters.clear();
+ }
+
+ private String getFieldName(Object notSelectedName) {
+ String fieldName = notSelectedName.toString().replaceAll("-", "").trim();
+ return Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventTree.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventTree.java
new file mode 100644
index 00000000..7e0b23e7
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/CapturedEventTree.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.e4.tools.event.spy.model.CapturedEvent;
+import org.eclipse.e4.tools.event.spy.model.CapturedEventTreeSelection;
+import org.eclipse.e4.tools.event.spy.model.ItemToFilter;
+import org.eclipse.e4.tools.event.spy.model.Parameter;
+import org.eclipse.e4.tools.event.spy.util.ParameterFormatter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.TreeEvent;
+import org.eclipse.swt.events.TreeListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+
+
+
+public class CapturedEventTree {
+
+ public interface SelectionListener {
+ void selectionChanged(CapturedEventTreeSelection selection);
+ }
+
+ private Tree tree;
+
+ private SelectionListener selectionListener;
+
+ private List<ItemToFilter> columns = new ArrayList<ItemToFilter>();
+
+
+ /* Layout scheme:
+ *
+ * +-- parent---------------+
+ * | |
+ * | Tree |
+ * | |
+ * +------------------------+
+ *
+ * */
+
+ public CapturedEventTree(Composite parent) {
+ tree = new Tree(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
+ tree.setHeaderVisible(true);
+ tree.setLinesVisible(true);
+
+ TreeColumn column = new TreeColumn(tree, SWT.LEFT);
+ column.setText(ItemToFilter.Topic.toString());
+ column.setWidth(350);
+ columns.add(ItemToFilter.Topic);
+
+ column = new TreeColumn(tree, SWT.LEFT);
+ column.setText(ItemToFilter.Publisher.toString());
+ column.setWidth(150);
+ columns.add(ItemToFilter.Publisher);
+
+ column = new TreeColumn(tree, SWT.LEFT);
+ column.setText(ItemToFilter.ChangedElement.toString());
+ column.setWidth(150);
+ columns.add(ItemToFilter.ChangedElement);
+
+ addTreeEventListeners();
+ }
+
+ @SuppressWarnings("unchecked")
+ private void addTreeEventListeners() {
+ tree.addTreeListener(new TreeListener() {
+ public void treeExpanded(TreeEvent e) {
+ TreeItem item = (TreeItem) e.item;
+ TreeItem paramItem = item.getItem(0);
+ if (paramItem.getText().isEmpty()) {
+ for (Parameter param: (List<Parameter>) paramItem.getData()) {
+ if (paramItem == null) {
+ paramItem = new TreeItem(item, SWT.NONE);
+ }
+ paramItem.setText(ParameterFormatter.toString(param));
+ paramItem = null;
+ }
+ }
+
+ }
+ public void treeCollapsed(TreeEvent e) {
+ }
+ });
+
+ tree.addMouseListener(new MouseListener() {
+ public void mouseUp(MouseEvent e) {
+ }
+ public void mouseDoubleClick(MouseEvent e) {
+
+ }
+ public void mouseDown(MouseEvent e) {
+ TreeItem[] items = tree.getSelection();
+ if (items == null || items.length == 0) {
+ return;
+ }
+ int selectedItemIndex = -1;
+ for (int i=0; i<columns.size(); i++) {
+ Rectangle rec = items[0].getBounds(i);
+ if (e.x >= rec.x && e.x <= rec.x + rec.width) {
+ selectedItemIndex = i;
+ break;
+ }
+ }
+ if (selectedItemIndex >= 0 && selectionListener != null) {
+ String selection = items[0].getText(selectedItemIndex);
+ if (!selection.isEmpty()) {
+ selectionListener.selectionChanged(new CapturedEventTreeSelection(selection,items[0].getItemCount() == 0));
+ }
+ }
+ }
+ });
+ }
+
+ public void addEvent(CapturedEvent event) {
+ TreeItem item = new TreeItem(tree, SWT.NONE);
+
+ item.setText(columns.indexOf(ItemToFilter.Topic), event.getTopic());
+ item.setText(columns.indexOf(ItemToFilter.Publisher), event.getPublisherClassName());
+ item.setText(columns.indexOf(ItemToFilter.ChangedElement), event.getChangedElementClassName());
+
+ if (event.hasParameters()) {
+ item = new TreeItem(item, SWT.NONE);
+ item.setData(event.getParameters());
+ }
+ }
+
+ public void setSelectionListener(SelectionListener selectionListener) {
+ this.selectionListener = selectionListener;
+ }
+
+ public Control getControl() {
+ return tree;
+ }
+
+ public void removeAll() {
+ tree.removeAll();
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/SpyDialog.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/SpyDialog.java
new file mode 100644
index 00000000..e7a29f18
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/SpyDialog.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.ui;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.tools.event.spy.core.EventMonitor;
+import org.eclipse.e4.tools.event.spy.model.CapturedEvent;
+import org.eclipse.e4.tools.event.spy.model.CapturedEventTreeSelection;
+import org.eclipse.e4.tools.event.spy.util.LoggerWrapper;
+import org.eclipse.e4.tools.event.spy.util.PDEUtils;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+public class SpyDialog extends Dialog implements EventMonitor.NewEventListener {
+ private final static String DIALOG_TITLE = "Event spy dialog";
+
+ private final static String[] SHOW_FILTER_LINK_TEXT = new String[]{"Show filters", "Hide filters"};
+
+ private CapturedEventTree capturedEventTree;
+
+ private CapturedEventFilters capturedEventFilters;
+
+ private Composite outer;
+
+ private EventMonitor eventMonitor;
+
+ private ToggleLink showFiltersLink;
+
+ @Inject
+ private LoggerWrapper logger;
+
+ @Inject
+ private IEventBroker eventBroker;
+
+ @Inject
+ public SpyDialog(Shell shell) {
+ super(shell);
+ setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE);
+ }
+
+ /* Layout scheme:
+ *
+ * +-- Outer ----------------------------------------+
+ * | +-- actionBar --------------------------------+ |
+ * | | | |
+ * | | Start capturing events | ShowFiltersLink | |
+ * | | | |
+ * | +---------------------------------------------+ |
+ * +-------------------------------------------------+
+ * | |
+ * | CapturedEventFilters |
+ * | |
+ * +-------------------------------------------------+
+ * | |
+ * | CapturedEventTree |
+ * | |
+ * +-------------------------------------------------+
+ * | |
+ * | Close |
+ * | |
+ * +-------------------------------------------------+
+ *
+ * */
+
+ @Override
+ protected Point getInitialSize() {
+ return new Point(600, 400);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ outer = (Composite) super.createDialogArea(parent);
+
+ createActionBar(outer);
+ createFilters(outer);
+ createCapturedEventTree(outer);
+
+ return outer;
+ }
+
+ private void createActionBar(Composite parent) {
+ Composite actionBar = new Composite(parent, SWT.NONE);
+ GridData gridData = createDefaultGridData();
+ gridData.grabExcessVerticalSpace = false;
+ actionBar.setLayoutData(gridData);
+
+ RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
+ rowLayout.spacing = 20;
+ actionBar.setLayout(rowLayout);
+
+ ToggleLink link = new ToggleLink(actionBar);
+ link.setText(new String[]{"Start capturing events", "Stop capturing events"});
+ link.setClickListener(new ToggleLink.ClickListener() {
+ public void clicked(boolean toggled) {
+ if (toggled) {
+ captureEvents();
+ } else {
+ stopCaptureEvents();
+ }
+ }
+ });
+
+ showFiltersLink = new ToggleLink(actionBar);
+ showFiltersLink.setText(new String[]{SHOW_FILTER_LINK_TEXT[0], SHOW_FILTER_LINK_TEXT[1]});
+ showFiltersLink.getControl().setLayoutData(new RowData(130, SWT.DEFAULT));
+ showFiltersLink.setClickListener(new ToggleLink.ClickListener() {
+ public void clicked(boolean toggled) {
+ showFilters(toggled);
+ }
+ });
+ }
+
+ private void createFilters(Composite parent) {
+ capturedEventFilters = new CapturedEventFilters(outer);
+ capturedEventFilters.getControl().setVisible(false);
+ GridData gridData = createDefaultGridData();
+ gridData.grabExcessVerticalSpace = false;
+ gridData.exclude = true;
+ capturedEventFilters.getControl().setLayoutData(gridData);
+ }
+
+ private void createCapturedEventTree(Composite parent) {
+ capturedEventTree = new CapturedEventTree(outer);
+ capturedEventTree.getControl().setLayoutData(createDefaultGridData());
+ capturedEventTree.setSelectionListener(new CapturedEventTree.SelectionListener() {
+ public void selectionChanged(CapturedEventTreeSelection selection) {
+ openResource(selection);
+ }
+ });
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText(DIALOG_TITLE);
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, IDialogConstants.OK_ID, "Close", false);
+ }
+
+ public void captureEvents() {
+ capturedEventTree.removeAll();
+ if (eventMonitor == null) {
+ eventMonitor = new EventMonitor(eventBroker);
+ eventMonitor.setNewEventListener(this);
+ }
+ eventMonitor.start(capturedEventFilters.getFilters());
+ getShell().setText(DIALOG_TITLE + " - capturing...");
+ }
+
+ public void stopCaptureEvents() {
+ if (eventMonitor != null) {
+ eventMonitor.stop();
+ }
+ getShell().setText(DIALOG_TITLE);
+ }
+
+ public void newEvent(CapturedEvent event) {
+ capturedEventTree.addEvent(event);
+ }
+
+ private void openResource(CapturedEventTreeSelection selection) {
+ String name = selection.getSelection();
+ if (selection.isParameter()) {
+ String[] splitted = selection.getSelection().split("=");
+ if (splitted.length == 2) {
+ name = splitted[1];
+ }
+ }
+
+ try {
+ PDEUtils.openClass(name);
+ } catch(ClassNotFoundException exc) {
+ logger.warn(exc.getMessage());
+ }
+ }
+
+ private void showFilters(boolean filtersVisible) {
+ capturedEventFilters.getControl().setVisible(filtersVisible);
+ ((GridData) capturedEventFilters.getControl().getLayoutData()).exclude = !filtersVisible;
+
+ //Filters have been set and filters UI is not visible so we have to mark it to user
+ if (!filtersVisible && capturedEventFilters.hasFilters()) {
+ showFiltersLink.setText(new String[] { String.format("%s (%d)", SHOW_FILTER_LINK_TEXT[0],
+ capturedEventFilters.getFiltersCount()), SHOW_FILTER_LINK_TEXT[1]});
+ } else {
+ showFiltersLink.setText(new String[] {SHOW_FILTER_LINK_TEXT[0], SHOW_FILTER_LINK_TEXT[1]});
+ }
+
+ outer.layout(false);
+ }
+
+ private GridData createDefaultGridData() {
+ GridData gridData = new GridData();
+ gridData.verticalAlignment = GridData.FILL;
+ gridData.verticalSpan = 2;
+ gridData.grabExcessVerticalSpace = true;
+ gridData.horizontalAlignment = GridData.FILL;
+ gridData.grabExcessHorizontalSpace = true;
+ return gridData;
+ }
+
+ /** for testing/modifying dialog UI
+ public static void main(String... args) {
+ Display display = new Display ();
+ Shell shell = new Shell (display);
+ shell.open ();
+
+ SpyDialog dialog = new SpyDialog(shell);
+
+ dialog.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch ()) display.sleep ();
+ }
+ display.dispose ();
+ }
+ */
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/ToggleLink.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/ToggleLink.java
new file mode 100644
index 00000000..58e71944
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/ui/ToggleLink.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.ui;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Listener;
+
+public class ToggleLink {
+ private Link link;
+
+ private ClickListener listener;
+
+ private String[] text = {"", ""};
+
+ public interface ClickListener {
+ void clicked(boolean toggled);
+ }
+
+ public ToggleLink(Composite parent) {
+ link = new Link(parent, SWT.NONE);
+ link.setSize(SWT.DEFAULT, SWT.DEFAULT);
+ link.addListener (SWT.Selection, new Listener() {
+ public void handleEvent(Event event) {
+ updateText();
+ if (listener != null) {
+ listener.clicked(isToggled());
+ }
+ }
+ });
+ }
+
+ private void updateText() {
+ String textToUpdate = link.getText().contains(text[0])? text[1]: text[0];
+ setText(textToUpdate);
+ }
+
+ private void setText(String text) {
+ link.setText(String.format("<a>%s</a>", text));
+ }
+
+ public void setClickListener(ClickListener listener) {
+ this.listener = listener;
+ }
+
+ public void setText(String[] text /*normal text, toggle text*/) {
+ this.text = text;
+ setText(isToggled()? text[1]: text[0]);
+ }
+
+ public Control getControl() {
+ return link;
+ }
+
+ private boolean isToggled() {
+ return link.getText().contains(text[1]);
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/LoggerWrapper.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/LoggerWrapper.java
new file mode 100644
index 00000000..cb3a95d5
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/LoggerWrapper.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.util;
+
+import javax.inject.Inject;
+
+import org.eclipse.e4.core.di.annotations.Creatable;
+import org.eclipse.e4.core.di.annotations.Optional;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.tools.event.spy.Constants;
+
+@Creatable
+public class LoggerWrapper extends Logger {
+ @Optional
+ @Inject
+ private Logger logger;
+
+ @Override
+ public boolean isErrorEnabled() {
+ if (logger != null) {
+ return logger.isErrorEnabled();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ if (logger != null) {
+ return logger.isTraceEnabled();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ if (logger != null) {
+ return logger.isWarnEnabled();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ if (logger != null) {
+ return logger.isInfoEnabled();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ if (logger != null) {
+ return logger.isDebugEnabled();
+ }
+ return false;
+ }
+
+ @Override
+ public void error(Throwable t, String message) {
+ if (logger != null && isErrorEnabled()) {
+ logger.error(t, withPluginInfo(message));
+ }
+ }
+
+ @Override
+ public void warn(Throwable t, String message) {
+ if (logger != null && isWarnEnabled()) {
+ logger.warn(t, withPluginInfo(message));
+ }
+ }
+
+ @Override
+ public void info(Throwable t, String message) {
+ if (logger != null && isInfoEnabled()) {
+ logger.info(t, withPluginInfo(message));
+ }
+ }
+
+ @Override
+ public void trace(Throwable t, String message) {
+ if (logger != null && isTraceEnabled()) {
+ logger.trace(t, withPluginInfo(message));
+ }
+ }
+
+ @Override
+ public void debug(Throwable t) {
+ if (logger != null && isDebugEnabled()) {
+ logger.debug(t);
+ }
+ }
+
+ @Override
+ public void debug(Throwable t, String message) {
+ if (logger != null && isDebugEnabled()) {
+ logger.debug(t, withPluginInfo(message));
+ }
+ }
+
+ private String withPluginInfo(String message) {
+ return String.format("Plugin '%s': %s", Constants.PLUGIN_ID, message);
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PDEUtils.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PDEUtils.java
new file mode 100644
index 00000000..274aadf5
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PDEUtils.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.core.plugin.IPluginModelBase;
+import org.eclipse.pde.core.plugin.PluginRegistry;
+import org.eclipse.pde.internal.core.PDECore;
+import org.eclipse.pde.internal.core.SearchablePluginsManager;
+import org.eclipse.pde.internal.runtime.PDERuntimeMessages;
+import org.eclipse.pde.internal.runtime.PDERuntimePlugin;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PartInitException;
+
+public class PDEUtils {
+ private final static Pattern CLASS_NAME_PATTERN = Pattern.compile("(([a-zA-Z_]+[0-9]*\\.)+[a-zA-Z_]+[a-z0-9]*)");
+
+ public static void openClass(String clsName) throws ClassNotFoundException {
+ Matcher matcher = CLASS_NAME_PATTERN.matcher(clsName);
+ if (matcher.find()) {
+ try {
+ clsName = matcher.group(1).trim();
+ openClass(Class.forName(clsName));
+ } catch(ClassNotFoundException exc) {
+ throw new ClassNotFoundException("Class not found in the bundle classpath: " + clsName);
+ }
+ }
+ }
+
+ public static void openClass(Class<?> cls) {
+ IPluginModelBase model = PluginRegistry.findModel(PluginUtils.getBundleId(cls));
+ IResource resource = model != null ? model.getUnderlyingResource() : null;
+ IJavaProject project = null;
+
+ // if we don't find a model
+ if (model == null) {
+ MessageDialog.openError(Display.getCurrent().getActiveShell(), PDERuntimeMessages.SpyIDEUtil_noSourceFound_title,
+ NLS.bind(PDERuntimeMessages.SpyIDEUtil_noSourceFound_message, new Object[] {cls.getName()}));
+ return;
+ }
+
+ if (resource != null) { // project is open in workspace
+ project = JavaCore.create(resource.getProject());
+ } else {
+ SearchablePluginsManager manager = PDECore.getDefault().getSearchablePluginsManager();
+ try {
+ manager.createProxyProject(new NullProgressMonitor());
+ manager.addToJavaSearch(new IPluginModelBase[] {model});
+ project = manager.getProxyProject();
+ } catch (CoreException e) {
+ }
+ }
+ if (project != null)
+ openInEditor(project, cls.getName());
+ }
+
+ private static void openInEditor(IJavaProject project, String clazz) {
+ try {
+ IType type = project.findType(clazz);
+ JavaUI.openInEditor(type, false, true);
+ } catch (JavaModelException e) {
+ PDERuntimePlugin.log(e);
+ } catch (PartInitException e) {
+ PDERuntimePlugin.log(e);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/ParameterFormatter.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/ParameterFormatter.java
new file mode 100644
index 00000000..9ebc147c
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/ParameterFormatter.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.util;
+
+import org.eclipse.e4.tools.event.spy.model.Parameter;
+
+public class ParameterFormatter {
+ //TODO: Add some parameter formatting and break to long strings into multiple lines
+ public static String toString(Parameter parameter) {
+ return String.format("%s = %s", parameter.getName(), parameter.getValue());
+ }
+}
diff --git a/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PluginUtils.java b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PluginUtils.java
new file mode 100644
index 00000000..cf3524f2
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.event.spy/src/org/eclipse/e4/tools/event/spy/util/PluginUtils.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.e4.tools.event.spy.util;
+
+import org.eclipse.e4.tools.event.spy.Constants;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+public class PluginUtils {
+ public static String getContributorURI() {
+ return String.format("platform:/plugin/%s", Constants.PLUGIN_ID);
+ }
+
+ public static String getContributionURI(Class<?> contributionCls) {
+ return String.format("bundleclass://%s/%s", Constants.PLUGIN_ID, contributionCls.getName());
+ }
+
+ public static String getBundleId(Class<?> cls) {
+ Bundle bundle = FrameworkUtil.getBundle(cls);
+ if (bundle == null) {
+ throw new IllegalArgumentException("Cannot find bundle for class: " + cls.getName());
+ }
+ return bundle.getSymbolicName();
+ }
+}
diff --git a/features/org.eclipse.e4.tools.event.spy.feature/.project b/features/org.eclipse.e4.tools.event.spy.feature/.project
new file mode 100644
index 00000000..fc6d26cd
--- /dev/null
+++ b/features/org.eclipse.e4.tools.event.spy.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.e4.tools.event.spy.feature</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/features/org.eclipse.e4.tools.event.spy.feature/build.properties b/features/org.eclipse.e4.tools.event.spy.feature/build.properties
new file mode 100644
index 00000000..b3a611b5
--- /dev/null
+++ b/features/org.eclipse.e4.tools.event.spy.feature/build.properties
@@ -0,0 +1,2 @@
+bin.includes = feature.xml,\
+ feature.properties
diff --git a/features/org.eclipse.e4.tools.event.spy.feature/feature.properties b/features/org.eclipse.e4.tools.event.spy.feature/feature.properties
new file mode 100644
index 00000000..ebea9fc0
--- /dev/null
+++ b/features/org.eclipse.e4.tools.event.spy.feature/feature.properties
@@ -0,0 +1,147 @@
+###############################################################################
+# Copyright (c) 2013 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+# feature.properties
+# contains externalized strings for feature.xml
+# "%foo" in feature.xml corresponds to the key "foo" in this file
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file should be translated.
+
+# "featureName" property - name of the feature
+featureName=E4 Event Spy (Incubation)
+
+# "providerName" property - name of the company that provides the feature
+providerName=Eclipse.org
+
+# "updateSiteName" property - label for the update site
+updateSiteName=The Eclipse Project Updates
+
+# "secondarySiteName" property - label for the update site
+secondaryUpdateSiteName=
+
+# "description" property - description of the feature
+description=E4 Event Spy
+
+# "copyright" property - text of the "Feature Update Copyright"
+copyright=\
+Copyright (c) 2013 IBM Corporation and others.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n\
+\n\
+Contributors:\n\
+ IBM Corporation - initial API and implementation\n
+################ end of copyright property ####################################
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+ECLIPSE FOUNDATION SOFTWARE USER AGREEMENT\n\
+March 17, 2005\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the Eclipse Foundation\n\
+is provided to you under the terms and conditions of the Eclipse Public\n\
+License Version 1.0 ("EPL"). A copy of the EPL is provided with this\n\
+Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse.org CVS\n\
+repository ("Repository") in CVS modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+ - Content may be structured and packaged into modules to facilitate delivering,\n\
+ extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+ plug-in fragments ("Fragments"), and features ("Features").\n\
+ - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java? ARchive)\n\
+ in a directory named "plugins".\n\
+ - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+ Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+ Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+ numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+ - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+ named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+Features may also include other Features ("Included Features"). Files named\n\
+"feature.xml" may contain a list of the names and version numbers of\n\
+Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+ - The top-level (root) directory\n\
+ - Plug-in and Fragment directories\n\
+ - Inside Plug-ins and Fragments packaged as JARs\n\
+ - Sub-directories of the directory named "src" of certain Plug-ins\n\
+ - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Eclipse Update Manager, you must agree to a license ("Feature Update\n\
+License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties". Such Abouts,\n\
+Feature Licenses and Feature Update Licenses contain the terms and\n\
+conditions (or references to such terms and conditions) that govern your\n\
+use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+ - IBM Public License 1.0 (available at http://oss.software.ibm.com/developerworks/opensource/license10.html)\n\
+ - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use,\n\
+and re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.\n
+########### end of license property ##########################################
diff --git a/features/org.eclipse.e4.tools.event.spy.feature/feature.xml b/features/org.eclipse.e4.tools.event.spy.feature/feature.xml
new file mode 100644
index 00000000..9b314be9
--- /dev/null
+++ b/features/org.eclipse.e4.tools.event.spy.feature/feature.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.e4.tools.event.spy.feature"
+ label="%featureName"
+ version="0.15.0.qualifier"
+ provider-name="%providerName">
+
+ <description>
+ %description
+ </description>
+
+ <copyright>
+ %copyright
+ </copyright>
+
+ <license url="%licenseURL">
+ %license
+ </license>
+
+ <plugin
+ id="org.eclipse.e4.tools.event.spy"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+</feature>
diff --git a/features/org.eclipse.e4.tools.event.spy.feature/forceQualifierUpdate.txt b/features/org.eclipse.e4.tools.event.spy.feature/forceQualifierUpdate.txt
new file mode 100644
index 00000000..2e3e3376
--- /dev/null
+++ b/features/org.eclipse.e4.tools.event.spy.feature/forceQualifierUpdate.txt
@@ -0,0 +1,2 @@
+# To force a version qualifier update add the bug here
+
diff --git a/features/org.eclipse.e4.tools.event.spy.feature/license.html b/features/org.eclipse.e4.tools.event.spy.feature/license.html
new file mode 100644
index 00000000..c6af966b
--- /dev/null
+++ b/features/org.eclipse.e4.tools.event.spy.feature/license.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<title>Eclipse.org Software User Agreement</title>
+</head>
+
+<body lang="EN-US" link=blue vlink=purple>
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>March 17, 2005</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY &quot;CONTENT&quot;). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation 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 provided with this Content and is also 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>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse.org CVS repository (&quot;Repository&quot;) in CVS
+ modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+ <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+ <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+ <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;. Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.</li>
+ <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+ <li>The top-level (root) directory</li>
+ <li>Plug-in and Fragment directories</li>
+ <li>Inside Plug-ins and Fragments packaged as JARs</li>
+ <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+ <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Eclipse Update Manager, you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+ <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+ <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+ <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+ <li>IBM Public License 1.0 (available at <a href="http://oss.software.ibm.com/developerworks/opensource/license10.html">http://oss.software.ibm.com/developerworks/opensource/license10.html</a>)</li>
+ <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+ <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<small>Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.</small>
+</body>
+</html>
diff --git a/features/org.eclipse.e4.tools.event.spy.feature/pom.xml b/features/org.eclipse.e4.tools.event.spy.feature/pom.xml
new file mode 100644
index 00000000..6135106e
--- /dev/null
+++ b/features/org.eclipse.e4.tools.event.spy.feature/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+ <groupId>org.eclipse.e4.tools</groupId>
+ <artifactId>e4-tools-aggregator</artifactId>
+ <version>0.15.0-SNAPSHOT</version>
+ <relativePath>../../</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.e4</groupId>
+ <artifactId>org.eclipse.e4.tools.event.spy.feature</artifactId>
+ <version>0.15.0.qualifier</version>
+ <packaging>eclipse-feature</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho.extras</groupId>
+ <artifactId>tycho-source-feature-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <id>source-feature</id>
+ <goals>
+ <goal>source-feature</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-p2-plugin</artifactId>
+ <version>${tycho.version}</version>
+ <executions>
+ <execution>
+ <id>attached-p2-metadata</id>
+ <phase>package</phase>
+ <goals>
+ <goal>p2-metadata</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project> \ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 3d440b88..24b8db85 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,10 +50,12 @@
<module>./bundles/org.eclipse.e4.tools.css.editor.ui</module>
<module>./bundles/org.eclipse.e4.tools.css.editor</module>
<module>./bundles/org.eclipse.e4.tools.css.spy</module>
+ <module>./bundles/org.eclipse.e4.tools.event.spy</module>
<module>./features/org.eclipse.e4.core.tools.feature</module>
<module>./features/org.eclipse.e4.tools.css.editor.feature</module>
<module>./features/org.eclipse.e4.tools.css.spy.feature</module>
<module>./features/org.eclipse.e4.tools.e3x.bridge.feature</module>
+ <module>./features/org.eclipse.e4.tools.event.spy.feature</module>
<module>./build/org.eclipse.e4.core.tools.update/</module>
</modules>
</project>

Back to the top