/*******************************************************************************
 * Copyright (c) 2009, 2020 Xored Software Inc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *     Xored Software Inc - initial API and implementation and/or initial documentation
 *******************************************************************************/
package org.eclipse.rcptt.tesla.recording.core.swt;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.bindings.Binding;
import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckboxCellEditor;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.rcptt.tesla.core.am.RecordingModeFeature;
import org.eclipse.rcptt.tesla.core.context.ContextManagement;
import org.eclipse.rcptt.tesla.core.context.ContextManagement.Context;
import org.eclipse.rcptt.tesla.core.protocol.Click;
import org.eclipse.rcptt.tesla.core.protocol.CompositeUIElement;
import org.eclipse.rcptt.tesla.core.protocol.ControlUIElement;
import org.eclipse.rcptt.tesla.core.protocol.ElementKind;
import org.eclipse.rcptt.tesla.core.protocol.LinkUIElement;
import org.eclipse.rcptt.tesla.core.protocol.MouseEvent;
import org.eclipse.rcptt.tesla.core.protocol.MouseEventKind;
import org.eclipse.rcptt.tesla.core.protocol.PartUIElement;
import org.eclipse.rcptt.tesla.core.protocol.ProtocolFactory;
import org.eclipse.rcptt.tesla.core.protocol.SWTDialogKind;
import org.eclipse.rcptt.tesla.core.protocol.SelectCommand;
import org.eclipse.rcptt.tesla.core.protocol.SelectData;
import org.eclipse.rcptt.tesla.core.protocol.SetSWTDialogInfo;
import org.eclipse.rcptt.tesla.core.protocol.SetSelection;
import org.eclipse.rcptt.tesla.core.protocol.SetTextOffset;
import org.eclipse.rcptt.tesla.core.protocol.SetTextSelection;
import org.eclipse.rcptt.tesla.core.protocol.TextUIElement;
import org.eclipse.rcptt.tesla.core.protocol.Type;
import org.eclipse.rcptt.tesla.core.protocol.ViewerUIElement;
import org.eclipse.rcptt.tesla.core.protocol.raw.Command;
import org.eclipse.rcptt.tesla.core.protocol.raw.RawEvent;
import org.eclipse.rcptt.tesla.core.protocol.raw.RawFactory;
import org.eclipse.rcptt.tesla.core.protocol.raw.SetMode;
import org.eclipse.rcptt.tesla.core.utils.TeslaUtils;
import org.eclipse.rcptt.tesla.internal.core.TeslaCore;
import org.eclipse.rcptt.tesla.internal.ui.player.FindResult;
import org.eclipse.rcptt.tesla.internal.ui.player.ISWTModelMapperExtension;
import org.eclipse.rcptt.tesla.internal.ui.player.PlayerTextUtils;
import org.eclipse.rcptt.tesla.internal.ui.player.SWTModelMapper;
import org.eclipse.rcptt.tesla.internal.ui.player.SWTUIElement;
import org.eclipse.rcptt.tesla.internal.ui.player.SWTUIPlayer;
import org.eclipse.rcptt.tesla.internal.ui.player.TeslaSWTAccess;
import org.eclipse.rcptt.tesla.internal.ui.player.viewers.Viewers;
import org.eclipse.rcptt.tesla.recording.aspects.IExtendedSWTEventListener;
import org.eclipse.rcptt.tesla.recording.aspects.SWTEventManager;
import org.eclipse.rcptt.tesla.recording.core.IRecordingHelper;
import org.eclipse.rcptt.tesla.recording.core.IRecordingModeListener;
import org.eclipse.rcptt.tesla.recording.core.IRecordingProcessor;
import org.eclipse.rcptt.tesla.recording.core.IRecordingProcessorExtension;
import org.eclipse.rcptt.tesla.recording.core.TeslaRecorder;
import org.eclipse.rcptt.tesla.recording.core.swt.peg.CommandPostProcessor;
import org.eclipse.rcptt.tesla.recording.core.swt.util.LastEvents;
import org.eclipse.rcptt.tesla.recording.core.swt.util.RecordedEvent;
import org.eclipse.rcptt.tesla.swt.workbench.EclipseWorkbenchProvider;
import org.eclipse.rcptt.util.swt.StringLines;
import org.eclipse.rcptt.util.swt.TableTreeUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.SWTEventListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.CoolItem;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Slider;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.TypedListener;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchPage;
import org.eclipse.ui.keys.IBindingService;
import org.osgi.framework.Bundle;

/**
 * Simple event collector Each used widget will be added as variable.
 *
 */
@SuppressWarnings("restriction")
public class SWTEventRecorder implements IRecordingProcessor, IExtendedSWTEventListener, IRecordingModeListener {
	// private Map<Widget, String> variables = new HashMap<Widget, String>();
	// private Map<String, Integer> varCounters = new HashMap<String,
	// Integer>();

	private LastEvents lastEvents = new LastEvents();

	private boolean enabled = true;
	private final IPartListener listener;
	private final IPageListener pageListener;
	private final IWindowListener windowListener;
	private String beforeTextState = null;
	private DNDSupport dragSupport;
	private final Map<Widget, String> lastTabItemSelection = new HashMap<Widget, String>();
	private final Set<String> pressed = new HashSet<String>();
	private boolean inStyledTextAction = false;
	private Event currentEvent;

	private final class PartListener implements IPartListener {

		public void partOpened(IWorkbenchPart part) {
		}

		public void partDeactivated(IWorkbenchPart part) {
		}

		public void partClosed(IWorkbenchPart part) {
			if (getLocator().getRecorder() == null) {
				return;
			}
			if (!getRecorder().hasListeners()) {
				return;
			}
			Context context = ContextManagement.currentContext();
			// TODO: This is Eclipse version dependent test
			if (!context.contains("org.eclipse.swt.custom.CTabFolder", "onMouse")) {
				return;
			}
			if (!TeslaCore.isEclipse4()) {
				// Skip for editors, will be done from different place.
				if (part instanceof IEditorPart) {
					return;
				}
			}
			Display display = PlatformUI.getWorkbench().getDisplay();
			Shell[] shells = display.getShells();
			for (Shell shell : shells) {
				if (isModal(shell)) {
					return;
				}
			}
			PartUIElement resultPart = getLocator().findPartElement(part, false);
			if (resultPart != null) {
				resultPart.close();
			}
		}

		public void partBroughtToTop(IWorkbenchPart part) {
		}

		public void partActivated(IWorkbenchPart part) {
			if (getRecorder() == null) {
				return;
			}
			if (!getRecorder().hasListeners()) {
				return;
			}
			boolean hashMouseUp = false;
			Context context = ContextManagement.currentContext();

			if (context.contains("org.eclipse.swt.custom.CTabFolder", "onMouse")) {
				hashMouseUp = true;
			}
			if (!hashMouseUp) {
				StackTraceElement[] stack = context.getStackTrace();
				for (StackTraceElement e : stack) {
					if (e.getMethodName().equals("mouseUp") || e.getMethodName().equals("handleEvent")
							|| e.getMethodName().equals("activate")) {
						String className = e.getClassName();
						int dollarPos = className.indexOf('$');
						if (dollarPos > 0)
							className = className.substring(0, dollarPos);
						if ("org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer".equals(className)) {
							hashMouseUp = true;
							break;
						}
					}
				}
			}
			if (!hashMouseUp) {
				return;// Skip, because not used click
			}

			if (context.contains("org.eclipse.ui.internal.WorkbenchPage", "hideView"))

			{
				// View was activated programmatically, so ignore.
				return;
			}
			Display display = PlatformUI.getWorkbench().getDisplay();
			Shell[] shells = display.getShells();
			for (Shell shell : shells) {
				if (isModal(shell)) {
					return;
				}
			}

			PartUIElement resultPart = getLocator().findPartElement(part, false);
			if (resultPart != null) {
				resultPart.click();
			}
		}

	}

	public SWTWidgetLocator getLocator() {
		return SWTRecordingHelper.getHelper().getLocator();
	}

	public static boolean isModal(Shell shell) {
		int style = shell.getStyle();
		int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL | SWT.MODELESS;
		String text = shell.getText();
		if (text != null && (text.trim().equalsIgnoreCase("problem occurred")
				|| text.trim().equalsIgnoreCase("Operation failed"))) {
			return true;
		}
		return (style & mask) > 0;
	}

	public TeslaRecorder getRecorder() {
		return recorder;
	}

	public SWTEventRecorder() {
		super();
		dragSupport = new DNDSupport();
		listener = new PartListener();

		pageListener = new IPageListener() {

			public void pageOpened(IWorkbenchPage page) {
				page.addPartListener(listener);
			}

			public void pageClosed(IWorkbenchPage page) {
			}

			public void pageActivated(IWorkbenchPage page) {
				page.addPartListener(listener);
			}
		};
		windowListener = new IWindowListener() {

			public void windowOpened(IWorkbenchWindow window) {
				window.addPageListener(pageListener);
				IWorkbenchPage[] pages = window.getPages();
				for (IWorkbenchPage page : pages) {
					page.addPartListener(listener);
				}
			}

			public void windowDeactivated(IWorkbenchWindow window) {
			}

			public void windowClosed(IWorkbenchWindow window) {
			}

			public void windowActivated(IWorkbenchWindow window) {
				window.addPageListener(pageListener);
			}
		};
		IWorkbench workbench = PlatformUI.getWorkbench();
		workbench.addWindowListener(windowListener);
		IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
		for (IWorkbenchWindow win : windows) {
			win.addPageListener(pageListener);
			IWorkbenchPage[] pages = win.getPages();
			for (IWorkbenchPage page : pages) {
				page.addPartListener(listener);
			}
		}

		SWTEventManager.addListener(this);
		// JFaceEventManager.addListener(this);
		// WorkbenchEventManager.addListener(this);
		// FormsEventManager.addListener(this);
	}

	private void enable() {
		enabled = true;
	}

	public boolean doProcessing(Context context, boolean contextChanged) {
		return false;
	}

	private Event lastEvent = null;

	public synchronized void recordEvent(Widget widget, int type, Event event) {
		if (getRecorder() == null) {
			return;
		}
		if (!getRecorder().hasListeners()) {
			return;
		}
		if (!enabled) {
			enable();
		}

		if (type == SWT.KeyDown || type == SWT.KeyUp) {
			keysSeen = true;

			if (type == SWT.KeyUp) {
				if (lastTraverseEvent != null) {
					RecordedEvent toRecordingTraverse = new RecordedEvent(getPlayer(), event, type, widget);
					lastTraverseEvent.detail = lastTraverseDetail;

					// Don't record traverse events for Browser - key pressing
					// recorded on KeyUp event
					if (!(widget instanceof Browser)) {
						addToPressed(lastTraverseEvent);
						processTraverse(lastTraverseEvent.widget, lastTraverseEvent, toRecordingTraverse);
						lastEvents.add(toRecordingTraverse);
					}
					lastTraverseEvent = null;
				}
			}
		}

		// fix of fix on Windows, see
		// org.eclipse.swt.widgets.Text.setText(String)
		if (type == SWT.Modify && widget instanceof Text && Platform.getOS().equals(Platform.OS_WIN32)) {
			Text text = (Text) widget;
			if ((text.getStyle() & SWT.MULTI) != 0
					&& ContextManagement.currentContext().contains("org.eclipse.swt.widgets.Text", "setText"))
				return;
		}

		// Check for extension to ignore recording against one of controls
		List<IRecordingProcessorExtension> list = getRecorder().getProcessors(IRecordingProcessorExtension.class);
		for (IRecordingProcessorExtension ext : list) {
			if (ext.isIgnored(widget, type, event)) {
				return;
			}
		}

		if (isIgnored(widget)) {
			return;
		}
		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			if (event != null && lastEvent != null) {
				if (event.time == lastEvent.time && event.widget == lastEvent.widget && event.type == lastEvent.type) {
					// Same event captured twice
					// System.out.println("ALREADY_PROCESSED_EVENT");
					return;
				}
			}
		}

		if (widget instanceof Menu && type == SWT.Show) {
			// special case when menu is shown on MouseDown, so we can not
			// record click properly on "some" platforms

			if (lastEvent != null && lastEvent.widget instanceof Button && lastEvent.type == SWT.MouseDown) {
				SWTEventManager.setMenuSource((Menu) widget, lastEvent.widget);

				if (!Platform.getOS().equals(Platform.OS_MACOSX)) {
					// it is recorded on Mac "automatically"
					FindResult result = getLocator().findElement(lastEvent.widget, false, false, true);
					if (result != null) {
						ControlUIElement e = new ControlUIElement(result.element, getRecorder());
						e.clickAndWait();
					}
				}
			} else if (lastEvent != null && lastEvent.widget instanceof Button && lastEvent.type == SWT.Selection) {
				SWTEventManager.setMenuSource((Menu) widget, lastEvent.widget);
			}
		}

		if (event != null)
			lastEvent = event;

		recordRawEvent(widget, type, event);
		recordEvent_(widget, type, event);
	}

	private void recordRawEvent(Widget widget, int type, Event event) {
		if (!getRecorder().isRawEventsEnabled()) {
			return;
		}
		// Record raw event
		RawEvent rawEvent = RawFactory.eINSTANCE.createRawEvent();
		rawEvent.setType(type);
		if (event != null) {
			rawEvent.setButton(event.button);
			rawEvent.setCharacter(event.character);
			rawEvent.setCount(event.count);
			rawEvent.setData(event.data == null ? null : event.data.toString());
			rawEvent.setDetail(event.detail);
			rawEvent.setEnd(event.end);
			rawEvent.setHeight(event.height);
			rawEvent.setIndex(event.index);
			rawEvent.setKeyCode(event.keyCode);
			rawEvent.setStart(event.start);
			rawEvent.setStateMask(event.stateMask);
			if (event.text != null) {
				String textValue = event.text;
				StringBuilder textResult = new StringBuilder();
				for (char c : textValue.toCharArray()) {
					if (!Character.isLetterOrDigit(c) && !Character.isWhitespace(c)) {
						textResult.append(' ');
					} else {
						textResult.append(c);
					}
				}
				rawEvent.setText(textResult.toString());
			}
			rawEvent.setTime(event.time);
			rawEvent.setWidth(event.width);
			rawEvent.setX(event.x);
			rawEvent.setY(event.y);
			rawEvent.getItem().add(getLocator().getWidgetID(event.item));
			rawEvent.setNativeEvent(!isNotNative(widget));
		}
		rawEvent.getWidget().add(getLocator().getWidgetID(widget));

		getRecorder().addRawEvent(rawEvent);
	}

	public boolean isIgnored(Widget widget) {
		Shell[] ignored = getPlayer().getIgnored();
		if (ignored == null) {
			return false;
		}
		Shell s = null;
		if (widget instanceof Control) {
			s = ((Control) widget).getShell();
		}
		if (widget instanceof MenuItem) {
			s = ((MenuItem) widget).getParent().getShell();
		}
		if (widget instanceof Menu) {
			s = ((Menu) widget).getShell();
		}
		if (widget instanceof ToolItem) {
			s = ((ToolItem) widget).getParent().getShell();
		}
		if (s != null) {
			for (Shell shell : ignored) {
				if (shell == s) {
					return true;
				}
			}
		}

		return false;
	}

	public SWTUIPlayer getPlayer() {
		return getLocator().getPlayer();
	}

	public static boolean keysSeen = false;
	public static Event lastTraverseEvent = null;
	public static int lastTraverseDetail = 0;

	private void recordEvent_(Widget widget, int type, Event event) {
		if (type == DND.DragStart || type == DND.DragEnd || type == DND.DragEnter || type == DND.DragOver
				|| type == DND.DragLeave || type == DND.Drop || type == DND.DragOperationChanged
				|| type == DND.DropAccept || type == DND.DragSetData) {
			if (event.widget == null) {
				event.widget = widget;
			}
			event.type = type;
			recordDragEvent(event);
			return;
		}
		RecordedEvent toRecording = new RecordedEvent(getPlayer(), event, type, widget);

		if (type == SWT.Show && widget instanceof Menu) {
			processMenuShow(widget, toRecording);
		} else if (type == SWT.Hide && widget instanceof Menu) {
			// menuSources.remove(widget);
			lastEvents.add(toRecording);
		}
		Context ctx = ContextManagement.currentContext();
		// Filter not window proc contexts

		if (isNotNative(widget)) {
			return;
		}

		// Check and ignore DataTime subcontrol events, exclusive to
		// SWT.Selection
		if (widget instanceof Control) {
			Control c = (Control) widget;
			if (c.getParent() instanceof DateTime) {
				processDateTime(c.getParent(), c, type, event);
				return;
			} else if (c instanceof DateTime) {
				processDateTime(c, c, type, event);
				return;
			}
		}

		// Check for ccombo based items
		CCombo[] combo = SWTEventManager.getCombo();
		for (CCombo cCombo : combo) {
			if (CComboSupport.isComboWidget(cCombo, widget)) {
				processCCombo(widget, cCombo, type, event);
				return;
			}
		}
		if (widget instanceof CCombo) {
			return; // Set text will be recorded elsewhere
		}

		if (isCanvas(widget, type)) {
			return;
		}
		if ((type == SWT.Selection || type == SWT.DefaultSelection)) {
			processSelection(widget, event, type, ctx);
		} else if (type == SWT.Modify && isSimpleTextControl(widget)) {
			// TODO: In case of combo update called from tree selection, we need
			// to make sure of correct flow filtering.
			if (ctx.contains("org.eclipse.swt.widgets.Combo", "removeAll")
					|| ctx.contains("org.eclipse.swt.widgets.Combo", "setItems")
					|| ctx.contains("org.eclipse.swt.widgets.Combo", "deselectAll")
					|| ctx.contains("org.eclipse.swt.widgets.Combo", "select")
					|| ctx.contains("org.eclipse.swt.widgets.Combo", "setText")
					|| ctx.contains("org.eclipse.jface.internal.databinding.swt.TextTextProperty", "doSetStringValue")
					|| ctx.contains("org.eclipse.swt.widgets.Text", "paste")) {
				return;
			}
			processModify(widget);
		} else if (type == SWT.Activate) {
			lastEvents.add(toRecording);
			// processActivateEvent(widget, toRecording);
		} else if (type == SWT.Deactivate) {
			lastEvents.add(toRecording);
		} else if (type == SWT.MouseUp) {
			processMouseUp(widget, event, toRecording);
		} else if (type == SWT.MouseDown) {
			processMouseDown(widget, event, toRecording);
		} else if (type == SWT.KeyDown) {
			if (ctx.contains("com.xored.swt.internal.composer.GeckoEditor$KeyAdapter", "handleEvent")) {
				return; // this event is duplicate, see QS-882
			}

			if (widget instanceof Combo)
				return;

			addToPressed(event);
			processKeyDown(widget, event);

			lastEvents.add(toRecording);
		} else if (type == SWT.KeyUp) {
			if (ctx.contains("com.xored.swt.internal.composer.GeckoEditor$KeyAdapter", "handleEvent")) {
				return; // this event is duplicate, see QS-882
			}

			if (widget instanceof Combo)
				return;

			String v = KeyStroke.getInstance(event.stateMask, event.keyCode).toString().toLowerCase();
			String[] values = v.split("\\+");
			boolean contains = false;
			for (String val : values) {
				if (pressed.contains(val)) {
					contains = true;
				}
			}
			// On MacOSX after press Enter in dialog with default selection,
			// no
			// KeyDown and Traverse event but unnecessary KeyUp
			boolean isEnterOnMac = Platform.getOS().equals(Platform.OS_MACOSX) && (event.character == SWT.CR)
					&& event.stateMask == 0;

			if (!contains && !isEnterOnMac) {
				// This is just key-up event
				processKeyDown(widget, event);
			}
			for (String val : values) {
				pressed.remove(val);
			}

			if (isSimpleTextControl(widget)) {
				beforeTextState = null;
			}

			lastEvents.add(toRecording);
			// }
		} else if (type == SWT.Traverse) {
			keysSeen = false;

			if (event.detail != SWT.TRAVERSE_PAGE_NEXT && event.detail != SWT.TRAVERSE_PAGE_PREVIOUS) {
				// Don't record traverse events for Browser - key pressing
				// recorded on KeyUp event
				if (!(widget instanceof Browser)) {
					addToPressed(event);
					processTraverse(widget, event, toRecording);
					lastEvents.add(toRecording);
				}
			} else if (event.detail != SWT.TRAVERSE_NONE) {
				event.widget = widget;
				lastTraverseEvent = event;
				lastTraverseDetail = event.detail;
			}
		} else if (type == SWT.MouseDoubleClick) {
			Listener[] listeners = widget.getListeners(SWT.MouseDoubleClick);
			if (listeners.length != 0 && !(widget instanceof ViewForm) && !(widget instanceof Sash)) {
				FindResult result = getLocator().findElement(widget, true, false, false);

				// System.out.println("RESULT is:" + result);
				if (result != null && result.element != null) {
					if (result.realElement.isTree() || result.realElement.isTable() || result.realElement.isList()) {
						String[] sel = result.realElement.getPathSelection();
						ViewerUIElement v = new ViewerUIElement(result.element, getRecorder());
						// Do not pass set selection if previous command is
						// click,
						// so double click will override it
						Command last = getRecorder().getContainer().getLast();
						if (sel != null && !(last instanceof Click && ((Click) last).isDefault())) {
							v.setSelection(sel);
						}
						v.doubleClick();
					} else {
						// Check for not a canvas
						if (!(isCanvas(widget, type))
								&& !widget.getClass().getName().equals("org.eclipse.draw2d.FigureCanvas")) {
							ControlUIElement e = new ControlUIElement(result.element, getRecorder());
							e.doubleClickAndWait();
						}
					}
				}
			}
			lastEvents.add(toRecording);
		} else if (type == SWT.Close) {
			processClose(widget);
		} else if (type == SWT.FocusIn) {
			processFocusIn(widget);
		}
		// else if (type == SWT.FocusOut) {
		// processFocusOut(widget);
		// }
		// else if (StyledTextSupport.isCaretEvent(widget.getClass(), type)
		// && widget instanceof StyledText) {
		// StyledText text = (StyledText) widget;
		// int offset = text.getCaretOffset();
		// FindResult element = findElement(widget, false, false, false);
		// TextUIElement textElement = new TextUIElement(element.element,
		// getRecorder());
		// textElement.selectLine(line);
		// }
		else {
			lastEvents.add(toRecording);
		}
	}

	private static boolean hasListeners(Widget widget, int event) {
		return hasNonPlatformListeners(widget.getListeners(event), event);
	}

	private void processFocusIn(Widget widget) {
		if (!(widget instanceof Text) || !hasListeners(widget, SWT.FocusIn)) {
			return;
		}
		// See http://jira4.xored.com/browse/QS-2100
		// The issue is that jface WizardDialog sets focus to the
		// focus control before stopping. Looks like there's no
		// other way to handle this situation besides
		// checking current stack trace and searching whether
		// WizardDialog#stopped is invoked
		Context ctx = ContextManagement.currentContext();
		if (ctx.contains(WizardDialog.class.getName(), "stopped")) {
			return;
		}
		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			if (ctx.contains(Display.class.getName(), "checkFocus")) {
				return;
			}
		}
		FindResult element = getLocator().findElement(widget, true, false, true);
		if (element == null || element.element == null) {
			return;
		}

		new ControlUIElement(element.element, getRecorder()).setFocus();
	}

	public void addToPressed(Event event) {
		KeyStroke strk = KeyStroke.getInstance(event.stateMask, event.keyCode);
		String split = strk.toString().toLowerCase();
		String[] values = split.split("\\+");
		for (String val : values) {
			if (!pressed.contains(val))
				pressed.add(val);
		}
	}

	private void processDateTime(Control dateTime, Control c, int type, Event event) {
		DateTime dt = (DateTime) dateTime;
		FindResult element;
		switch (type) {
		case SWT.Selection:
			element = getLocator().findElement(dateTime, false, false, true);
			if (element != null && element.element != null) {
				TextUIElement e = new TextUIElement(element.element, getRecorder());
				e.setText(PlayerTextUtils.getDateTimeValue(dt));
			}
			break;
		case SWT.MouseDoubleClick:
			element = getLocator().findElement(dateTime, false, false, true);
			if (element != null && element.element != null) {
				ControlUIElement e = new ControlUIElement(element.element, getRecorder());
				e.doubleClickAndWait();
			}
			break;
		case SWT.KeyDown:
			processKeyDown(dt, event);
			break;
		}
	}

	public boolean isCanvas(Widget widget, int type) {
		List<IRecordingProcessorExtension> list = getRecorder().getProcessors(IRecordingProcessorExtension.class);
		for (IRecordingProcessorExtension ext : list) {
			if (widget instanceof Canvas && ext.isNotCanvas(widget, type, null)) {
				return false;
			}
		}

		if (widget instanceof Canvas && !(widget instanceof Shell) && !(widget instanceof StyledText)
				&& !(widget instanceof Browser) && !(widget instanceof CLabel)) {
			// Fiter events came to EditDomain
			if (type == SWT.MouseDown || type == SWT.MouseUp || type == SWT.MouseMove || type == SWT.MouseDoubleClick
					|| type == SWT.MouseEnter || type == SWT.MouseExit || type == SWT.MouseHover
					|| type == SWT.MouseWheel) {
				String clName = widget.getClass().getName();
				if (!clName.equals("org.eclipse.draw2d.FigureCanvas")) {
					return true;
				}
			}
		}
		return false;
	}

	public boolean isNotNative(Widget widget) {
		Context ctx = ContextManagement.currentContext();
		// if (ctx.hasCall("org.eclipse.swt.widgets.Display",
		// "runDeferredEvents",
		// 6)
		// || ctx
		// .hasCall("org.eclipse.swt.widgets.Widget", "sendEvent",
		// 6)) {
		// return false;
		// }
		if (ctx.contains("org.eclipse.swt.widgets.Composite", "setFocus")) {
			return true;
		}
		if (ctx.contains("org.eclipse.swt.widgets.Shell", "close")) {
			return true;
		}
		if (ctx.contains("org.eclipse.swt.widgets.TreeItem", "setExpanded")) {
			return true;
		}
		if (ctx.contains("org.eclipse.ui.views.properties.PropertySheetViewer", "removeItem")) {
			return true;
		}

		if (ctx.contains("org.eclipse.swt.widgets.TabFolder", "createItem")
				|| ctx.contains("org.eclipse.swt.widgets.TabFolder", "destroyItem")) {
			return true;
		}
		if (ctx.containsClass("org.eclipse.swt.custom.CCombo") && !(widget instanceof CCombo)) {
			return true;
		}

		if (!getRecorder().isNotNativeEventsIgnored()) {
			return false;
		}

		// if (Platform.getOS().equals(Platform.OS_MACOSX)) {
		if (!ctx.contains("org.eclipse.swt.widgets.Display", "windowProc")
				&& !ctx.contains("org.eclipse.swt.widgets.Display", "runDeferredEvents")
				&& !ctx.contains("org.eclipse.swt.widgets.Control", "traverse")) {
			return true;
		}
		// } else {
		// if (!ctx.contains("org.eclipse.swt.widgets.Display", "windowProc")) {
		// return true;
		// }
		// }

		return false;
	}

	private void processCCombo(Widget widget, CCombo cCombo, int type, Event event) {
		switch (type) {
		case SWT.Selection:
			if (widget instanceof org.eclipse.swt.widgets.List) {
				FindResult result = getLocator().findElement(cCombo, true, false, false);
				if (result != null) {
					org.eclipse.swt.widgets.List l = (org.eclipse.swt.widgets.List) widget;
					TextUIElement e = new TextUIElement(result.element, getRecorder());
					String[] selection = l.getSelection();
					if (selection.length == 1) {
						String value = selection[0];
						processComboSelection(e, cCombo.getItems(), value);
					}
				}
			}
			break;

		// case SWT.KeyDown:
		// // if (!(widget instanceof Text)) {
		// processKeyDown(cCombo, event);
		// lastEvents.add(toRecording);
		// // }
		// break;
		//
		// case SWT.KeyUp:
		// if (isSimpleTextControl(widget)) {
		// beforeTextState = null;
		// }
		// lastEvents.add(toRecording);
		// break;

		case SWT.Modify:
			FindResult result = getLocator().findElement(cCombo, true, false, false);
			if (result != null) {
				TextUIElement e = new TextUIElement(result.element, getRecorder());
				String text = cCombo.getText();
				if (Arrays.asList(cCombo.getItems()).contains(text))
					e.select(text);
				else
					e.setText(text);
			}
			break;
		}
	}

	@SuppressWarnings("unused")
	private boolean isDebug() {
		Bundle bundle = Platform.getBundle("org.eclipse.rcptt.tesla.recording.ui.dev");
		return bundle != null;
	}

	public static boolean isIgnoreSelection(Widget widget, Event event, int type, Context ctx) {
		SWTUIElement swtuiElement = SWTRecordingHelper.getHelper().getLocator().getPlayer().wrap(widget);
		if (swtuiElement != null && swtuiElement.getKind().is(ElementKind.Unknown))
			return true;

		if ((widget instanceof Canvas && !(widget instanceof StyledText))
				&& Arrays.asList(SWT.Selection, SWT.DefaultSelection).contains(type)) {
			return true;
		}

		if (widget instanceof Combo && Arrays.asList(SWT.Selection, SWT.DefaultSelection).contains(type)) {
			return true;
		}

		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			if (widget instanceof Sash) {
				return true;
			}

			// Ignore radio buttons it's recorded on MouseUp (on some radio on
			// MacOSX selection event not appear)
			// for example see radio buttons on Install/Update preference page
			if (widget instanceof Button && (((Button) widget).getStyle() & SWT.RADIO) != 0) {
				return true;
			}
		}

		return false;
	}

	private void processSelection(Widget widget, Event event, int type, Context ctx) {
		boolean isRadioWidget = widget instanceof Button && (((Button) widget).getStyle() & SWT.RADIO) != 0;
		boolean isTabFolder = widget instanceof TabFolder || widget instanceof CTabFolder;
		boolean isTreeOrTableOrList = (widget instanceof Tree || widget instanceof Table
				|| widget instanceof org.eclipse.swt.widgets.List);
		boolean clean = true;

		if (EclipseWorkbenchProvider.getProvider().isViewOrEditorButton(widget)) {
			ToolItem button = (ToolItem) widget;
			String tip = button.getToolTipText();
			CTabFolder ctabFolder = EclipseWorkbenchProvider.getProvider().getTabFolderFromButton(button);
			if (ctabFolder != null && tip != null) {
				if (tip.equals("Maximize")) {
					SWTEventManager.recordTabFolderEvent(ctabFolder, SWTEventManager.EVENT_TAB_MAXIMIZE);
				} else if (tip.equals("Minimize")) {
					SWTEventManager.recordTabFolderEvent(ctabFolder, SWTEventManager.EVENT_TAB_MINIMIZE);
				} else if (tip.equals("Restore")) {
					SWTEventManager.recordTabFolderEvent(ctabFolder, SWTEventManager.EVENT_TAB_RESTORE);
				} else if (tip.equals("View Menu")) {
					// do nothing
				} else if (tip.equals("Show List")) {
					SWTEventManager.recordTabFolderEvent(ctabFolder, SWTEventManager.EVENT_TAB_SHOW_LIST);
				}
				return;
			}
		}

		if (isIgnoreSelection(widget, event, type, ctx)) {
			return;
		}

		if (WidgetClassifier.isAColumn(widget)) {
			processColumnHeaderSelection(widget);
			return;
		}

		if (widget instanceof org.eclipse.swt.widgets.Link) {
			FindResult result = getLocator().findElement(widget, true, false, false);
			if (result != null && result.element != null) {
				LinkUIElement e = new LinkUIElement(result.element, getRecorder());
				String[] links = LinkUIElement.parse(((org.eclipse.swt.widgets.Link) widget).getText());
				if (links.length == 1 && links[0].equals(event.text)) {
					// There's only one clickable segment in the
					// link, so 'click-link' command will be recorded without
					// argument
					e.clickLink(null);
				} else {
					e.clickLink(event.text);
				}
			}
			return;
		}

		if ((widget instanceof MenuItem) && SWTWidgetLocator.isCTabFolderListMenuItem((MenuItem) widget)) {
			CTabFolder miTabFolder = SWTWidgetLocator.getCTabFolder((MenuItem) widget);
			FindResult result = getLocator().findElement(miTabFolder, true, false, false);
			ProcessCTabFolderItemSelection(miTabFolder, result, ((MenuItem) widget).getText());
			return;
		}

		if (widget instanceof Slider) {
			FindResult result = getLocator().findElement(widget, true, false, false);
			if (result != null && result.element != null) {
				TextUIElement e = new TextUIElement(result.element, getRecorder());
				e.setText(Integer.toString(((Slider) widget).getSelection()));
			}
			return;
		}

		boolean isCheckable = Platform.getOS().equals(Platform.OS_WIN32) && isTreeOrTableOrList;
		boolean isMouseOrKeyOps = lastEvents.checkType(widget, SWT.MouseUp, SWT.MouseDown, SWT.Arm, SWT.KeyDown,
				SWT.KeyUp, SWT.MouseDoubleClick, SWT.MouseMove);

		boolean isFromFilteredItemsSelectionDialog = ctx.contains("org.eclipse.ui.dialogs.FilteredItemsSelectionDialog",
				"refresh");
		if (isFromFilteredItemsSelectionDialog)
			return;

		boolean isWidgetSendSelectionNonWin32 = ctx.contains("org.eclipse.swt.widgets.Widget", "sendSelectionEvent")
				&& !Platform.getOS().equals(Platform.OS_WIN32);

		boolean isRunDefferedEventsOSX = ctx.contains("org.eclipse.swt.widgets.Display", "runDeferredEvents")
				&& Platform.getOS().equals(Platform.OS_MACOSX);

		boolean isButtonFocusEvent = widget instanceof Button
				&& (lastEvents.checkType(widget, SWT.FocusIn) || ((Button) widget).isFocusControl());
		boolean isListTreeTableActivate = (widget instanceof Table || widget instanceof Tree
				|| widget instanceof org.eclipse.swt.widgets.List) && lastEvents.checkType(widget, SWT.Activate);
		if (widget instanceof Sash) {
			return;
		}
		try {
			if (widget instanceof Spinner) {
				FindResult result = getLocator().findElement(widget, true, false, false);
				// System.out.println("RESULT is:" + result);
				if (result != null && result.element != null) {
					TextUIElement e = new TextUIElement(result.element, getRecorder());
					e.setText(Integer.toString(((Spinner) widget).getSelection()));
				}
			}
			if (widget instanceof Text || widget instanceof StyledText || widget instanceof Browser) {
				processTextWidgetSelectionEvent(widget);
				return;
			}
			// Radio MenuItem (first event from previous selected item, second
			// event from item that was selected)
			if (widget instanceof MenuItem && (((MenuItem) widget).getStyle() & SWT.RADIO) != 0) {
				FindResult result = getLocator().findElement(widget, true, false, false);
				if (((MenuItem) widget).getSelection() && result != null && result.element != null) {
					ControlUIElement e = new ControlUIElement(result.element, getRecorder());
					e.clickAndWait(type == SWT.DefaultSelection, event.stateMask);
				}
			} else if ((isMouseOrKeyOps || isWidgetSendSelectionNonWin32 || isRunDefferedEventsOSX || isButtonFocusEvent
					|| isListTreeTableActivate || isCheckable) && !(isRadioWidget && !((Button) widget).getSelection())
					&& !isTabFolder || (type == SWT.DefaultSelection && isTreeOrTableOrList)) {
				if (widget instanceof MenuItem) {
					MenuItem mi = (MenuItem) widget;
					Object data = mi.getData();
					if (data instanceof ActionContributionItem) {
						ActionContributionItem aci = (ActionContributionItem) data;
						if (isIgnoredAction(aci.getAction())) {
							return; // ignore Preferences and About menu item
						}
					}
				}
				FindResult result = getLocator().findElement(widget, true, false, false);

				if (result != null && result.element != null) {
					if (result.realElement.isTree() || result.realElement.isTable() || result.realElement.isList()) {
						processViewers(event, type, result);
					} else {
						if (!result.realElement.isText()) {
							ControlUIElement e = new ControlUIElement(result.element, getRecorder());
							boolean skipEvent = false;
							if (Platform.getOS().equals(Platform.OS_MACOSX)) {
								if (widget instanceof Button) {
									if ((widget.getStyle() & SWT.CHECK) != 0) {
										skipEvent = true;
									}
								}
							}
							if (!skipEvent) {
								if (event != null && event.detail == SWT.ARROW) {
									e.clickArrowAndWait(type == SWT.DefaultSelection);
								} else if (widget instanceof Button && (widget.getStyle() & SWT.CHECK) != 0) {
									e.check(((Button) widget).getSelection());
								} else {
									e.clickAndWait(type == SWT.DefaultSelection, event.stateMask);
								}
							}
						}
					}
				}
			} else {
				if (widget instanceof ToolItem && (lastEvents.checkType(((ToolItem) widget).getParent(), SWT.MouseUp)
						|| Platform.getOS().equals(Platform.OS_WIN32))) {
					processToolItem(widget, event);
				} else if (widget instanceof CoolItem
						&& (lastEvents.checkType(((CoolItem) widget).getParent(), SWT.MouseUp)
								|| Platform.getOS().equals(Platform.OS_WIN32))) {
					processCoolItem(widget);
				} else if (isRadioWidget) {
					if (!Platform.getOS().equals(Platform.OS_WIN32)) {
						Button radio = (Button) widget;
						if (radio.getSelection()) {
							FindResult result = getLocator().findElement(widget, true, false, false);
							// System.out.println("RESULT is:" + result);
							ControlUIElement e = new ControlUIElement(result.element, getRecorder());
							e.clickAndWait();
							lastEvents.clear();
							// System.out.println("_1_Clean Events" + index++);
							clean = false;
						}
					} else {
						clean = false;
					}
				}
			}
			isTabFolder = processTabFolder(widget, isTabFolder);
		} finally {
			if (clean && !isTabFolder) {
				lastEvents.clear();
				// menuSources.clear();
				// System.out.println("_2_Clean Events" + index++);
			}
		}
	}

	private void processColumnHeaderSelection(Widget widget) {
		FindResult result = getLocator().findElement(widget, false, false, false);
		new ControlUIElement(result.element, getRecorder()).click();
	}

	private boolean isIgnoredAction(IAction action) {
		if (action.getId() != null && action.getId().equals("preferences")) {
			if ((action.getActionDefinitionId() != null
					&& action.getActionDefinitionId().equals("org.eclipse.ui.window.preferences"))
					&& !action.getClass().getName().equals("org.eclipse.ui.internal.OpenPreferencesAction")) {
				return true;
			}
		} else if (action.getId() != null && action.getId().equals("about")) {
			if (action.getActionDefinitionId() != null
					&& action.getActionDefinitionId().equals("org.eclipse.ui.help.aboutAction")) {
				return true;
			}
		}
		if (action.getClass().getName().equals("org.eclipse.ui.internal.OpenPreferencesAction")) {
			// Do
			// getRecorder().safeExecuteCommand(
			// ProtocolFactory.eINSTANCE.createClickPreferencesMenu());
			return true;
		}
		return false;
	}

	@SuppressWarnings("unused")
	private void processTextWidgetSelectionEvent(Widget widget) {
		if (!inStyledTextAction) {

			Object this1 = TeslaSWTAccess.getThis(widget);

			FindResult result = getLocator().findElement(widget, true, false, false);
			if (result != null) {
				TextUIElement textCtrl = new TextUIElement(result.element, getRecorder());
				if (widget instanceof StyledText) {
					StyledText styledText = ((StyledText) widget);
					Point selection = styledText.getSelectionRange();
					if (selection.y != 0) {
						Command last = getRecorder().getContainer().getLast();
						if (last instanceof SetTextOffset) {
							SetTextOffset offset = (SetTextOffset) last;
							if (EcoreUtil.equals(offset.getElement(), result.element)) {
								getRecorder().removeLast();
							}
						}

						int startLine = styledText.getLineAtOffset(selection.x);
						int startOffset = selection.x - styledText.getOffsetAtLine(startLine);

						int endLine = styledText.getLineAtOffset(selection.x + selection.y);
						int endOffset = (selection.x + selection.y) - styledText.getOffsetAtLine(endLine);

						int caretOffset = styledText.getCaretOffset();
						if (caretOffset == selection.x) {
							textCtrl.setSelection(endLine, endOffset, startLine, startOffset);
						} else {
							textCtrl.setSelection(startLine, startOffset, endLine, endOffset);
						}
					}
				}
			}
		}
	}

	private boolean processTabFolder(Widget widget, boolean tabFolder) {
		if (!(widget instanceof TabFolder) && !(widget instanceof CTabFolder)) {
			return tabFolder;
		}
		FindResult result = getLocator().findElement(widget, true, false, false);

		if (result == null) {
			return tabFolder;
		}

		String tabName = null;
		if (widget instanceof TabFolder) {
			TabFolder tabFolderWidget = (TabFolder) widget;
			TabItem selectedItem = null;

			int selectionIndex = tabFolderWidget.getSelectionIndex();
			if (selectionIndex != -1) {
				selectedItem = tabFolderWidget.getItem(selectionIndex);

			}

			// Ivan Inozemtsev: On Linux if there are no selection listeners,
			// then selection event happens before updating
			// selection index, but after real tab switching
			// therefore, we need to manually iterate through
			// tabs in order to find which one is visible
			for (TabItem item : tabFolderWidget.getItems()) {
				if (item.isDisposed()) {
					continue;
				}

				Control content = item.getControl();
				if (content == null || content.isDisposed()) {
					continue;
				}

				if (content.isVisible()) {
					selectedItem = item;
					break;
				}
			}

			if (selectedItem == null) {
				return tabFolder;
			}
			tabName = PlayerTextUtils.removeAcceleratorFromText(selectedItem.getText());
		} else {
			CTabFolder tabFolderWidget = (CTabFolder) widget;
			CTabItem selectedItem = null;

			int selectionIndex = tabFolderWidget.getSelectionIndex();
			if (selectionIndex != -1) {
				selectedItem = tabFolderWidget.getItem(selectionIndex);

			}

			// Ivan Inozemtsev: On Linux if there are no selection listeners,
			// then selection event happens before updating
			// selection index, but after real tab switching
			// therefore, we need to manually iterate through
			// tabs in order to find which one is visible
			for (CTabItem item : tabFolderWidget.getItems()) {
				if (item.isDisposed()) {
					continue;
				}

				Control content = item.getControl();
				if (content == null || content.isDisposed()) {
					continue;
				}

				if (content.isVisible()) {
					selectedItem = item;
					break;
				}
			}

			if (selectedItem == null) {
				return tabFolder;
			}
			tabName = PlayerTextUtils.removeAcceleratorFromText(selectedItem.getText());
		}

		if (lastTabItemSelection.containsKey(widget)) {
			String v = lastTabItemSelection.get(widget);
			if (v.equals(tabName)) {
				return tabFolder;
			}
		}

		CompositeUIElement v = new CompositeUIElement(result.element, getRecorder());
		ControlUIElement tabItem = v.tabItem(tabName);
		tabItem.clickAndWait();
		return false;

	}

	private void processCoolItem(Widget widget) {
		// System.out.println("$");
		FindResult result = getLocator().findElement(widget, false, false, false);
		if (result != null) {
			ControlUIElement ctrl = new ControlUIElement(result.element, getRecorder());
			ctrl.clickAndWait();
		}
	}

	private void processToolItem(Widget widget, Event event) {
		ToolItem item = (ToolItem) widget;
		if ((item.getStyle() & SWT.RADIO) != 0 && !item.getSelection())
			return;

		boolean arrow = (event != null && event.detail == SWT.ARROW);
		FindResult result = getLocator().findElement(widget, false, false, false);
		if (result != null && result.element != null) {
			ControlUIElement ctrl = new ControlUIElement(result.element, getRecorder());
			if (arrow) {
				ctrl.clickArrowAndWait();
			} else {
				ctrl.clickAndWait();
			}
		}
	}

	private void processViewers(Event event, int type, FindResult result) {
		if (result.realElement.isSupportMultipleSelections()) {
			ViewerUIElement v = new ViewerUIElement(result.element, getRecorder());
			if (event.detail == SWT.CHECK && event.item != null) {
				String[] sel = null;
				if (event.item instanceof TableItem) {
					TableItem tItem = (TableItem) event.item;
					sel = Viewers.getPathByTableItem(tItem);
				} else if (event.item instanceof TreeItem) {
					TreeItem trItem = (TreeItem) event.item;
					sel = Viewers.getPathByTreeItem(trItem);
				}
				boolean checked = true;
				if (event.item instanceof TreeItem) {
					checked = ((TreeItem) event.item).getChecked();
				} else if (event.item instanceof TableItem) {
					checked = ((TableItem) event.item).getChecked();
				}
				v.checkItem(checked, sel);
			} else {
				String[][] selection = result.realElement.getMultiPathSelection();
				if (selection != null && selection.length > 0) {
					if (!lastEvents.checkType(result.realElement.widget, SWT.MouseDoubleClick)) {
						if (type == SWT.DefaultSelection) {
							v.click(true);
						} else {
							if (recordClickInSeletion) {
								recordClickInSeletion = false;
								String[] path = Viewers.getPathByItem(event.item);
								v.item(path).click();
							} else {
								v.setMultiSelection(selection);
							}
						}
					}
				}
			}
		} else {
			String sel[] = null;
			if (sel == null) {
				sel = result.realElement.getPathSelection();
			}
			if (event != null && event.item != null && event.detail == SWT.CHECK) {
				// Try to extract selection from event.
				if (event.item instanceof TableItem) {
					TableItem tItem = (TableItem) event.item;
					sel = Viewers.getPathByTableItem(tItem);
				} else if (event.item instanceof TreeItem) {
					TreeItem trItem = (TreeItem) event.item;
					sel = Viewers.getPathByTreeItem(trItem);
				}
			}
			if (sel != null && sel.length > 0) {
				ViewerUIElement v = new ViewerUIElement(result.element, getRecorder());
				if (event != null && event.detail == SWT.CHECK) {
					boolean checked = true;
					if (event.item instanceof TreeItem) {
						checked = ((TreeItem) event.item).getChecked();
					} else if (event.item instanceof TableItem) {
						checked = ((TableItem) event.item).getChecked();
					}
					v.checkItem(checked, sel);
				} else {
					if (!lastEvents.checkType(result.realElement.widget, SWT.MouseDoubleClick)) {
						if (type == SWT.DefaultSelection) {
							v.click(true);
						} else {
							if (recordClickInSeletion) {
								recordClickInSeletion = false;
								String[] path = Viewers.getPathByItem(event.item);
								v.item(path).click();
							} else
								v.setSelection(sel);
						}
					}
				}
			}
		}
	}

	private static void processComboSelection(TextUIElement e, String[] items, String text) {
		if (Arrays.asList(items).contains(text))
			e.select(text);
		else
			e.setText(text);
	}

	private void processModify(Widget widget) {
		SWTUIElement wrap = getPlayer().wrap(widget);

		if (wrap.isDisabled()) { // Do not record modifications of disabled
			// fields.
			return;
		}
		if (lastEvents.checkType(widget, SWT.KeyDown, SWT.KeyUp, SWT.MouseDown) && !(widget instanceof Combo)) {
			FindResult element = getLocator().findElement(widget, true, false, false);
			if (element != null) {
				TextUIElement e = new TextUIElement(element.element, getRecorder());
				String currentText = element.realElement.getModificationText();
				if (currentText.trim().length() == 0) {
					// try obtain one character from keydown
					RecordedEvent e2 = lastEvents.getEvent(widget, SWT.KeyDown);
					if (e2 != null && !Character.isISOControl(e2.event.character)) {
						currentText = new String(new char[] { e2.event.character });
					}
				}
				if (beforeTextState == null || !beforeTextState.equals(currentText)) {
					if (widget != JFaceRecordingProcessor.lastCellEditorControl) {
						if (!(widget instanceof Combo)) {
							e.setText(currentText, false, isPasswordField(widget));
						} else {
							processComboSelection(e, ((Combo) widget).getItems(), currentText);
						}
					}
				}
			}
			beforeTextState = null;
			lastEvents.clear();
			pressed.clear();
		} else if (widget instanceof Combo) {
			Control ctrl = (Control) widget; // Skip events from invisible
			// shells.
			if (!ctrl.getShell().isVisible()) {
				return;
			}
			FindResult element = getLocator().findElement(widget, true, false, false);
			if (element != null && element.element != null) {
				TextUIElement e = new TextUIElement(element.element, getRecorder());
				processComboSelection(e, ((Combo) widget).getItems(), element.realElement.getModificationText());
				lastEvents.clear();
				// System.out.println("_4_Clean Events" + index++);
			}
			// System.out.println("Clean Events" + index++);
		}
	}

	private static boolean isPasswordField(Widget widget) {
		if ((widget.getStyle() & SWT.PASSWORD) != 0)
			return true;
		if (widget instanceof Text) {
			return ((Text) widget).getEchoChar() != '\0';
		}
		return false;
	}

	private void processMenuShow(Widget widget, RecordedEvent toRecording) {
		Object menuSource = null;

		// try to find column
		if (lastEvent != null && lastEvent.type == SWT.MenuDetect
				&& (lastEvent.widget instanceof Tree || lastEvent.widget instanceof Table)) {
			Point point = lastEvent.widget.getDisplay().map(null, (Control) lastEvent.widget, lastEvent.x, lastEvent.y);
			menuSource = TableTreeUtil.getColumnFromPoint(lastEvent.widget, point);
		}

		if (menuSource == null) {
			// Save click widget
			// Last last event with specified menu
			for (RecordedEvent e : lastEvents.fromMostRecent()) {
				Widget wid = e.widget;
				if (wid instanceof Control && !wid.isDisposed()) {
					Menu widMenu = ((Control) wid).getMenu();
					if (widMenu != null && widMenu.equals(widget)) {
						menuSource = wid;
						break;
					}
				}
			}
		}

		if (menuSource == null) {
			// Go over all control and try to locate menu
			if (widget instanceof Menu) {
				Decorations parent = ((Menu) widget).getParent();
				menuSource = findMenuSource(parent, widget);

				if (menuSource == null) {
					menuSource = SWTWidgetLocator.findViewMenuSource(widget);
				}
			}
		}
		if (menuSource != null) {
			SWTEventManager.setMenuSource((Menu) widget, menuSource);

		}
		getLocator().cleanMenuSources();
		lastEvents.add(toRecording);

		// Add selector for menu, for cases user show/hide menu, and some stuff
		// in APP are changed.
		getLocator().findElement(widget, false, false, false);
	}

	private Widget findMenuSource(Composite parent, Widget widget) {

		Menu menu = parent.getMenu();

		if (menu != null && menu.equals(widget)) {
			return parent;
		}
		Control[] children = parent.getChildren();
		for (Control control : children) {
			menu = control.getMenu();
			if (menu != null && menu.equals(widget)) {
				return control;
			}
			if (control instanceof Composite) {
				Widget result = findMenuSource((Composite) control, widget);
				if (result != null) {
					return result;
				}
			}
		}

		return null;
	}

	public void processKeyDown(Widget widget, Event event) {
		// if (checkType(widget, SWT.KeyDown)) {
		boolean shift = (event.stateMask & SWT.SHIFT) != 0;
		boolean ctrlb = (event.stateMask & SWT.CTRL) != 0;
		boolean alt = (event.stateMask & SWT.ALT) != 0;
		boolean check1 = ((event.stateMask & SWT.MODIFIER_MASK) != 0) && (!shift || ctrlb || alt);
		boolean enter = (event.character == SWT.CR) && event.stateMask == 0;
		boolean helpKey = event.keyCode == SWT.F1;
		boolean arrayKey = event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN
				|| event.keyCode == SWT.ARROW_LEFT || event.keyCode == SWT.ARROW_RIGHT;

		FindResult result = getLocator().findElement(widget, true, false, false);
		if (result != null) {
			if (isSimpleTextControl(widget)) {
				beforeTextState = result.realElement.getModificationText();
				if (enter || helpKey || arrayKey) {
					ControlUIElement ctrl = new ControlUIElement(result.element, getRecorder());
					ctrl.press(event.keyCode, event.stateMask, widget instanceof Browser || helpKey, event.character,
							getMeta(event.stateMask));
					return;
				}
			}
			if (!isSimpleTextControl(widget) || check1) {
				ControlUIElement ctrl = new ControlUIElement(result.element, getRecorder());
				if (!(event.keyCode == SWT.SHIFT || event.keyCode == SWT.CTRL || event.keyCode == SWT.ALT
						|| event.keyCode == SWT.COMMAND)) {
					if ((event.keyCode & SWT.KEYCODE_BIT) == 0 && event.stateMask == 0
							&& !Character.isISOControl(event.character)) {
						if (widget instanceof StyledText || widget instanceof Browser
								|| widget.getListeners(SWT.KeyDown).length > 0
								|| widget.getListeners(SWT.KeyUp).length > 0) {
							ctrl.type(new String(new char[] { event.character }), widget instanceof Browser);
						}
					} else {
						// TODO record shortcut with command binding
						// String typeActionId = checkForActionCommand(
						// event.stateMask, event.keyCode);
						// if (typeActionId != null) {
						// ctrl.typeAction(typeActionId);
						// } else {
						if (widget instanceof StyledText || widget instanceof Browser) {
							if (event.stateMask == SWT.SHIFT && !Character.isISOControl(event.character)) {
								ctrl.type(new String(new char[] { event.character }), widget instanceof Browser);
							} else {
								ctrl.press(event.keyCode, event.stateMask, widget instanceof Browser, event.character,
										getMeta(event.stateMask));
							}
						} else {
							ctrl.press(event.keyCode, event.stateMask, widget instanceof Browser, event.character,
									getMeta(event.stateMask));
						}
						// }
					}
				}
			}
			lastEvents.clear();
		}
		// }
	}

	private static boolean isSimpleTextControl(Widget widget) {
		if (widget instanceof Combo || widget instanceof Spinner)
			return true;
		if (widget instanceof Text)
			// && (((Text) widget).getStyle() & SWT.SINGLE) != 0)
			return true;
		return false;
	}

	public void processTraverse(Widget widget, Event event, RecordedEvent toRecording) {
		// === traverse types ===
		// - SWT.TRAVERSE_NONE
		// * SWT.TRAVERSE_ESCAPE (event chain)
		// - SWT.TRAVERSE_RETURN (event chain)
		// * SWT.TRAVERSE_TAB_NEXT
		// * SWT.TRAVERSE_TAB_PREVIOUS
		// * SWT.TRAVERSE_ARROW_NEXT
		// * SWT.TRAVERSE_ARROW_PREVIOUS
		// * SWT.TRAVERSE_MNEMONIC
		// * SWT.TRAVERSE_PAGE_NEXT
		// * SWT.TRAVERSE_PAGE_PREVIOUS

		// detecting assert/record mode shortcuts
		if (event.detail == SWT.TRAVERSE_MNEMONIC) {
			TeslaRecorder recorder = getRecorder();
			if (recorder == null) {
				return;
			}
			String[] assertShortcuts = recorder.getAssertModeShortcuts();
			String[] recordShortcuts = recorder.getRecordModeShortcuts();
			String[] startRecordShortcuts = recorder.getStartRecordShortcuts();
			String[] stopRecordShortcuts = recorder.getStopRecordShortcuts();
			String[] replayShortcuts = recorder.getReplayShortcuts();

			SWTAssertManager assertManager = recorder.getProcessor(SWTAssertManager.class);

			if (assertManager != null) {
				boolean assertRequest = assertManager.isShortcutRequest(event, assertShortcuts);
				boolean recordingRequest = assertManager.isShortcutRequest(event, recordShortcuts);
				boolean startRecordRequest = assertManager.isShortcutRequest(event, startRecordShortcuts);
				boolean stopRecordRequest = assertManager.isShortcutRequest(event, stopRecordShortcuts);
				boolean replayRequest = assertManager.isShortcutRequest(event, replayShortcuts);

				if (assertRequest || recordingRequest || startRecordRequest || stopRecordRequest || replayRequest) {
					assertManager.setFreeze(assertRequest, null);

					Type type = ProtocolFactory.eINSTANCE.createType();
					type.setState(event.stateMask);
					type.setCharacter(event.character);
					type.setCode(event.keyCode);
					getRecorder().safeExecuteCommand(type);

					event.detail = SWT.TRAVERSE_NONE;
					event.doit = false;
					return;
				}
			}
		}

		boolean radioWidgetIgnored = widget instanceof Button && (((Button) widget).getStyle() & SWT.RADIO) != 0
				&& (event.detail == SWT.TRAVERSE_ARROW_NEXT || event.detail == SWT.TRAVERSE_ARROW_PREVIOUS);

		boolean isEscapeChain = false;

		RecordedEvent lastRecorded = lastEvents.lastRecorded();
		if (lastRecorded != null) {

			isEscapeChain = event.detail == SWT.TRAVERSE_ESCAPE && lastRecorded.type == SWT.Traverse
					&& lastRecorded.event.doit == true && lastRecorded.event.detail == SWT.TRAVERSE_ESCAPE;

			// boolean isReturnChain = event.detail == SWT.TRAVERSE_RETURN
			// && lastRecorded.type == SWT.Traverse
			// && lastRecorded.event.doit == true
			// && lastRecorded.event.detail == SWT.TRAVERSE_RETURN;
		}

		if (event.doit && event.detail != SWT.TRAVERSE_NONE && event.detail != SWT.TRAVERSE_RETURN && !isEscapeChain
				&& !radioWidgetIgnored) {
			FindResult result = getLocator().findElement(widget, true, false, false);
			if (result != null) {
				ControlUIElement ctrl = new ControlUIElement(result.element, getRecorder());
				ctrl.traverse(event.detail, event.character);
			}
		}
	}

	public static int getMeta(int stateMask) {

		// The recognized modifiers keys are M1, M2, M3, M4, ALT, COMMAND, CTRL,
		// and SHIFT. The "M" modifier keys are a platform-independent way of
		// representing keys, and these are generally preferred. M1 is the
		// COMMAND key on MacOS X, and the CTRL key on most other platforms. M2
		// is the SHIFT key. M3 is the Option key on MacOS X, and the ALT key on
		// most other platforms. M4 is the CTRL key on MacOS X, and is undefined
		// on other platforms. (from Eclipse SDK Help)
		final int M1 = 1;
		final int M2 = 2;
		final int M3 = 4;
		final int M4 = 8;

		int meta = 0;

		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			if ((stateMask & SWT.COMMAND) != 0)
				meta |= M1;
			if ((stateMask & SWT.SHIFT) != 0)
				meta |= M2;
			if ((stateMask & SWT.ALT) != 0) // what is Option key on Mac, it's a
				// synonym ALT?
				meta |= M3;
			if ((stateMask & SWT.CTRL) != 0)
				meta |= M4;

		} else {
			if ((stateMask & SWT.CTRL) != 0)
				meta |= M1;
			if ((stateMask & SWT.SHIFT) != 0)
				meta |= M2;
			if ((stateMask & SWT.ALT) != 0)
				meta |= M3;
		}

		return meta;
	}

	@SuppressWarnings("unused")
	private String checkForActionCommand(int mask, int keyCode) {
		KeyStroke hotKey = KeyStroke.getInstance(mask, Character.toUpperCase(keyCode));
		IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getService(IBindingService.class);
		Binding binding = bindingService.getPerfectMatch(KeySequence.getInstance(hotKey));
		if (binding != null && binding.getParameterizedCommand() != null
				&& binding.getParameterizedCommand().getId() != null) {
			return binding.getParameterizedCommand().getId();
		}
		return null;
	}

	private void processMouseUp(Widget widget, Event event, RecordedEvent toRecording) {
		if (widget instanceof Table || widget instanceof Tree) {
			Viewer viewer = TeslaSWTAccess.getViewer((Control) widget);
			if (viewer != null && viewer instanceof ColumnViewer) {
				ColumnViewer cview = (ColumnViewer) viewer;
				CellEditor[] editors = cview.getCellEditors();
				// Collect click column
				ViewerCell cell = cview.getCell(new Point(event.x, event.y));
				if (cell != null && editors != null) {
					int index = cell.getColumnIndex();
					if (editors[index] != null && editors[index] instanceof CheckboxCellEditor) {
						recordCellAccess(widget, event, RecordCellAccessSource.MouseUp);
						return;
					}
				}
			}
			Listener[] listenersUp = widget.getListeners(SWT.MouseUp);
			if ((listenersUp != null && hasNonPlatformListeners(listenersUp, SWT.MouseUp)) || mouseDownRecorded) {
				mouseDownRecorded = false;
				recordCellAccess(widget, event, RecordCellAccessSource.MouseUp);
			}
		}
		// Listener[] listenersDown = widget.getListeners(SWT.MouseDown);
		// if ((listenersDown != null && containsNonPlatform(listenersDown,
		// SWT.MouseDown))) {
		recordTextSetFocus(widget, event.button);
		// }
		if (Platform.getOS().equals(Platform.OS_MACOSX)) {
			if (widget instanceof Button) {
				if ((widget.getStyle() & SWT.CHECK) != 0) {
					FindResult result = getLocator().findElement(widget, false, false, true);
					if (result != null) {
						ControlUIElement e = new ControlUIElement(result.element, getRecorder());
						e.check(((Button) widget).getSelection());
					}
				} else if ((widget.getStyle() & SWT.RADIO) != 0) {
					FindResult result = getLocator().findElement(widget, false, false, true);
					if (result != null) {
						ControlUIElement e = new ControlUIElement(result.element, getRecorder());
						e.clickAndWait();
					}
				}
			}
		}

		// click on FilteredTree or Q7 SearchControl clear button
		if (widget instanceof Label && isSearchControlLabel((Label) widget)
				&& lastEvents.checkType(widget, SWT.MouseDown)) {
			FindResult result = getLocator().findElement(widget, true, false, false);
			if (result != null) {
				ControlUIElement e = new ControlUIElement(result.element, getRecorder());
				e.clickAndWait();
				beforeTextState = "";
			}
		}

		lastEvents.add(toRecording);
	}

	private boolean isSearchControlLabel(Label label) {
		if (label.getParent() instanceof Composite && label.getParent().getParent() != null
				&& label.getParent().getParent().getClass().getName().equals("org.eclipse.ui.dialogs.FilteredTree")) {
			return true;
		}
		if (label.getParent() instanceof Composite && label.getParent().getParent() != null && label.getParent()
				.getParent().getClass().getName().equals("org.eclipse.rcptt.ui.commons.SearchControl")) {
			return true;
		}
		return false;
	}

	private boolean mouseDownRecorded = false;
	private boolean recordClickInSeletion = false;

	private enum RecordCellAccessSource {
		MouseDown, MouseUp
	}

	private void recordCellAccess(Widget widget, Event event, RecordCellAccessSource source) {
		if (!(widget instanceof Table) && !(widget instanceof Tree)) {
			return;
		}

		Point pt = new Point(event.x, event.y);
		int row = TableTreeUtil.findRow(widget, pt);
		if (row == -1)
			return; // click on an icon or expansion sign

		boolean hasColumns = TableTreeUtil.getColumnCount(widget) > 0;

		FindResult result = getLocator().findElement(widget, true, false, false);

		// if (isDublicateCellClick(column, row)) {
		// return;
		// }
		ViewerUIElement ve = new ViewerUIElement(result.element, getRecorder());

		if (source == RecordCellAccessSource.MouseDown) {
			mouseDownRecorded = true;

			// record click if it has no columns and it is single selection or
			// multiple but selection is replaced
			recordClickInSeletion = !hasColumns && ((widget.getStyle() & SWT.MULTI) == 0
					|| ((event.stateMask & SWT.SHIFT) == 0 && (event.stateMask & SWT.CTRL) == 0));

			if (widget instanceof Tree && hasColumns) {
				List<String> path = Arrays.asList(Viewers.getPathByItem(TableTreeUtil.getItem(widget, row)));

				if (path.size() > 1) {
					ve.item(path.subList(0, path.size() - 1).toArray(new String[0])).expand();
				}
			}
		}

		if (hasColumns) {
			Point cell = TableTreeUtil.findCell(widget, pt);
			if (cell == null) {
				return;
			}
			row = cell.x;
			int column = cell.y;

			recordMouseEvent(ve.item(column, row), event,
					source == RecordCellAccessSource.MouseDown ? SWT.MouseDown : SWT.MouseUp);
			// ve.item(column, row).click();
		} else if (source == RecordCellAccessSource.MouseUp && recordClickInSeletion) {
			recordClickInSeletion = false;
			Object[] selection = TableTreeUtil.getSelection(widget);

			List<String> path;
			if (selection.length == 1)
				path = Arrays.asList(Viewers.getPathByItem(selection[0]));
			else
				path = Arrays.asList(Viewers.getPathByItem(TableTreeUtil.getItem(widget, row)));
			ve.item(path.toArray(new String[0])).click();

		}
	}

	private void recordTextSetFocus(Widget widget, int button) {
		if (widget instanceof Text) {
			// just record click and we are done

			String start = null;
			String end = null;

			Text t = (Text) widget;

			if (!t.getText().isEmpty()) {
				boolean multi = (t.getStyle() & SWT.MULTI) != 0;
				if (multi) {
					int iSelEnd = t.getCaretPosition();
					int iSelStart;
					Point selection = t.getSelection();
					if (iSelEnd != selection.y) {
						iSelStart = selection.y;
					} else {
						iSelStart = selection.x;
					}
					StringLines lines = new StringLines(t.getText());
					if (iSelStart != iSelEnd) {
						start = lines.calcLineColumn(iSelStart);
						end = lines.calcLineColumn(iSelEnd);
					} else {
						start = lines.calcLineColumn(iSelEnd);
					}
				} else {
					int iSelEnd = t.getCaretPosition();
					int iSelStart;
					Point point = t.getSelection();
					if (point != null) {
						if (iSelEnd != point.y) {
							iSelStart = point.y;
						} else {
							iSelStart = point.x;
						}
						if (iSelStart != iSelEnd) {
							start = Integer.toString(iSelStart + 1);
							end = Integer.toString(iSelEnd + 1);
						} else {
							start = Integer.toString(iSelEnd + 1);
						}

					}
				}
			}

			new ControlUIElement(getLocator().findElement(widget, true, false, false).element, getRecorder())
					.clickText(start, end, TeslaUtils.intToButtonName(button));
		}
	}

	private void recordMouseEvent(ControlUIElement element, Event event, int type) {
		MouseEvent me = ProtocolFactory.eINSTANCE.createMouseEvent();
		me.setButton(event.button);
		me.setCount(isDefaultCount(event) ? -1 : event.count);
		me.setElement(element.getElement());
		me.setKind(mouseToEventKind.get(event.type == 0 ? type : event.type));
		me.setStateMask(event.stateMask);
		me.setX(Integer.MIN_VALUE);
		me.setY(Integer.MIN_VALUE);
		getRecorder().safeExecuteCommand(me);
	}

	private static boolean isDefaultCount(Event event) {
		if (!defaultCounts.containsKey(event.type)) {
			return false;
		}
		return defaultCounts.get(event.type) == event.count;
	}

	private static final Map<Integer, MouseEventKind> mouseToEventKind = new HashMap<Integer, MouseEventKind>();
	static {
		mouseToEventKind.put(SWT.MouseDoubleClick, MouseEventKind.DOUBLE_CLICK);
		mouseToEventKind.put(SWT.MouseDown, MouseEventKind.DOWN);
		mouseToEventKind.put(SWT.MouseEnter, MouseEventKind.ENTER);
		mouseToEventKind.put(SWT.MouseExit, MouseEventKind.EXIT);
		mouseToEventKind.put(SWT.MouseMove, MouseEventKind.MOVE);
		mouseToEventKind.put(SWT.MouseUp, MouseEventKind.UP);
		mouseToEventKind.put(SWT.MouseHover, MouseEventKind.HOVER);
	}
	private static final Map<Integer, Integer> defaultCounts = new HashMap<Integer, Integer>();
	static {
		defaultCounts.put(SWT.MouseDoubleClick, 2);
		defaultCounts.put(SWT.MouseDown, 1);
		defaultCounts.put(SWT.MouseEnter, 0);
		defaultCounts.put(SWT.MouseExit, 0);
		defaultCounts.put(SWT.MouseMove, 0);
		defaultCounts.put(SWT.MouseUp, 1);
		defaultCounts.put(SWT.MouseHover, 0);
	}

	@SuppressWarnings("unused")
	private boolean isDublicateCellClick(int col, int row) {
		boolean itemClickCmdFound = false;
		for (int i = 1; i <= getRecorder().getContainer().size(); i++) {
			Command cmd = getRecorder().getContainer().getLastCommand(i);
			if (cmd instanceof Click && ElementKind.Item.toString().equals(((Click) cmd).getElement().getKind())) {
				itemClickCmdFound = true;
				continue;
			}
			if (cmd instanceof SelectCommand && itemClickCmdFound) {
				SelectData data = ((SelectCommand) cmd).getData();
				if (data.getIndexes() != null && data.getIndexes().size() == 2 && data.getIndexes().get(0) == col
						&& data.getIndexes().get(1) == row) {
					return true;
				}
			}
			if (!(cmd instanceof SetSelection || cmd instanceof SelectCommand)) {
				return false;
			}
		}
		return false;
	}

	private static boolean hasNonPlatformListeners(Listener[] listenersDown, int kind) {
		if (listenersDown == null) {
			return false;
		}
		for (Listener listener : listenersDown) {
			if (listener instanceof TypedListener) {
				SWTEventListener eventListener = ((TypedListener) listener).getEventListener();
				if (eventListener != null) {
					String lName = eventListener.getClass().getName();
					if (kind == SWT.MouseUp
							&& lName.contains("org.eclipse.ui.internal.quickaccess.QuickAccessDialog")) {
						return true;
					}
					if (lName.contains("org.eclipse.swt") || lName.contains("org.eclipse.ui")
							|| lName.contains("org.eclipse.jface")) {
						continue;
					}
				}
				return true;
			}
			String lName = listener.getClass().getName();
			if (lName.contains("org.eclipse.swt") || lName.contains("org.eclipse.ui")
					|| lName.contains("org.eclipse.jface")) {
				continue;
			}
			return true;
		}
		return false;
	}

	private void processMouseDown(Widget widget, Event event, RecordedEvent toRecording) {
		if ((widget instanceof TabFolder || widget instanceof CTabFolder)) {
			// Check for workbench internal element click
			boolean skip = false;
			if (TeslaCore.isEclipse4() && widget instanceof CTabFolder) {
				// eclipse 4.x
				skip = EclipseWorkbenchProvider.getProvider().extractViewOrEditorControl((CTabFolder) widget) != null;
			}

			if (!skip) {
				FindResult result = getLocator().findElement(widget, true, false, false);
				if (result != null && result.realElement.getKind().is(ElementKind.TabFolder)) {
					String tabName = null;
					boolean closeAction = false;
					if (widget instanceof TabFolder) {
						TabItem[] items = ((TabFolder) widget).getItems();
						for (TabItem tabItem : items) {
							Rectangle bounds = tabItem.getBounds();
							if (bounds.contains(event.x, event.y)) {
								// Set selection on selected widget.
								tabName = PlayerTextUtils.removeAcceleratorFromText(tabItem.getText());
								break;
							}
						}

					} else if (widget instanceof CTabFolder) {
						CTabItem[] items = ((CTabFolder) widget).getItems();
						for (CTabItem tabItem : items) {
							Rectangle bounds = tabItem.getBounds();
							if (bounds.contains(event.x, event.y)) {
								// Check for tab item close rect and record
								// close command for tab item.
								// Set selection on selected widget.
								tabName = PlayerTextUtils.removeAcceleratorFromText(tabItem.getText());
								Rectangle rect = TeslaSWTAccess.getCTabItemCloseRect(tabItem);
								if (rect != null) {
									if (rect.contains(event.x, event.y)) {
										closeAction = true;
									}
								}
								break;
							}
						}
					}
					if (tabName != null) {
						if (!closeAction) {
							if (widget instanceof CTabFolder) {
								ProcessCTabFolderItemSelection((CTabFolder) widget, result, tabName);
							}
						} else {
							CompositeUIElement v = new CompositeUIElement(result.element, getRecorder());
							ControlUIElement tabItem = v.tabItem(tabName);
							tabItem.close();
						}
					}
				}
			}
		}
		recordTextSetFocus(widget, event.button);

		if (widget instanceof org.eclipse.swt.widgets.List && ((Control) widget).isVisible())
			// This forces the element mapping to be created so we can retrieve
			// it later when it becomes invisible
			getLocator().findElement(widget, false, false, false);

		Listener[] listenersDown = widget.getListeners(SWT.MouseDown);
		if ((listenersDown != null && hasNonPlatformListeners(listenersDown, SWT.MouseDown))) {
			recordCellAccess(widget, event, RecordCellAccessSource.MouseDown);
		}
		Listener[] listenersUp = widget.getListeners(SWT.MouseUp);
		if (widget instanceof Label && ((listenersDown != null && hasNonPlatformListeners(listenersDown, SWT.MouseDown))
				|| (listenersUp != null && hasNonPlatformListeners(listenersUp, SWT.MouseUp)))) {
			FindResult result = getLocator().findElement(widget, true, false, false);
			if (result != null) {
				ControlUIElement e = new ControlUIElement(result.element, getRecorder());
				e.clickAndWait(false, event.stateMask);
				beforeTextState = "";
			}
		}
		lastEvents.add(toRecording);
	}

	private void ProcessCTabFolderItemSelection(CTabFolder tabFolder, FindResult result, String tabName) {
		boolean needSelection = true;
		if (lastTabItemSelection.containsKey(tabFolder)) {
			String v = lastTabItemSelection.get(tabFolder);
			if (v.equals(tabName)) {
				needSelection = false;
			}
		}
		if (needSelection) {
			lastTabItemSelection.put(tabFolder, tabName);
			CompositeUIElement v = new CompositeUIElement(result.element, getRecorder());
			ControlUIElement tabItem = v.tabItem(tabName);
			tabItem.clickAndWait();
		}
	}

	private void processClose(Widget widget) {
		Command lastCmd = getRecorder().getContainer().getLast();
		if (lastCmd instanceof Type && ((Type) lastCmd).isTraverse()
				&& ((Type) lastCmd).getCode() == SWT.TRAVERSE_ESCAPE) {
			return;
		}
		FindResult result = getLocator().findElement(widget, true, false, false);
		if (result != null) {
			ControlUIElement e = new ControlUIElement(result.element, getRecorder());
			e.close();
		}
	}

	// private void processActivateEvent(Widget widget, RecordedEvent
	// toRecording) {
	// boolean radioWidget = widget instanceof Button
	// && (((Button) widget).getStyle() & SWT.RADIO) != 0;
	// if (radioWidget) {
	// if (Platform.getOS().equals(Platform.OS_WIN32)
	// || checkType(widget, SWT.MouseUp, SWT.MouseDown)) {
	// FindResult result = getLocator().findElement(widget, true,
	// false, false);
	// if (result != null) {
	// // System.out.println("RESULT is:" + result);
	// ControlUIElement e = new ControlUIElement(result.element,
	// getRecorder());
	// e.clickAndWait();
	// lastEvents.clear();
	// }
	// // System.out.println("_5_Clean Events" + index++);
	// }
	// }
	// if (widget instanceof ExpandableComposite) {
	// System.out.println("Activate");
	// }
	// lastEvents.add(toRecording);
	// }

	List<RecordedEvent> takeMenuEvents(List<RecordedEvent> lastEvents2) {
		List<RecordedEvent> result = new ArrayList<RecordedEvent>();
		for (RecordedEvent e : lastEvents2) {
			if (e.widget instanceof Menu || e.widget instanceof MenuItem) {
				if (!(e.widget.isDisposed())) {
					result.add(e);
				}
			}
		}
		// Filter Hides for menus.
		return result;
	}

	public synchronized void clear() {
		SWTRecordingHelper.getHelper().clear();
		SWTModelMapper.initializeExtensions(getRecorder().getProcessors(ISWTModelMapperExtension.class));
		this.lastEvents.clear();
		// this.varCounters.clear();
		// this.variables.clear();
		getLocator().cleanMenuSources();
		lastTabItemSelection.clear();
		// activeCellEditors.clear();
		inStyledTextAction = false;
		lastEvent = null;
		lastTraverseEvent = null;
		pressed.clear();
	}

	public void recordDragEvent(Event event) {
		// System.err.println("DND:" + event);
		if (getRecorder() == null) {
			return;
		}
		if (!getRecorder().hasListeners()) {
			return;
		}
		dragSupport.processDND(event);
	}

	public void recordSWTDialog(Dialog dialog, Object result) {
		if (getRecorder() == null) {
			return;
		}
		if (!getRecorder().hasListeners()) {
			return;
		}
		SetSWTDialogInfo info = ProtocolFactory.eINSTANCE.createSetSWTDialogInfo();
		if (dialog instanceof FileDialog) {
			info.setKind(SWTDialogKind.FILE_SELECTOR);
		} else if (dialog instanceof DirectoryDialog) {
			info.setKind(SWTDialogKind.FOLDER_SELECTOR);
		} else if (dialog instanceof MessageBox) {
			info.setKind(SWTDialogKind.MESSAGE_BOX);
		} else if (dialog instanceof FontDialog) {
			info.setKind(SWTDialogKind.FONT_DIALOG);
		} else if (dialog instanceof ColorDialog) {
			info.setKind(SWTDialogKind.COLOR);
		} else {
			return;
		}
		if (result instanceof String[]) {
			for (String currentStr : (String[]) result) {
				if (dialog instanceof FileDialog) {
					processFileDialogValue(info, currentStr);
				} else {
					info.getPath().add(currentStr);
				}
			}
		} else if (result instanceof String) {
			if (dialog instanceof DirectoryDialog) {
				processFileDialogValue(info, (String) result);
			} else {
				info.getPath().add((String) result);
			}
		} else if (result instanceof Integer) {
			info.getPath().add(Integer.toString((Integer) result));
		} else if (result instanceof FontData) {
			info.getPath().add(((FontData) result).toString());
		} else if (result instanceof RGB) {
			RGB rgb = (RGB) result;
			info.getPath().add("" + rgb.red + "," + rgb.green + "," + rgb.blue);
		} else {
			info.getPath().clear();
		}
		getRecorder().safeExecuteCommand(info);
	}

	private void processFileDialogValue(SetSWTDialogInfo info, String pathStr) {
		// Make workspace relative path, if file are from workspace
		// and
		// add "workspace://" prefix
		try {
			Class.forName("org.eclipse.core.resources.ResourcesPlugin");
		} catch (Throwable e) {
			info.getPath().add(pathStr);
			return;
		}
		try {
			IPath workspaceLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation();
			File f = new File(pathStr);
			IPath path = new Path(f.getCanonicalPath());
			if (workspaceLocation.isPrefixOf(path)) {
				info.getPath().add("platform:/resource/"
						+ path.removeFirstSegments(workspaceLocation.segmentCount()).setDevice(null));
			} else {
				info.getPath().add(pathStr);
			}
		} catch (IOException e) {
			// TeslaCore.log(e);
		}
	}

	public void setFreeze(final boolean value, SetMode command) {
		// Display display = PlatformUI.getWorkbench().getDisplay();
		// if (display.isDisposed()) {
		// SWTEventManager.setFreeze(false);
		// return;
		// }
		// SWTEventManager.setIgnoreFreeze(player.getIgnored());
		// SWTEventManager.setFreeze(value);
	}

	public void recordStyledTextOffset(StyledText text) {
		if (inStyledTextAction) {
			return;
		}
		if (getRecorder() == null) {
			return;
		}
		if (!getRecorder().hasListeners()) {
			return;
		}
		if (!enabled) {
			enable();
		}
		// Check for extension to ignore recording against one of controls
		List<IRecordingProcessorExtension> list = getRecorder().getProcessors(IRecordingProcessorExtension.class);
		for (IRecordingProcessorExtension ext : list) {
			if (ext.isIgnored(text, SWT.Selection, null)) {
				return;
			}
		}
		if (isIgnored(text)) {
			return;
		}
		Context context = ContextManagement.currentContext();
		if (!context.contains("org.eclipse.swt.custom.StyledText", "doContent")
				&& !context.contains("org.eclipse.swt.custom.StyledText", "setContent")
				&& !context.contains("org.eclipse.swt.custom.StyledText", "reset")
				&& !context.contains("org.eclipse.swt.custom.StyledText", "handleKey")
				&& !context.contains("org.eclipse.swt.custom.StyledText", "setSelectionRange")
				&& !context.contains("org.eclipse.swt.custom.StyledText", "setSelection")
				&& !context.contains("org.eclipse.swt.custom.StyledText", "setStyleRanges")) {
			Command last = getRecorder().getContainer().getLast();
			if (last instanceof Type) {
				Type type = (Type) last;
				if (type.getCode() != null && type.getCode().intValue() == SWT.BS && type.getState() != null
						&& type.getState().intValue() == SWT.CTRL) {
					// This is Ctrl+Backspace. Ignore position change.
					return;
				}
				if (type.getCode() != null && type.getCode().intValue() == SWT.TAB && type.getState() != null
						&& type.getState().intValue() == 0) {
					// This is Tab. Ignore position change.
					return;
				}
			}
			FindResult element = getLocator().findElement(text, false, false, false);
			if (element != null) {
				TextUIElement textCtrl = new TextUIElement(element.element, getRecorder());
				int offset = text.getCaretOffset();
				int lineAtOffset = text.getLineAtOffset(offset);
				int offsetAtLine = text.getOffsetAtLine(lineAtOffset);
				if (!(last instanceof SetTextSelection
						&& EcoreUtil.equals(((SetTextSelection) last).getElement(), element.element))) {
					// Ignore after setSelection
					textCtrl.setTextOffset(lineAtOffset, offset - offsetAtLine);

				}
			}
		}
	}

	public void recordStyledTextActionAfter(StyledText text, int action) {
		inStyledTextAction = false;
	}

	public void recordStyledTextActionBefore(StyledText text, int action) {
		inStyledTextAction = true;
	}

	private TeslaRecorder recorder = null;

	public void initialize(final TeslaRecorder teslaRecorder) {
		this.recorder = teslaRecorder;
		this.dragSupport.setRecorder(teslaRecorder);
		// getLocator();// .initialize(teslaRecorder);
		teslaRecorder.addListener(this);
		final CommandPostProcessor pp = new CommandPostProcessor(teslaRecorder);
		teslaRecorder.addListener(new IRecordingModeListener() {

			public void changeMode(boolean inRecording) {
				if (inRecording) {
					teslaRecorder.addListener(pp);
				} else {
					teslaRecorder.removeListener(pp);
				}
			}
		});
	}

	public int getInitLevel() {
		return 10;
	};

	public void changeMode(boolean inRecording) {
		RecordingModeFeature.setRecordingModeActive(inRecording);
	}

	public void recordTabFolderEvent(Control tabControl, int eventId) {
		if (getRecorder() == null || !getRecorder().hasListeners()) {
			return;
		}

		FindResult result = null;

		if (tabControl instanceof CTabFolder) {
			CTabFolder tabFolder = (CTabFolder) tabControl;
			Widget w = EclipseWorkbenchProvider.getProvider().extractViewOrEditorControl(tabFolder);
			if (w != null) {
				Map<Control, SWTUIElement> references = EclipseWorkbenchProvider.getProvider()
						.getWorkbenchReference(getPlayer());
				SWTUIElement element = references.get(w);

				result = getLocator().findElement(element, false, false, true);
			}
		}

		if (result == null)
			result = getLocator().findElement(tabControl, false, false, true);

		if (result != null) {
			ControlUIElement ctrl = new ControlUIElement(result.element, getRecorder());
			switch (eventId) {
			case SWTEventManager.EVENT_TAB_MINIMIZE:
				ctrl.minimize();
				break;
			case SWTEventManager.EVENT_TAB_MAXIMIZE:
				ctrl.maximize();
				break;
			case SWTEventManager.EVENT_TAB_RESTORE:
				ctrl.restore();
				break;
			case SWTEventManager.EVENT_TAB_SHOW_LIST:
				ctrl.showTabList();
				break;
			}

		}
	}

	public void resetAssertSelection() {
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public IRecordingHelper getHelper() {
		return SWTRecordingHelper.getHelper();
	}

	public boolean isExclusiveEventHandle(Widget widget, int type, Event event) {
		return false;
	}

	public Event getCurrentEvent() {
		return currentEvent;
	}

	public void setCurrentEvent(Event event) {
		currentEvent = event;
	}

	@Override
	public void removeClosedShell(SWTUIElement wrappedShell) {
		SWTRecordingHelper.getHelper().remove(wrappedShell);		
	}
}
