/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.ui.swt; import org.eclipse.core.runtime.Assert; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; 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.riena.ui.swt.facades.SWTFacade; /** * Forwards events from the source control to the target control. Listeners on * the target control will receive events from the source control, as if the * events had occurred on the target. * <p> * This class helps custom widgets handle events from child-widgets in a manner * that does not expose implementation details. * <p> * A custom widget that is implemented as a subclass of Composite (for example * ChoiceComposite or DatePickerComposite) containing other child-widgets (such * as Text or Button widgets), may use an instance of this class to forward * events from the child-widgets to the main-widget. Events occurring on the * child-widgets will be refired on the main-widget. This allows client code to * register listeners with the main-widget (which is exposed) without having to * add listeners to the child-widgets (which may be considered internal and thus * might not be exposed). * * @since 3.0 */ class EventForwarder implements Listener { private static final SWTFacade SWT_FACADE = SWTFacade.getDefault(); private final Control source; private final Control target; /** * Creates a class that automatically forwards events from the source * control to the target control. * <p> * Attachment and detachment of the forwarder is handled automatically. * * @param source * the source Control; never null * @param target * the target Control; never null */ EventForwarder(final Control source, final Control target) { Assert.isNotNull(target); final int[] eventTypes = { SWT.FocusIn, SWT.FocusOut, SWT.MenuDetect, SWT.DragDetect, SWT.MouseDoubleClick, SWTFacade.MouseMove, SWTFacade.MouseEnter, SWTFacade.MouseExit, SWTFacade.MouseHover, SWTFacade.MouseWheel, SWT.MouseDown, SWT.Traverse, }; for (final int type : eventTypes) { source.addListener(type, this); } this.source = source; this.target = target; } public void handleEvent(final Event event) { if (target.isDisposed()) { return; } Event e; switch (event.type) { case SWT.FocusIn: case SWT.FocusOut: case SWT.MenuDetect: notifyTarget(createEvent(event)); break; case SWT.DragDetect: case SWT.MouseDoubleClick: case SWTFacade.MouseMove: case SWTFacade.MouseEnter: case SWTFacade.MouseExit: case SWTFacade.MouseHover: case SWTFacade.MouseWheel: notifyTarget(createEvent(event)); event.type = SWT.None; break; case SWT.MouseDown: e = createEvent(event); notifyTarget(e); event.doit = e.doit; break; case SWT.Traverse: e = createEvent(event); notifyTarget(e); event.doit = e.doit; event.detail = e.detail; break; } } // helping methods ////////////////// private Event createEvent(final Event event) { final Event result = new Event(); result.display = event.display; result.widget = target; result.type = event.type; result.detail = event.detail; final Point pt = getDisplay().map(source, target, event.x, event.y); event.x = pt.x; event.y = pt.y; result.count = event.count; result.time = event.time; result.button = event.button; result.character = event.character; result.keyCode = event.keyCode; SWT_FACADE.copyEventKeyLocation(event, result); result.stateMask = event.stateMask; result.doit = event.doit; result.data = event.data; return result; } private Display getDisplay() { return source.getDisplay(); } private void notifyTarget(final Event event) { target.notifyListeners(event.type, event); } }