Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Tiede2013-02-11 09:46:45 +0000
committerMarkus Tiede2013-02-11 09:46:45 +0000
commit354a64d80640d6dd87c4e3328d1819eced9d36b5 (patch)
treec3bf383f2932fbd29af92abe3f2a722239e437a8 /org.eclipse.jubula.rc.rcp.e3/src
parent769dc38fdd89a6a7f0dc85757a424854c3ff5c51 (diff)
downloadorg.eclipse.jubula.core-354a64d80640d6dd87c4e3328d1819eced9d36b5.tar.gz
org.eclipse.jubula.core-354a64d80640d6dd87c4e3328d1819eced9d36b5.tar.xz
org.eclipse.jubula.core-354a64d80640d6dd87c4e3328d1819eced9d36b5.zip
Sprint task - patch / attachment 226820 for bug http://bugs.eclipse.org/399745 reviewed and applied.
Diffstat (limited to 'org.eclipse.jubula.rc.rcp.e3/src')
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3ComponentNamer.java34
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3Startup.java410
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/factory/DefaultEditPartAdapterFactory.java85
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/ClassCountEditPartIdentifier.java73
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/IEditPartIdentifier.java39
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/StaticEditPartIdentifier.java53
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/implclasses/FigureCanvasImplClass.java764
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/FigureHighlighter.java196
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/GefInspectorListenerAppender.java441
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/listener/GefPartListener.java144
-rw-r--r--org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/util/FigureCanvasUtil.java114
11 files changed, 2353 insertions, 0 deletions
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3ComponentNamer.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3ComponentNamer.java
new file mode 100644
index 000000000..9da5bbdf1
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3ComponentNamer.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2013 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.accessor;
+
+import org.eclipse.jface.preference.PreferenceManager;
+import org.eclipse.jubula.rc.rcp.swt.aut.RcpSwtComponentNamer;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * This listener assigns names to components as they become visible. The
+ * assigned name is determined by supporting data of the component and its
+ * surroundings.
+ *
+ * @author BREDEX GmbH
+ * @created Oct 19, 2007
+ */
+public class E3ComponentNamer extends RcpSwtComponentNamer {
+
+ /**
+ * {@inheritDoc}
+ */
+ protected PreferenceManager getPreferenceManager() {
+ return PlatformUI.getWorkbench()
+ .getPreferenceManager();
+ }
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3Startup.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3Startup.java
new file mode 100644
index 000000000..5a48a6559
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/accessor/E3Startup.java
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.accessor;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jubula.rc.common.AUTServer;
+import org.eclipse.jubula.rc.common.tester.adapter.factory.GUIAdapterFactoryRegistry;
+import org.eclipse.jubula.rc.rcp.e3.gef.inspector.GefInspectorListenerAppender;
+import org.eclipse.jubula.rc.rcp.e3.gef.listener.GefPartListener;
+import org.eclipse.jubula.rc.rcp.swt.aut.RcpSwtComponentNamer;
+import org.eclipse.jubula.rc.swt.SwtAUTServer;
+import org.eclipse.jubula.rc.swt.tester.adapter.factory.SWTAdapterFactory;
+import org.eclipse.jubula.tools.constants.AutConfigConstants;
+import org.eclipse.jubula.tools.constants.CommandConstants;
+import org.eclipse.jubula.tools.utils.EnvironmentUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.CoolBar;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IPartListener2;
+import org.eclipse.ui.IStartup;
+import org.eclipse.ui.IViewReference;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPartReference;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.WorkbenchPartReference;
+
+
+/**
+ * Initializes an AUT Server in a plug-in context.
+ *
+ * It is very important to avoid referencing GEF (org.eclipse.gef.*) classes
+ * directly from this class, as this will cause Class Not Found errors if the
+ * AUT does not contain the GEF plug-in.
+ *
+ * @author BREDEX GmbH
+ * @created Oct 5, 2007
+ */
+public abstract class E3Startup implements IStartup {
+
+ /** bundle ID for Eclipse Graphical Editing Framework (GEF) */
+ private static final String GEF_BUNDLE_ID = "org.eclipse.gef"; //$NON-NLS-1$
+
+ /** Single listener instance */
+ private IPartListener2 m_partNamingListener =
+ new PartNamingListener();
+
+ /**
+ * This listener
+ */
+ private IPartListener2 m_gefListener = null;
+
+ /**
+ * Assigns the controls (Composites) of Parts unique names based on
+ * their partId.
+ *
+ * @author BREDEX GmbH
+ * @created Oct 5, 2007
+ */
+ protected class PartNamingListener implements IPartListener2 {
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partActivated(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partBroughtToTop(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partClosed(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partDeactivated(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partHidden(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partInputChanged(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partOpened(IWorkbenchPartReference partRef) {
+ if (partRef instanceof WorkbenchPartReference) {
+ WorkbenchPartReference workbenchPartRef =
+ (WorkbenchPartReference)partRef;
+ // Get pane contents and part id
+ Control partContent =
+ workbenchPartRef.getPane().getControl();
+
+ if (RcpSwtComponentNamer.hasWidgetToBeNamed(partContent)) {
+
+ // Name pane control based on part
+ String partId = workbenchPartRef.getId();
+
+ // Append secondary id, if necessary
+ if (partRef instanceof IViewReference) {
+ String secondaryId =
+ ((IViewReference)partRef).getSecondaryId();
+ if (secondaryId != null) {
+ partId += "_" + secondaryId; //$NON-NLS-1$
+ }
+ }
+
+ if (partId == null || partId.trim().length() == 0) {
+ // Don't assign a name if the id is unusable
+ return;
+ }
+ RcpSwtComponentNamer.setComponentName(partContent, partId);
+
+ // Assign a corresponding id to the part's toolbar, if
+ // possible/usable.
+ final Control partToolbar =
+ getToolBarFromWorkbenchPartRef(workbenchPartRef);
+ final String finalPartId = partId;
+ if (partToolbar != null) {
+ RcpSwtComponentNamer.setToolbarComponentName(
+ partToolbar, finalPartId);
+ }
+
+ // A repaint is required in order for the aut component
+ // hierarchy to notice the change.
+ Shell shell = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getShell();
+ repaintToolbars(shell);
+ }
+ }
+
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partVisible(IWorkbenchPartReference partRef) {
+ partOpened(partRef);
+ }
+
+ }
+
+ /**
+ * This abstract method is a place holder for different implementations
+ * depending on Eclipse e3.x and e4.x running in compatibility mode
+ * to get the SWT control form a given workbench part reference.
+ * @param workbenchPartRef The workbench part reference.
+ * @return The control of the tool bar from the given workbench part reference
+ * or null, if it does not exist.
+ * @see org.eclipse.jubula.rc.rcp.e3.specific#Startup
+ * @see org.eclipse.jubula.rc.rcp.e4.compat#Startup
+ */
+ public abstract Control getToolBarFromWorkbenchPartRef(
+ WorkbenchPartReference workbenchPartRef);
+
+ /**
+ * {@inheritDoc}
+ */
+ public void earlyStartup() {
+ final Properties envVars =
+ EnvironmentUtils.getProcessEnvironment();
+
+ if (getValue(AutConfigConstants.AUT_AGENT_HOST, envVars) != null) {
+ final IWorkbench workbench = PlatformUI.getWorkbench();
+ final Display display = workbench.getDisplay();
+ initAutServer(display, envVars);
+
+ display.syncExec(new Runnable() {
+ public void run() {
+ // add GEF listeners (and listener appenders) for GEF, if available
+ if (Platform.getBundle(E3Startup.GEF_BUNDLE_ID) != null) {
+ m_gefListener = new GefPartListener();
+ AUTServer.getInstance().addInspectorListenerAppender(
+ new GefInspectorListenerAppender());
+ }
+
+ // add naming listener
+ E3ComponentNamer namer = new E3ComponentNamer();
+ display.addFilter(SWT.Paint, namer);
+ display.addFilter(SWT.Activate, namer);
+
+ // Add window listener
+ addWindowListener(workbench);
+
+ IWorkbenchWindow window =
+ workbench.getActiveWorkbenchWindow();
+ if (window != null) {
+ // Add part listeners
+ addPartListeners(window);
+
+ // Handle existing parts
+ IWorkbenchPage [] pages = window.getPages();
+ for (int i = 0; i < pages.length; i++) {
+ IEditorReference[] editorRefs =
+ pages[i].getEditorReferences();
+ IViewReference[] viewRefs =
+ pages[i].getViewReferences();
+ for (int j = 0; j < editorRefs.length; j++) {
+ m_partNamingListener.partOpened(editorRefs[j]);
+ if (m_gefListener != null) {
+ m_gefListener.partOpened(editorRefs[j]);
+ }
+ }
+ for (int k = 0; k < viewRefs.length; k++) {
+ m_partNamingListener.partOpened(viewRefs[k]);
+ if (m_gefListener != null) {
+ m_gefListener.partOpened(viewRefs[k]);
+ }
+ }
+ }
+
+ // If a shell already exists, make sure that we get another
+ // chance to immediately add/use our naming listeners.
+ Shell mainShell = window.getShell();
+ if (mainShell != null && !mainShell.isDisposed()) {
+ repaintToolbars(mainShell);
+ }
+ }
+ }
+
+ });
+ // Registering the AdapterFactory for SWT at the registry
+ GUIAdapterFactoryRegistry.getInstance()
+ .registerFactory(new SWTAdapterFactory());
+ // add listener to AUT
+ AUTServer.getInstance().addToolKitEventListenerToAUT();
+
+ }
+
+ }
+
+ /**
+ * Initializes the AUT Server for the host application.
+ *
+ * @param display The Display to use for the AUT Server.
+ * @param envVars Environment variables to consult in configuring the
+ * AUT Server.
+ */
+ private void initAutServer(Display display, Properties envVars) {
+ ((SwtAUTServer)AUTServer.getInstance(CommandConstants
+ .AUT_SWT_SERVER)).setDisplay(display);
+ AUTServer.getInstance().setAutAgentHost(getValue(
+ AutConfigConstants.AUT_AGENT_HOST, envVars));
+ AUTServer.getInstance().setAutAgentPort(getValue(
+ AutConfigConstants.AUT_AGENT_PORT, envVars));
+ AUTServer.getInstance().setAutID(getValue(
+ AutConfigConstants.AUT_NAME, envVars));
+
+ AUTServer.getInstance().start(true);
+ }
+
+ /**
+ * Adds a window listener to the given workbench. This listener adds a
+ * part naming listener to opening windows.
+ *
+ * @param workbench The workbench to which the listener will be added.
+ */
+ private void addWindowListener(IWorkbench workbench) {
+ workbench.addWindowListener(new IWindowListener() {
+
+ public void windowActivated(IWorkbenchWindow window) {
+ addPartListeners(window);
+ }
+
+ public void windowClosed(IWorkbenchWindow window) {
+ // Do nothing
+ }
+
+ public void windowDeactivated(IWorkbenchWindow window) {
+ // Do nothing
+ }
+
+ public void windowOpened(IWorkbenchWindow window) {
+ addPartListeners(window);
+ }
+
+ });
+ }
+
+ /**
+ * Fires a paint event on all Toolbars and Coolbars within the given shell.
+ *
+ * @param mainShell The shell to search for Coolbars and Toolbars.
+ */
+ public static void repaintToolbars(Shell mainShell) {
+ List toolbarList = new ArrayList();
+ getToolbars(mainShell, toolbarList);
+ Iterator iter = toolbarList.iterator();
+ while (iter.hasNext()) {
+ Control toolbar = (Control)iter.next();
+ toolbar.update();
+ toolbar.redraw();
+ toolbar.update();
+ }
+ }
+
+ /**
+ * Adds all Coolbars and Toolbars within the given composite to the given
+ * list. The search is is also performed recursively on children of the
+ * given composite.
+ *
+ * @param composite The composite to search.
+ * @param toolbarList The list to which found Toolbars and Coolbars will
+ * be added.
+ */
+ public static void getToolbars(Composite composite,
+ List toolbarList) {
+
+ if (composite != null && !composite.isDisposed()) {
+ Control [] children = composite.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ if (children[i] instanceof Composite) {
+ getToolbars((Composite)children[i], toolbarList);
+ }
+ try {
+ if (children[i] instanceof ToolBar
+ || children[i] instanceof CoolBar) {
+
+ toolbarList.add(children[i]);
+ }
+ } catch (NoClassDefFoundError e) {
+ // we may be running in eRCP which doesn't know about
+ // toolbars, so we just ignore this
+ }
+ }
+ }
+ }
+
+ /**
+ * Add part listeners to the given window.
+ *
+ * @param window The window to which the listeners will be added.
+ */
+ private void addPartListeners(IWorkbenchWindow window) {
+ window.getPartService().addPartListener(m_partNamingListener);
+ if (m_gefListener != null) {
+ window.getPartService().addPartListener(m_gefListener);
+ }
+ }
+
+ /**
+ * Returns the value for a given property. First, <code>envVars</code>
+ * is checked for the given property. If this
+ * property cannot be found there, the
+ * Java System Properties will be checked. If the property is not
+ * found there, <code>null</code> will be returned.
+ *
+ * @param envVars The first source to check for the given property.
+ * @param propName The name of the property for which to find the value.
+ * @return The value for the given property name, or <code>null</code> if
+ * given property name cannot be found.
+ */
+ private String getValue(String propName, Properties envVars) {
+ String value =
+ envVars.getProperty(propName);
+ if (value == null) {
+ value = System.getProperty(propName);
+ }
+ return value;
+ }
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/factory/DefaultEditPartAdapterFactory.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/factory/DefaultEditPartAdapterFactory.java
new file mode 100644
index 000000000..21a71612a
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/factory/DefaultEditPartAdapterFactory.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.factory;
+
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.gef.EditPart;
+import org.eclipse.jubula.rc.rcp.e3.gef.identifier.ClassCountEditPartIdentifier;
+import org.eclipse.jubula.rc.rcp.e3.gef.identifier.IEditPartIdentifier;
+
+
+/**
+ * The default adapter factory for getting adapters from EditPart to
+ * IEditPartIdentifier.
+ *
+ * @author BREDEX GmbH
+ * @created May 13, 2009
+ */
+public class DefaultEditPartAdapterFactory implements IAdapterFactory {
+
+ /** the types managed by this factory */
+ private static final Class [] ADAPTABLE_TYPES =
+ new Class [] {EditPart.class};
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getAdapter(Object adaptableObject, Class adapterType) {
+ if (adaptableObject instanceof EditPart) {
+ if (adapterType == IEditPartIdentifier.class) {
+ return new ClassCountEditPartIdentifier(
+ (EditPart)adaptableObject);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class[] getAdapterList() {
+ return ADAPTABLE_TYPES;
+ }
+
+ /**
+ *
+ * @param editPart The EditPart for which to find the IEditPartIdentifier.
+ * @return the IEditPartIdentifier for the given EditPart. First, an attempt
+ * is made to load this from a registered adapter factory. If this
+ * does not provide an adapter, then this adapter factory is
+ * queried, providing a default implementation.
+ */
+ public static IEditPartIdentifier loadFigureIdentifier(EditPart editPart) {
+ if (editPart == null) {
+ // null-safe
+ return null;
+ }
+ IEditPartIdentifier editPartIdentifier =
+ (IEditPartIdentifier)Platform.getAdapterManager().loadAdapter(
+ editPart, IEditPartIdentifier.class.getName());
+// if (editPartIdentifier == null) {
+// AccessibleEditPart accessible =
+// (AccessibleEditPart)Platform.getAdapterManager().loadAdapter(
+// editPart, AccessibleEditPart.class.getName());
+// AccessibleEvent e = new AccessibleEvent(IEditPartIdentifier.class);
+// accessible.getName(e);
+// if (e.result != null) {
+// editPartIdentifier = new StaticEditPartIdentifier(e.result);
+// }
+// }
+ if (editPartIdentifier == null) {
+ editPartIdentifier = new ClassCountEditPartIdentifier(editPart);
+ }
+
+ return editPartIdentifier;
+ }
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/ClassCountEditPartIdentifier.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/ClassCountEditPartIdentifier.java
new file mode 100644
index 000000000..1376beb74
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/ClassCountEditPartIdentifier.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.identifier;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.gef.EditPart;
+
+/**
+ * Default implementation of {@link IEditPartIdentifier}. The identifier is
+ * the name of the class of the {@link EditPart} plus a sequential number.
+ *
+ * @author BREDEX GmbH
+ * @created May 13, 2009
+ */
+public class ClassCountEditPartIdentifier implements IEditPartIdentifier {
+
+ /** the EditPart for which identifiers can be generated */
+ private EditPart m_editPart;
+
+ /**
+ * Constructor
+ *
+ * @param editPart The EditPart for which identifiers can be generated.
+ */
+ public ClassCountEditPartIdentifier(EditPart editPart) {
+ m_editPart = editPart;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getIdentifier() {
+ EditPart parent = m_editPart.getParent();
+ String className = m_editPart.getClass().getName();
+ String id = className;
+ if (parent != null) {
+ id += "_"; //$NON-NLS-1$
+ Iterator siblingIterator = parent.getChildren().iterator();
+ boolean isFound = false;
+ int count = 0;
+ while (siblingIterator.hasNext() && !isFound) {
+ EditPart sibling = (EditPart)siblingIterator.next();
+ if (sibling == m_editPart) {
+ isFound = true;
+ }
+ if (sibling.getClass().getName().equals(className)) {
+ count++;
+ }
+ }
+ id += count;
+ }
+ return id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map getConnectionAnchors() {
+ return new HashMap();
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/IEditPartIdentifier.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/IEditPartIdentifier.java
new file mode 100644
index 000000000..f386f260f
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/IEditPartIdentifier.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.identifier;
+
+import java.util.Map;
+
+
+
+/**
+ * Encapsulates the ability to generate unique IDs for a given
+ * {@link org.eclipse.gef.EditPart}.
+ *
+ * @author BREDEX GmbH
+ * @created May 13, 2009
+ */
+public interface IEditPartIdentifier {
+
+ /**
+ *
+ * @return a String uniquely identifying the EditPart.
+ */
+ public String getIdentifier();
+
+ /**
+ *
+ * @return a map that correlates identifiers (<code>String</code>s) with
+ * <code>ConnectionAnchor</code>s.
+ */
+ public Map getConnectionAnchors();
+
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/StaticEditPartIdentifier.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/StaticEditPartIdentifier.java
new file mode 100644
index 000000000..8a4ab9a12
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/identifier/StaticEditPartIdentifier.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.identifier;
+
+import java.util.Collections;
+import java.util.Map;
+
+
+/**
+ * Provides a static String as an identifier. This class does not take the
+ * state of the {@link org.eclipse.gef.EditPart} into account, so it is useful
+ * for stateless {@link org.eclipse.gef.EditPart}s (ex. containers).
+ *
+ * @author BREDEX GmbH
+ * @created May 19, 2009
+ */
+public class StaticEditPartIdentifier implements IEditPartIdentifier {
+
+ /** the identifier that will always be returned */
+ private String m_id;
+
+ /**
+ * Constructor
+ *
+ * @param id The static identifier String that will always be returned.
+ */
+ public StaticEditPartIdentifier(String id) {
+ m_id = id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getIdentifier() {
+ return m_id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map getConnectionAnchors() {
+ return Collections.EMPTY_MAP;
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/implclasses/FigureCanvasImplClass.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/implclasses/FigureCanvasImplClass.java
new file mode 100644
index 000000000..49ac0983f
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/implclasses/FigureCanvasImplClass.java
@@ -0,0 +1,764 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.implclasses;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.lang.Validate;
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.gef.RootEditPart;
+import org.eclipse.gef.palette.PaletteEntry;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.jubula.rc.common.driver.ClickOptions;
+import org.eclipse.jubula.rc.common.driver.IRobot;
+import org.eclipse.jubula.rc.common.driver.IRunnable;
+import org.eclipse.jubula.rc.common.exception.StepExecutionException;
+import org.eclipse.jubula.rc.common.implclasses.MatchUtil;
+import org.eclipse.jubula.rc.common.implclasses.Verifier;
+import org.eclipse.jubula.rc.rcp.e3.gef.factory.DefaultEditPartAdapterFactory;
+import org.eclipse.jubula.rc.rcp.e3.gef.identifier.IEditPartIdentifier;
+import org.eclipse.jubula.rc.rcp.e3.gef.listener.GefPartListener;
+import org.eclipse.jubula.rc.swt.driver.DragAndDropHelperSwt;
+import org.eclipse.jubula.rc.swt.implclasses.AbstractControlImplClass;
+import org.eclipse.jubula.rc.swt.implclasses.MenuUtil;
+import org.eclipse.jubula.tools.objects.event.EventFactory;
+import org.eclipse.jubula.tools.objects.event.TestErrorEvent;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+
+/**
+ * Implementation class for Figure Canvas (Eclipse GEF).
+ *
+ * @author BREDEX GmbH
+ * @created May 13, 2009
+ */
+public class FigureCanvasImplClass extends AbstractControlImplClass {
+
+ /**
+ * the viewer that contains the EditParts corresponding to the FigureCanvas
+ */
+ private GraphicalViewer m_viewer = null;
+
+ /** the composite in which the IFigures are displayed */
+ private Composite m_composite = null;
+
+ /**
+ * {@inheritDoc}
+ */
+ public Control getComponent() {
+ return m_composite;
+ }
+
+ /**
+ *
+ * @return the viewer associated with the canvas to test.
+ */
+ private GraphicalViewer getViewer() {
+ return m_viewer;
+ }
+
+ /**
+ *
+ * @return the control for the canvas to test.
+ */
+ private Control getViewerControl() {
+ return getViewer().getControl();
+ }
+
+ /**
+ *
+ * @return the root edit part of the viewer.
+ */
+ private RootEditPart getRootEditPart() {
+ return getViewer().getRootEditPart();
+ }
+
+ /**
+ *
+ * @return the root of the palette viewer (tool palette).
+ */
+ private RootEditPart getPaletteRoot() {
+ return getViewer().getEditDomain().getPaletteViewer().getRootEditPart();
+ }
+
+ /**
+ *
+ * @param textPath The path to the tool.
+ * @param operator The operator used for matching.
+ * @return the EditPart found at the end of the given path. Returns
+ * <code>null</code> if no EditPart can be found for the given path
+ * or if the EditPart found is not a GraphicalEditPart.
+ */
+ private GraphicalEditPart findPaletteEditPart(
+ String textPath, String operator) {
+
+ final String[] pathItems = MenuUtil.splitPath(textPath);
+ boolean isExisting = true;
+
+ EditPart currentEditPart = getPaletteRoot().getContents();
+
+ for (int i = 0; i < pathItems.length && currentEditPart != null; i++) {
+ List effectiveChildren = currentEditPart.getChildren();
+
+ EditPart [] children =
+ (EditPart [])effectiveChildren.toArray(
+ new EditPart[effectiveChildren.size()]);
+ boolean itemFound = false;
+ for (int j = 0; j < children.length && !itemFound; j++) {
+ Object model = children[j].getModel();
+ if (model instanceof PaletteEntry) {
+ String entryLabel = ((PaletteEntry)model).getLabel();
+ if (entryLabel != null
+ && MatchUtil.getInstance().match(
+ entryLabel, pathItems[i], operator)) {
+ itemFound = true;
+ currentEditPart = children[j];
+ }
+ }
+ }
+ if (!itemFound) {
+ isExisting = false;
+ break;
+ }
+
+ }
+
+ return isExisting && currentEditPart instanceof GraphicalEditPart
+ ? (GraphicalEditPart)currentEditPart : null;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String[] getTextArrayFromComponent() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setComponent(final Object graphicsComponent) {
+ getEventThreadQueuer().invokeAndWait(getClass().getName() + ".setComponent", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ FigureCanvas figureCanvas = (FigureCanvas)graphicsComponent;
+ Composite parent = figureCanvas;
+ while (parent != null
+ && !(parent.getData(
+ GefPartListener.TEST_GEF_VIEWER_DATA_KEY)
+ instanceof GraphicalViewer)) {
+ parent = parent.getParent();
+ }
+
+ if (parent != null) {
+ m_composite = parent;
+ m_viewer =
+ (GraphicalViewer)parent.getData(
+ GefPartListener.TEST_GEF_VIEWER_DATA_KEY);
+ }
+ return null;
+ }
+
+ });
+ }
+
+ /**
+ * Checks whether the figure for the EditPart for the given path exists and
+ * is visible.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @param exists Whether the figure is expected to exist.
+ */
+ public void gdCheckFigureExists(
+ String textPath, String operator, boolean exists) {
+
+ boolean isExisting =
+ findFigure(findEditPart(textPath, operator)) != null;
+ if (!isExisting) {
+ // See if there's a connection anchor at the given path
+ isExisting = findConnectionAnchor(textPath, operator) != null;
+ }
+
+ Verifier.equals(exists, isExisting);
+
+ }
+
+ /**
+ * Checks the given property of the figure at the given path.
+ *
+ * @param textPath The path to the figure.
+ * @param textPathOperator The operator used for matching the text path.
+ * @param propertyName The name of the property
+ * @param expectedPropValue The value of the property as a string
+ * @param valueOperator The operator used to verify
+ */
+ public void gdVerifyFigureProperty(String textPath,
+ String textPathOperator, final String propertyName,
+ String expectedPropValue, String valueOperator) {
+
+ final IFigure figure =
+ findFigure(findEditPart(textPath, textPathOperator));
+ if (figure == null) {
+ throw new StepExecutionException(
+ "No figure could be found for the given text path.", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NOT_FOUND));
+ }
+ Object prop = getEventThreadQueuer().invokeAndWait("getProperty", //$NON-NLS-1$
+ new IRunnable() {
+
+ public Object run() throws StepExecutionException {
+ try {
+ return PropertyUtils.getProperty(figure, propertyName);
+ } catch (IllegalAccessException e) {
+ throw new StepExecutionException(
+ e.getMessage(),
+ EventFactory.createActionError(
+ TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
+ } catch (InvocationTargetException e) {
+ throw new StepExecutionException(
+ e.getMessage(),
+ EventFactory.createActionError(
+ TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
+ } catch (NoSuchMethodException e) {
+ throw new StepExecutionException(
+ e.getMessage(),
+ EventFactory.createActionError(
+ TestErrorEvent.PROPERTY_NOT_ACCESSABLE));
+ }
+ }
+
+ });
+ final String propToStr = String.valueOf(prop);
+ Verifier.match(propToStr, expectedPropValue, valueOperator);
+
+ }
+
+ /**
+ * Checks whether the tool for the given path exists and
+ * is visible.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @param exists Whether the figure is expected to exist.
+ */
+ public void gdCheckToolExists(
+ String textPath, String operator, boolean exists) {
+
+ boolean isExisting = findPaletteFigure(textPath, operator) != null;
+
+ Verifier.equals(exists, isExisting);
+
+ }
+
+ /**
+ * Finds and clicks the figure for the given path.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @param count The number of times to click.
+ * @param button The mouse button to use for the click.
+ */
+ public void gdClickFigure(String textPath, String operator,
+ int count, int button) {
+
+ getRobot().click(getViewerControl(),
+ getFigureBoundsChecked(textPath, operator),
+ ClickOptions.create().setScrollToVisible(false)
+ .setClickCount(count).setMouseButton(button));
+ }
+
+ /**
+ * Finds and clicks on a connection between a source figure and a
+ * target figure.
+ *
+ * @param sourceTextPath The path to the source figure.
+ * @param sourceOperator The operator to use for matching the source
+ * figure path.
+ * @param targetTextPath The path to the target figure.
+ * @param targetOperator The operator to use for matching the target
+ * figure path.
+ * @param count The number of times to click.
+ * @param button The mouse button to use for the click.
+ */
+ public void gdClickConnection(String sourceTextPath, String sourceOperator,
+ String targetTextPath, String targetOperator,
+ int count, int button) {
+
+ GraphicalEditPart sourceEditPart =
+ findEditPart(sourceTextPath, sourceOperator);
+ GraphicalEditPart targetEditPart =
+ findEditPart(targetTextPath, targetOperator);
+
+ ConnectionEditPart connectionEditPart = null;
+
+ if (sourceEditPart != null) {
+ List sourceConnectionList = sourceEditPart.getSourceConnections();
+ ConnectionEditPart [] sourceConnections =
+ (ConnectionEditPart [])sourceConnectionList.toArray(
+ new ConnectionEditPart[sourceConnectionList.size()]);
+ for (int i = 0; i < sourceConnections.length
+ && connectionEditPart == null; i++) {
+ if (sourceConnections[i].getTarget() == targetEditPart) {
+ connectionEditPart = sourceConnections[i];
+ }
+ }
+ } else if (targetEditPart != null) {
+ List targetConnectionList = targetEditPart.getTargetConnections();
+ ConnectionEditPart [] targetConnections =
+ (ConnectionEditPart [])targetConnectionList.toArray(
+ new ConnectionEditPart[targetConnectionList.size()]);
+ for (int i = 0; i < targetConnections.length
+ && connectionEditPart == null; i++) {
+ if (targetConnections[i].getSource() == targetEditPart) {
+ connectionEditPart = targetConnections[i];
+ }
+ }
+ } else {
+ throw new StepExecutionException(
+ "No figures could be found for the given text paths.", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+ IFigure connectionFigure = findFigure(connectionEditPart);
+ if (connectionFigure == null) {
+ String missingEnd = sourceEditPart == null ? "source" : "target"; //$NON-NLS-1$ //$NON-NLS-2$
+ throw new StepExecutionException(
+ "No connection could be found for the given " + missingEnd + " figure.", //$NON-NLS-1$ //$NON-NLS-2$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+
+ // Scrolling
+ revealEditPart(connectionEditPart);
+
+ if (connectionFigure instanceof Connection) {
+ Point midpoint =
+ ((Connection)connectionFigure).getPoints().getMidpoint();
+ connectionFigure.translateToAbsolute(midpoint);
+ getRobot().click(getViewerControl(), null,
+ ClickOptions.create().setScrollToVisible(false)
+ .setClickCount(count).setMouseButton(button),
+ midpoint.x, true, midpoint.y, true);
+ } else {
+ getRobot().click(getViewerControl(),
+ getBounds(connectionFigure),
+ ClickOptions.create().setScrollToVisible(false)
+ .setClickCount(count).setMouseButton(button));
+ }
+
+ }
+
+ /**
+ * Clicks the specified position within the given figure.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @param count amount of clicks
+ * @param button what button should be clicked
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @throws StepExecutionException if step execution fails.
+ */
+ public void gdClickInFigure(String textPath, String operator,
+ int count, int button, int xPos, String xUnits,
+ int yPos, String yUnits) throws StepExecutionException {
+
+ getRobot().click(getViewerControl(),
+ getFigureBoundsChecked(textPath, operator),
+ ClickOptions.create().setScrollToVisible(false)
+ .setClickCount(count).setMouseButton(button),
+ xPos, xUnits.equalsIgnoreCase(POS_UNIT_PIXEL),
+ yPos, yUnits.equalsIgnoreCase(POS_UNIT_PIXEL));
+ }
+
+ /**
+ * Simulates the beginning of a Drag. Moves to the specified position
+ * within the given figure and stores information related to the drag to
+ * be used later by a Drop operation.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @param mouseButton the mouse button.
+ * @param modifier the modifier, e.g. shift, ctrl, etc.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ */
+ public void gdDragFigure(String textPath, String operator,
+ int mouseButton, String modifier, int xPos,
+ String xUnits, int yPos, String yUnits) {
+ // Only store the Drag-Information. Otherwise the GUI-Eventqueue
+ // blocks after performed Drag!
+ final DragAndDropHelperSwt dndHelper = DragAndDropHelperSwt
+ .getInstance();
+ dndHelper.setMouseButton(mouseButton);
+ dndHelper.setModifier(modifier);
+ dndHelper.setDragComponent(null);
+ gdClickInFigure(textPath, operator, 0, mouseButton,
+ xPos, xUnits, yPos, yUnits);
+ }
+
+ /**
+ * Performs a Drop. Moves to the specified location within the given figure
+ * and releases the modifier and mouse button pressed by the previous drag
+ * operation.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @param xPos what x position
+ * @param xUnits should x position be pixel or percent values
+ * @param yPos what y position
+ * @param yUnits should y position be pixel or percent values
+ * @param delayBeforeDrop the amount of time (in milliseconds) to wait
+ * between moving the mouse to the drop point and
+ * releasing the mouse button
+ */
+ public void gdDropOnFigure(final String textPath, final String operator,
+ final int xPos, final String xUnits, final int yPos,
+ final String yUnits, int delayBeforeDrop) {
+
+ final DragAndDropHelperSwt dndHelper =
+ DragAndDropHelperSwt.getInstance();
+ final IRobot robot = getRobot();
+ final String modifier = dndHelper.getModifier();
+ final int mouseButton = dndHelper.getMouseButton();
+ // Note: This method performs the drag AND drop action in one runnable
+ // in the GUI-Eventqueue because after the mousePress, the eventqueue
+ // blocks!
+ try {
+ pressOrReleaseModifiers(modifier, true);
+
+ getEventThreadQueuer().invokeAndWait("gdStartDragFigure", new IRunnable() { //$NON-NLS-1$
+ public Object run() throws StepExecutionException {
+ // drag
+ robot.mousePress(dndHelper.getDragComponent(), null,
+ mouseButton);
+
+ shakeMouse();
+
+ // drop
+ gdClickInFigure(textPath, operator, 0,
+ mouseButton, xPos, xUnits, yPos, yUnits);
+
+ return null;
+ }
+ });
+
+ waitBeforeDrop(delayBeforeDrop);
+ } finally {
+ getRobot().mouseRelease(null, null, mouseButton);
+ pressOrReleaseModifiers(modifier, false);
+ }
+ }
+
+ /**
+ * Returns the bounds for the figure for the given path. If no such
+ * figure can be found, a {@link StepExecutionException} will be thrown.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @return the bounds of the figure for the given path.
+ */
+ private Rectangle getFigureBoundsChecked(String textPath, String operator) {
+ GraphicalEditPart editPart =
+ findEditPart(textPath, operator);
+ IFigure figure = findFigure(editPart);
+ ConnectionAnchor anchor = null;
+
+ if (figure == null) {
+ // Try to find a connection anchor instead
+ anchor = findConnectionAnchor(textPath, operator);
+ if (anchor != null) {
+ final String[] pathItems = MenuUtil.splitPath(textPath);
+ final String[] editPartPathItems =
+ new String[pathItems.length - 1];
+ System.arraycopy(
+ pathItems, 0, editPartPathItems, 0,
+ editPartPathItems.length);
+ editPart = findEditPart(operator, editPartPathItems);
+ }
+ if (anchor == null || findFigure(editPart) == null) {
+ throw new StepExecutionException(
+ "No figure could be found for the given text path.", //$NON-NLS-1$
+ EventFactory.createActionError(
+ TestErrorEvent.NOT_FOUND));
+ }
+
+ }
+
+ // Scrolling
+ revealEditPart(editPart);
+
+ return figure != null ? getBounds(figure) : getBounds(anchor);
+ }
+
+ /**
+ * Clicks the tool found at the given path.
+ *
+ * @param textPath The path to the tool.
+ * @param operator The operator used for matching.
+ * @param count The number of times to click.
+ */
+ public void gdSelectTool(String textPath, String operator, int count) {
+ Control paletteControl = getPaletteControl();
+ IFigure figure =
+ findPaletteFigureChecked(textPath, operator);
+ getRobot().click(paletteControl, getBounds(figure),
+ ClickOptions.create().setScrollToVisible(false)
+ .setClickCount(count));
+ }
+
+ /**
+ * @return the control associated with the palette viewer.
+ */
+ private Control getPaletteControl() {
+ EditDomain editDomain = getViewer().getEditDomain();
+ if (editDomain == null) {
+ return null;
+ }
+
+ PaletteViewer paletteViewer = editDomain.getPaletteViewer();
+ if (paletteViewer == null) {
+ return null;
+ }
+
+ return paletteViewer.getControl();
+ }
+
+ /**
+ *
+ * @param figure The figure for which to find the bounds.
+ * @return the bounds of the given figure.
+ */
+ private Rectangle getBounds(IFigure figure) {
+ org.eclipse.draw2d.geometry.Rectangle figureBounds =
+ new org.eclipse.draw2d.geometry.Rectangle(figure.getBounds());
+
+ // Take scrolling and zooming into account
+ figure.translateToAbsolute(figureBounds);
+
+ return new Rectangle(
+ figureBounds.x, figureBounds.y,
+ figureBounds.width, figureBounds.height);
+ }
+
+ /**
+ *
+ * @param anchor The anchor for which to find the bounds.
+ * @return the "bounds" of the given anchor. Since the location of an
+ * anchor is defined as a single point, the bounds are a small
+ * rectangle with that point at the center.
+ */
+ private Rectangle getBounds(ConnectionAnchor anchor) {
+ Validate.notNull(anchor);
+ Point refPoint = anchor.getReferencePoint();
+
+ return new Rectangle(
+ refPoint.x - 1, refPoint.y - 1, 3, 3);
+ }
+
+ /**
+ *
+ * @param textPath The path to the GraphicalEditPart.
+ * @param operator The operator used for matching.
+ * @return the GraphicalEditPart for the given path. Returns
+ * <code>null</code> if no EditPart exists for the given path or if
+ * the found EditPart is not a GraphicalEditPart.
+ */
+ private GraphicalEditPart findEditPart(String textPath, String operator) {
+ final String[] pathItems = MenuUtil.splitPath(textPath);
+ return findEditPart(operator, pathItems);
+ }
+
+ /**
+ * @param operator The operator used for matching.
+ * @param pathItems The path to the GraphicalEditPart. Each element in the
+ * array represents a single segment of the path.
+ * @return the GraphicalEditPart for the given path. Returns
+ * <code>null</code> if no EditPart exists for the given path or if
+ * the found EditPart is not a GraphicalEditPart.
+ */
+ private GraphicalEditPart findEditPart(String operator,
+ final String[] pathItems) {
+ boolean isExisting = true;
+ EditPart currentEditPart = getRootEditPart().getContents();
+
+ for (int i = 0; i < pathItems.length && currentEditPart != null; i++) {
+ List effectiveChildren = currentEditPart.getChildren();
+ EditPart [] children =
+ (EditPart [])effectiveChildren.toArray(
+ new EditPart[effectiveChildren.size()]);
+ boolean itemFound = false;
+ for (int j = 0; j < children.length && !itemFound; j++) {
+ IEditPartIdentifier childFigureIdentifier =
+ DefaultEditPartAdapterFactory.loadFigureIdentifier(
+ children[j]);
+ if (childFigureIdentifier != null) {
+ String figureId = childFigureIdentifier.getIdentifier();
+ if (figureId != null
+ && MatchUtil.getInstance().match(
+ figureId, pathItems[i], operator)) {
+ itemFound = true;
+ currentEditPart = children[j];
+ }
+ }
+ }
+ if (!itemFound) {
+ isExisting = false;
+ break;
+ }
+
+ }
+
+ return isExisting && currentEditPart instanceof GraphicalEditPart
+ ? (GraphicalEditPart)currentEditPart : null;
+ }
+
+ /**
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @return the figure for the GraphicalEditPart for the given path within
+ * the palette. Returns <code>null</code> if no EditPart exists
+ * for the given path or if the found EditPart does not have a
+ * figure.
+ */
+ private IFigure findPaletteFigure(String textPath, String operator) {
+ GraphicalEditPart editPart = findPaletteEditPart(textPath, operator);
+
+ // Scrolling
+ revealEditPart(editPart);
+
+ return findFigure(editPart);
+ }
+
+ /**
+ * Finds and returns the palette figure for the given path. If no such
+ * figure can be found, a {@link StepExecutionException} will be thrown.
+ *
+ * @param textPath The path to the figure.
+ * @param operator The operator used for matching.
+ * @return the figure for the GraphicalEditPart for the given path within
+ * the palette.
+ */
+ private IFigure findPaletteFigureChecked(String textPath, String operator) {
+ IFigure figure = findPaletteFigure(textPath, operator);
+ if (figure == null) {
+ throw new StepExecutionException(
+ "No palette figure could be found for the given text path.", //$NON-NLS-1$
+ EventFactory.createActionError(TestErrorEvent.NOT_FOUND));
+ }
+ return figure;
+
+ }
+
+ /**
+ *
+ * @param editPart The EditPart for which to find the corresponding figure.
+ * @return the (visible) figure corresponding to the given EditPart, or
+ * <code>null</code> if no visible figure corresponds to the given
+ * EditPart.
+ */
+ private IFigure findFigure(GraphicalEditPart editPart) {
+ if (editPart != null) {
+ IFigure figure = editPart.getFigure();
+ if (figure.isShowing()) {
+ return figure;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Attempts to find a connection anchor at the given textpath.
+ *
+ * @param textPath The path to the anchor.
+ * @param operator The operator used for matching.
+ * @return the anchor found at the given text path, or <code>null</code>
+ * if no such anchor exists.
+ */
+ private ConnectionAnchor findConnectionAnchor(
+ String textPath, String operator) {
+
+ final String[] pathItems = MenuUtil.splitPath(textPath);
+ final String[] editPartPathItems = new String[pathItems.length - 1];
+ System.arraycopy(
+ pathItems, 0, editPartPathItems, 0, editPartPathItems.length);
+ GraphicalEditPart editPart = findEditPart(operator, editPartPathItems);
+ if (editPart != null) {
+ String anchorPathItem = pathItems[pathItems.length - 1];
+ IEditPartIdentifier editPartIdentifier =
+ DefaultEditPartAdapterFactory.loadFigureIdentifier(editPart);
+ if (editPartIdentifier != null) {
+ Map anchorMap =
+ editPartIdentifier.getConnectionAnchors();
+ if (anchorMap != null) {
+ Iterator anchorMapIter =
+ anchorMap.keySet().iterator();
+ while (anchorMapIter.hasNext()) {
+ Object anchorMapKey = anchorMapIter.next();
+ Object anchorMapValue =
+ anchorMap.get(anchorMapKey);
+ if (anchorMapKey instanceof String
+ && anchorMapValue instanceof ConnectionAnchor
+ && MatchUtil.getInstance().match(
+ (String)anchorMapKey, anchorPathItem,
+ operator)) {
+
+ return (ConnectionAnchor)anchorMapValue;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Reveals the given {@link EditPart} within its viewer.
+ *
+ * @param editPart the {@link EditPart} to reveal.
+ */
+ private void revealEditPart(final EditPart editPart) {
+ if (editPart != null) {
+ getEventThreadQueuer().invokeAndWait(getClass().getName() + ".revealEditPart", new IRunnable() { //$NON-NLS-1$
+
+ public Object run() throws StepExecutionException {
+ editPart.getViewer().reveal(editPart);
+ return null;
+ }
+
+ });
+ }
+ }
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/FigureHighlighter.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/FigureHighlighter.java
new file mode 100644
index 000000000..9d269f799
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/FigureHighlighter.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.inspector;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.jubula.rc.rcp.e3.gef.factory.DefaultEditPartAdapterFactory;
+import org.eclipse.jubula.rc.rcp.e3.gef.identifier.IEditPartIdentifier;
+import org.eclipse.jubula.rc.rcp.e3.gef.util.FigureCanvasUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+
+
+/**
+ * Highlights figures as the mouse moves over them.
+ *
+ * @author BREDEX GmbH
+ * @created Jun 26, 2009
+ */
+public class FigureHighlighter implements MouseMoveListener {
+
+ /** the viewer containing figures that can be highlighted */
+ private GraphicalViewer m_viewer;
+
+ /** the color to use for highlighting */
+ private Color m_highlightColor;
+
+ /** transparency for highlighting */
+ private int m_highlightAlpha;
+
+ /** the current highlighted bounds */
+ private Rectangle m_currentBounds;
+
+ /** the pain listener that performs the actual highlighting */
+ private PaintListener m_paintListener;
+
+ /**
+ * Constructor
+ *
+ * @param viewer The viewer containing figures to highlight.
+ */
+ public FigureHighlighter(GraphicalViewer viewer) {
+ m_viewer = viewer;
+ m_highlightColor =
+ viewer.getControl().getDisplay().getSystemColor(SWT.COLOR_BLUE);
+ m_highlightAlpha = 100;
+ m_currentBounds = null;
+ m_paintListener = new PaintListener() {
+
+ public void paintControl(PaintEvent e) {
+ if (m_currentBounds != null) {
+ Color bgColor = e.gc.getBackground();
+ int alpha = e.gc.getAlpha();
+ e.gc.setAlpha(m_highlightAlpha);
+ e.gc.setBackground(m_highlightColor);
+ e.gc.fillRectangle(m_currentBounds);
+ e.gc.setAlpha(alpha);
+ e.gc.setBackground(bgColor);
+ }
+ }
+
+ };
+ viewer.getControl().addPaintListener(m_paintListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void mouseMove(MouseEvent e) {
+ Point cursorLocation =
+ new Point(e.x, e.y);
+ EditPart editPart =
+ FigureCanvasUtil.findAtCurrentMousePosition(e.display, m_viewer);
+ if (editPart == m_viewer.getContents().getRoot()
+ || editPart == null) {
+ if (m_currentBounds != null) {
+ m_currentBounds = null;
+ m_viewer.getControl().redraw();
+ }
+
+ return;
+ }
+
+ // Check for connection anchor
+ Rectangle anchorBounds =
+ getConnectionAnchorBounds(
+ DefaultEditPartAdapterFactory.loadFigureIdentifier(
+ editPart), cursorLocation);
+
+ if (anchorBounds == null
+ && editPart instanceof ConnectionEditPart) {
+
+ ConnectionEditPart connEditPart =
+ (ConnectionEditPart)editPart;
+ EditPart srcEditPart = connEditPart.getSource();
+ EditPart targetEditPart = connEditPart.getTarget();
+ anchorBounds = getConnectionAnchorBounds(
+ DefaultEditPartAdapterFactory.loadFigureIdentifier(srcEditPart),
+ cursorLocation);
+ if (anchorBounds == null) {
+ anchorBounds = getConnectionAnchorBounds(
+ DefaultEditPartAdapterFactory
+ .loadFigureIdentifier(targetEditPart),
+ cursorLocation);
+ }
+ }
+
+ Rectangle bounds = anchorBounds;
+ if (bounds == null
+ && editPart != m_viewer.getContents().getRoot()
+ && !(editPart instanceof ConnectionEditPart)
+ && editPart instanceof GraphicalEditPart) {
+ IFigure figure = ((GraphicalEditPart)editPart).getFigure();
+ org.eclipse.draw2d.geometry.Rectangle figureBounds =
+ new org.eclipse.draw2d.geometry.Rectangle(figure.getBounds());
+ figure.translateToAbsolute(figureBounds);
+ bounds = new Rectangle(figureBounds.x, figureBounds.y,
+ figureBounds.width, figureBounds.height);
+ }
+ m_currentBounds = bounds;
+ m_viewer.getControl().redraw();
+
+ }
+
+ /**
+ *
+ * @param editPartIdentifier Provides a list of possible anchors.
+ * @param cursorLocation The location at which to look for the anchor.
+ * @return the bounds for the connection anchor at the given location, or
+ * <code>null</code> if no such anchor can be found.
+ */
+ private Rectangle getConnectionAnchorBounds(
+ IEditPartIdentifier editPartIdentifier, Point cursorLocation) {
+
+ if (editPartIdentifier != null) {
+ Map anchorMap =
+ editPartIdentifier.getConnectionAnchors();
+ if (anchorMap != null) {
+ Iterator iter = anchorMap.keySet().iterator();
+ while (iter.hasNext()) {
+ Object key = iter.next();
+ Object value = anchorMap.get(key);
+ if (key instanceof String
+ && value instanceof ConnectionAnchor) {
+ Point refPoint =
+ ((ConnectionAnchor)value).getReferencePoint();
+
+ // The "bounds" of an anchor is considered to be
+ // 3 pixels in all directions.
+ Rectangle refBounds = new Rectangle(
+ refPoint.x - 3, refPoint.y - 3, 7, 7);
+ if (refBounds.contains(cursorLocation.getSWTPoint())) {
+ return refBounds;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Removes all listeners added by this highlighter.
+ */
+ public void removeAddedListeners() {
+ Control control = m_viewer.getControl();
+ if (!control.isDisposed()) {
+ control.removePaintListener(m_paintListener);
+ control.redraw();
+ }
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/GefInspectorListenerAppender.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/GefInspectorListenerAppender.java
new file mode 100644
index 000000000..c880d2f87
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/inspector/GefInspectorListenerAppender.java
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.inspector;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.gef.RootEditPart;
+import org.eclipse.gef.palette.PaletteEntry;
+import org.eclipse.gef.ui.palette.PaletteViewer;
+import org.eclipse.jubula.communication.message.InspectorComponentSelectedMessage;
+import org.eclipse.jubula.rc.common.AUTServer;
+import org.eclipse.jubula.rc.common.listener.IAutListenerAppender;
+import org.eclipse.jubula.rc.common.logger.AutServerLogger;
+import org.eclipse.jubula.rc.rcp.e3.gef.factory.DefaultEditPartAdapterFactory;
+import org.eclipse.jubula.rc.rcp.e3.gef.identifier.IEditPartIdentifier;
+import org.eclipse.jubula.rc.rcp.e3.gef.listener.GefPartListener;
+import org.eclipse.jubula.rc.rcp.e3.gef.util.FigureCanvasUtil;
+import org.eclipse.jubula.tools.exception.CommunicationException;
+import org.eclipse.jubula.tools.objects.ComponentIdentifier;
+import org.eclipse.jubula.tools.objects.IComponentIdentifier;
+import org.eclipse.swt.SWT;
+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.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.PlatformUI;
+
+
+/**
+ * Adds listeners for the Inspector function. These listeners will only
+ * interact with GEF components.
+ *
+ * @author BREDEX GmbH
+ * @created Jun 11, 2009
+ */
+public class GefInspectorListenerAppender implements IAutListenerAppender {
+
+ /** the logger */
+ private static final AutServerLogger LOG =
+ new AutServerLogger(GefInspectorListenerAppender.class);
+
+ /**
+ * Responsible for adding highlighters to controls and managing those
+ * highlighters.
+ *
+ * @author BREDEX GmbH
+ * @created Jun 29, 2009
+ */
+ private static class FigureHighlightAppender implements Listener {
+
+ /** mapping from control to figure highlighter */
+ private Map m_canvasToListener = new HashMap();
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handleEvent(Event event) {
+ if (event.widget instanceof FigureCanvas) {
+ FigureCanvas canvas = (FigureCanvas)event.widget;
+ if (event.type == SWT.MouseEnter) {
+ handleMouseEnter(canvas);
+ }
+ }
+ }
+
+ /**
+ * Removes all listeners added by this appender.
+ */
+ public void removeAddedListeners() {
+ Iterator iter = m_canvasToListener.keySet().iterator();
+ while (iter.hasNext()) {
+ Control control = (Control)iter.next();
+ if (!control.isDisposed()) {
+ FigureHighlighter highlighter =
+ (FigureHighlighter)m_canvasToListener.get(control);
+ highlighter.removeAddedListeners();
+ control.removeMouseMoveListener(highlighter);
+ }
+ }
+ m_canvasToListener.clear();
+ }
+
+ /**
+ * Adds a figure highlighter to the given canvas.
+ *
+ * @param canvas The figure canvas entered by the mouse.
+ */
+ private void handleMouseEnter(final FigureCanvas canvas) {
+ if (m_canvasToListener.containsKey(canvas)) {
+ // Highlighter already registered.
+ return;
+ }
+
+ GraphicalViewer viewer = FigureCanvasUtil.getViewer(canvas);
+ if (viewer != null) {
+ if (viewer.getContents() instanceof GraphicalEditPart) {
+ FigureHighlighter highlighter =
+ new FigureHighlighter(viewer);
+ m_canvasToListener.put(canvas, highlighter);
+ canvas.addMouseMoveListener(highlighter);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Listens for a mouse click and:
+ * 1. deregisters itself and any other provider listeners, and
+ * 2. sends a "component selected" message
+ *
+ * if that mouse click was over a GEF component.
+ *
+ * @author BREDEX GmbH
+ * @created Jun 11, 2009
+ */
+ private static class GefInspectorComponentSelectedListener
+ implements Listener {
+
+ /** the appender */
+ private FigureHighlightAppender m_highlightAppender;
+
+ /**
+ * Constructor
+ *
+ * @param highlightAppender The appender to use.
+ */
+ public GefInspectorComponentSelectedListener(
+ FigureHighlightAppender highlightAppender) {
+ m_highlightAppender = highlightAppender;
+ }
+
+ /**
+ *
+ * @param editPartIdentifier Provides connection anchor IDs and
+ * locations.
+ * @param cursorLocation The location at which to search for an
+ * anchor point.
+ * @return the ID of the connection anchor at the given location, or
+ * <code>null</code> if there is no connection anchor at the
+ * given location.
+ */
+ private String getConnectionAnchorId(
+ IEditPartIdentifier editPartIdentifier, Point cursorLocation) {
+
+ if (editPartIdentifier != null) {
+ Map anchorMap =
+ editPartIdentifier.getConnectionAnchors();
+ if (anchorMap != null) {
+ Iterator iter = anchorMap.keySet().iterator();
+ while (iter.hasNext()) {
+ Object key = iter.next();
+ Object value = anchorMap.get(key);
+ if (key instanceof String
+ && value instanceof ConnectionAnchor) {
+ Point refPoint =
+ ((ConnectionAnchor)value).getReferencePoint();
+
+ // A click is recognized as being "within the
+ // bounds" of an anchor if it is within 3 pixels
+ // in any direction.
+ Rectangle refBounds = new Rectangle(
+ refPoint.x - 3, refPoint.y - 3, 7, 7);
+ if (refBounds.contains(cursorLocation)) {
+ return (String)key;
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void handleEvent(Event event) {
+ Display display = event.display;
+ display.removeFilter(SWT.MouseDown, this);
+ display.removeFilter(SWT.MouseEnter, m_highlightAppender);
+ m_highlightAppender.removeAddedListeners();
+ event.doit = false;
+ event.type = SWT.None;
+ Widget selectedWidget = event.widget;
+ IComponentIdentifier compId = null;
+
+ if (!(selectedWidget instanceof FigureCanvas)) {
+ sendIdInfo(compId);
+ return;
+ }
+
+ FigureCanvas figureCanvas =
+ (FigureCanvas)selectedWidget;
+ Composite parent = figureCanvas;
+ while (parent != null
+ && !(parent.getData(
+ GefPartListener.TEST_GEF_VIEWER_DATA_KEY)
+ instanceof GraphicalViewer)) {
+ parent = parent.getParent();
+ }
+
+ if (parent == null) {
+ sendIdInfo(compId);
+ return;
+ }
+
+ Object gefData =
+ parent.getData(GefPartListener.TEST_GEF_VIEWER_DATA_KEY);
+
+ if (gefData instanceof EditPartViewer) {
+ EditPartViewer viewer = (EditPartViewer)gefData;
+ Point cursorLocation = new Point(display.map(null,
+ viewer.getControl(),
+ display.getCursorLocation()));
+ EditPart editPart = viewer.findObjectAt(cursorLocation);
+ EditPart primaryEditPart = FigureCanvasUtil.getPrimaryEditPart(
+ editPart, viewer.getRootEditPart());
+ List idStringList = Collections.EMPTY_LIST;
+
+ if (primaryEditPart != null) {
+ idStringList = getPathToRoot(viewer.getRootEditPart(),
+ cursorLocation, primaryEditPart);
+
+ } else {
+ // No primary figure found.
+ // Check whether a tool was selected.
+ EditDomain editDomain = viewer.getEditDomain();
+ if (editDomain != null) {
+ PaletteViewer paletteViewer =
+ editDomain.getPaletteViewer();
+ if (paletteViewer != null) {
+ EditPart paletteEditPart =
+ paletteViewer.findObjectAt(new Point(
+ display.map(viewer.getControl(),
+ paletteViewer.getControl(),
+ cursorLocation.getSWTPoint())));
+ if (paletteEditPart != null) {
+ idStringList = getToolPathToRoot(
+ paletteViewer.getRootEditPart(),
+ paletteEditPart);
+ }
+ }
+ }
+ }
+
+ compId = createCompId(idStringList);
+ }
+ sendIdInfo(compId);
+ }
+
+ /**
+ *
+ * @param editPart The edit part for which to find the path.
+ * @param root The root for <code>editPart</code>. This is used to
+ * avoid adding the root identifier to the returned list.
+ * @param cursorLocation The location to check for nearby connection
+ * anchors.
+ * @return a list containing the identifier of each edit part between
+ * <code>editPart</code> and its root. The first element in the
+ * list will be the identifier for a connection anchor if
+ * <code>cursorLocation</code> is near such an anchor.
+ */
+ private List getPathToRoot(RootEditPart root, Point cursorLocation,
+ EditPart editPart) {
+
+ List idStringList = new ArrayList();
+ EditPart currentEditPart = editPart;
+
+ // Check for connection anchor
+ String connectionId =
+ getConnectionAnchorId(
+ DefaultEditPartAdapterFactory.loadFigureIdentifier(
+ currentEditPart),
+ cursorLocation);
+
+ if (connectionId == null
+ && currentEditPart instanceof ConnectionEditPart) {
+
+ ConnectionEditPart connEditPart =
+ (ConnectionEditPart)editPart;
+ EditPart srcEditPart = connEditPart.getSource();
+ EditPart targetEditPart = connEditPart.getTarget();
+ connectionId = getConnectionAnchorId(
+ DefaultEditPartAdapterFactory
+ .loadFigureIdentifier(srcEditPart),
+ cursorLocation);
+ if (connectionId != null) {
+ currentEditPart = srcEditPart;
+ } else {
+ connectionId = getConnectionAnchorId(
+ DefaultEditPartAdapterFactory
+ .loadFigureIdentifier(targetEditPart),
+ cursorLocation);
+ if (connectionId != null) {
+ currentEditPart = targetEditPart;
+ }
+ }
+ }
+
+ if (connectionId != null) {
+ idStringList.add(connectionId);
+ }
+
+ while (currentEditPart != root.getContents()
+ && currentEditPart != null) {
+ IEditPartIdentifier identifier =
+ DefaultEditPartAdapterFactory.loadFigureIdentifier(
+ currentEditPart);
+ if (identifier != null) {
+ idStringList.add(identifier.getIdentifier());
+ }
+ currentEditPart = currentEditPart.getParent();
+ }
+
+ return idStringList;
+
+ }
+
+ /**
+ *
+ * @param editPart The edit part for which to find the path.
+ * @param root The root for <code>editPart</code>. This is used to
+ * avoid adding the root identifier to the returned list.
+ * @return a list containing the identifier of each edit part between
+ * <code>editPart</code> and its root.
+ */
+ private List getToolPathToRoot(RootEditPart root, EditPart editPart) {
+
+ List idStringList = new ArrayList();
+ EditPart currentEditPart = editPart;
+
+ if (currentEditPart != null) {
+ Object model = currentEditPart.getModel();
+ while (model instanceof PaletteEntry
+ && currentEditPart != root.getContents()) {
+ idStringList.add(((PaletteEntry)model).getLabel());
+ currentEditPart =
+ currentEditPart.getParent();
+ model = currentEditPart.getModel();
+ }
+ }
+
+ return idStringList;
+ }
+
+ /**
+ * Sends the given ID information to the client.
+ *
+ * @param compId The component identifier to send. May be
+ * <code>null</code>.
+ */
+ private void sendIdInfo(IComponentIdentifier compId) {
+ InspectorComponentSelectedMessage message =
+ new InspectorComponentSelectedMessage();
+ message.setComponentIdentifier(compId);
+ try {
+ AUTServer.getInstance().getCommunicator().send(message);
+ } catch (CommunicationException e) {
+ LOG.error("Error occurred while trying to send message to Client.", e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ *
+ * @param idStringList The path to root for a specific edit part or
+ * connection anchor.
+ * @return a component identifier for the given path, or
+ * <code>null</code> if no valid component identifier can be
+ * generated.
+ */
+ private IComponentIdentifier createCompId(List idStringList) {
+ IComponentIdentifier compId = null;
+ if (!idStringList.isEmpty()) {
+ Collections.reverse(idStringList);
+ compId = new ComponentIdentifier();
+ compId.setHierarchyNames(idStringList);
+ }
+
+ return compId;
+ }
+ }
+
+ /** the listener responsible for appending highlight listeners */
+ private FigureHighlightAppender m_highlightAppender;
+
+ /** the listener responsible for handling mouse clicks */
+ private GefInspectorComponentSelectedListener m_componentSelectedListener;
+
+ /**
+ * Constructor
+ */
+ public GefInspectorListenerAppender() {
+ m_highlightAppender = new FigureHighlightAppender();
+ m_componentSelectedListener =
+ new GefInspectorComponentSelectedListener(m_highlightAppender);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addAutListener() {
+ final Display display = PlatformUI.getWorkbench().getDisplay();
+
+ display.syncExec(new Runnable() {
+
+ public void run() {
+ display.addFilter(SWT.MouseEnter, m_highlightAppender);
+ display.addFilter(SWT.MouseDown, m_componentSelectedListener);
+ }
+
+ });
+ }
+
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/listener/GefPartListener.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/listener/GefPartListener.java
new file mode 100644
index 000000000..5f0bc71b8
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/listener/GefPartListener.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.listener;
+
+import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IPartListener2;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartReference;
+import org.eclipse.ui.internal.WorkbenchPartReference;
+import org.eclipse.ui.part.MultiPageEditorPart;
+
+
+/**
+ * @author BREDEX GmbH
+ * @created Dec 17, 2009
+ */
+public class GefPartListener implements IPartListener2 {
+
+ /** Key for GEF Viewer in component data */
+ public static final String TEST_GEF_VIEWER_DATA_KEY = "TEST_GEF_VIEWER"; //$NON-NLS-1$
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partActivated(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partBroughtToTop(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partClosed(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partDeactivated(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partHidden(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partInputChanged(IWorkbenchPartReference partRef) {
+ // Do nothing
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partOpened(final IWorkbenchPartReference partRef) {
+ IWorkbenchPart part = partRef.getPart(false);
+
+ if (part instanceof MultiPageEditorPart) {
+ ((MultiPageEditorPart)part).getSite().getSelectionProvider()
+ .addSelectionChangedListener(new ISelectionChangedListener() {
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (event.getSource() instanceof GraphicalViewer) {
+ registerGraphicalViewer(
+ (GraphicalViewer)event.getSource(), partRef);
+ }
+ }
+ });
+ }
+
+ if (part != null
+ && partRef instanceof WorkbenchPartReference) {
+ GraphicalViewer viewer =
+ (GraphicalViewer)part.getAdapter(
+ GraphicalViewer.class);
+ registerGraphicalViewer(viewer, partRef);
+ }
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ public void partVisible(IWorkbenchPartReference partRef) {
+ partOpened(partRef);
+ }
+
+ /**
+ * Registers a {@link GraphicalViewer} with the given
+ * {@link IWorkbenchPartReference}.
+ *
+ * @param viewer The viewer to register.
+ * @param partRef The reference to the part that (indirectly) contains the
+ * viewer.
+ */
+ private void registerGraphicalViewer(GraphicalViewer viewer,
+ IWorkbenchPartReference partRef) {
+
+ IWorkbenchPart part = partRef.getPart(false);
+ if (part != null && partRef instanceof WorkbenchPartReference) {
+ if (viewer != null) {
+ // Note the viewer on the component
+ Control partContent =
+ ((WorkbenchPartReference)partRef).getPane().getControl();
+
+ if (partContent != null && !partContent.isDisposed()) {
+ partContent.setData(
+ GefPartListener.TEST_GEF_VIEWER_DATA_KEY,
+ viewer);
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/util/FigureCanvasUtil.java b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/util/FigureCanvasUtil.java
new file mode 100644
index 000000000..be2816202
--- /dev/null
+++ b/org.eclipse.jubula.rc.rcp.e3/src/org/eclipse/jubula/rc/rcp/e3/gef/util/FigureCanvasUtil.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 BREDEX GmbH.
+ * 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:
+ * BREDEX GmbH - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.jubula.rc.rcp.e3.gef.util;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.gef.RootEditPart;
+import org.eclipse.jubula.rc.rcp.e3.gef.factory.DefaultEditPartAdapterFactory;
+import org.eclipse.jubula.rc.rcp.e3.gef.identifier.IEditPartIdentifier;
+import org.eclipse.jubula.rc.rcp.e3.gef.listener.GefPartListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+
+/**
+ * Utility class for interacting with a FigureCanvas.
+ *
+ * @author BREDEX GmbH
+ * @created Jun 26, 2009
+ */
+public class FigureCanvasUtil {
+
+ /**
+ * Private constructor
+ */
+ private FigureCanvasUtil() {
+ // Nothing to initialize
+ }
+
+ /**
+ *
+ * @param figureCanvas
+ * The canvas for which to find the viewer.
+ * @return the graphical viewer associated with the given canvas, or
+ * <code>null</code> if no such viewer could be found.
+ */
+ public static GraphicalViewer getViewer(FigureCanvas figureCanvas) {
+ Composite parent = figureCanvas;
+ while (parent != null
+ && !(parent.getData(GefPartListener.TEST_GEF_VIEWER_DATA_KEY)
+ instanceof GraphicalViewer)) {
+ parent = parent.getParent();
+ }
+
+ if (parent != null) {
+
+ return (GraphicalViewer)parent
+ .getData(GefPartListener.TEST_GEF_VIEWER_DATA_KEY);
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ * @param display The display containing the edit part to find.
+ * @param viewer The viewer containing the edit part to find.
+ * @return the edit part for the viewer at the current mouse pointer
+ * coordinates, or <code>null</code> if no such edit part can be
+ * found.
+ */
+ public static EditPart findAtCurrentMousePosition(
+ Display display, EditPartViewer viewer) {
+ Point cursorLocation = new Point(display.map(null, viewer.getControl(),
+ display.getCursorLocation()));
+ EditPart editPart = viewer.findObjectAt(cursorLocation);
+ EditPart primaryEditPart = getPrimaryEditPart(editPart, viewer
+ .getRootEditPart());
+
+ return primaryEditPart;
+ }
+
+ /**
+ * Searches the path to root for the first element considered to be testable
+ * by Jubula. Testable in this case means that an ID can be acquired for
+ * the edit part.
+ *
+ * @param editPart
+ * The starting edit part.
+ * @param root
+ * The root for <code>editPart</code>. This is used to avoid
+ * identifying the root edit part as the primary edit part.
+ * @return the first edit part on the path to root that has an ID.
+ */
+ public static EditPart getPrimaryEditPart(final EditPart editPart,
+ RootEditPart root) {
+
+ EditPart currentEditPart = editPart;
+
+ while (currentEditPart != root.getContents()
+ && currentEditPart != null) {
+ IEditPartIdentifier identifier = DefaultEditPartAdapterFactory
+ .loadFigureIdentifier(currentEditPart);
+ if (identifier != null) {
+ return currentEditPart;
+ }
+ currentEditPart = currentEditPart.getParent();
+ }
+
+ return null;
+ }
+
+}

Back to the top