/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.papyrus.xwt.core;
import java.lang.reflect.Method;
import org.eclipse.papyrus.xwt.IEventConstants;
import org.eclipse.papyrus.xwt.XWT;
import org.eclipse.papyrus.xwt.XWTMaps;
import org.eclipse.papyrus.xwt.annotation.Containment;
import org.eclipse.papyrus.xwt.internal.core.IEventController;
import org.eclipse.papyrus.xwt.internal.utils.LoggerManager;
import org.eclipse.papyrus.xwt.internal.utils.UserData;
import org.eclipse.papyrus.xwt.javabean.Controller;
import org.eclipse.papyrus.xwt.metadata.IEvent;
import org.eclipse.papyrus.xwt.metadata.IMetaclass;
import org.eclipse.papyrus.xwt.metadata.ModelUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
/**
*
* @author yyang (yves.yang@soyatec.com)
*/
public class EventTrigger extends TriggerBase {
private String sourceName;
private String routedEvent;
private TriggerAction[] actions = TriggerAction.EMPTY_ARRAY;
public String getSourceName() {
return sourceName;
}
public void setSourceName(String sourceName) {
this.sourceName = sourceName;
}
public String getRoutedEvent() {
return routedEvent;
}
public void setRoutedEvent(String routedEvent) {
this.routedEvent = routedEvent;
}
@Containment
public TriggerAction[] getActions() {
return actions;
}
public void setActions(TriggerAction[] actions) {
this.actions = actions;
}
@Override
public void prepare(Object target) {
String routedEvent = getRoutedEvent();
if(routedEvent != null) {
Object source = getElementByName(target, getSourceName());
IMetaclass metaclass = XWT.getMetaclass(source);
IEvent event = metaclass.findEvent(ModelUtils.normalizeEventName(routedEvent));
if(event == null) {
if(routedEvent != null && !routedEvent.toLowerCase().endsWith(IEventConstants.SUFFIX_KEY)) {
LoggerManager.log("Event " + routedEvent + " is not found in " + source.getClass().getName() + ". Please add a suffix \"Event\"!");
} else {
LoggerManager.log("Event " + routedEvent + " is not found in " + source.getClass().getName());
}
return;
}
for(TriggerAction triggerAction : getActions()) {
triggerAction.initialize(target);
}
String name = event.getName();
if("loadedevent".equalsIgnoreCase(name)) {
Widget widget = UserData.getWidget(source);
IEventController eventController = UserData.updateEventController(source);
RunablePaintAction paintRunnable = createPaintRunnable(source);
try {
Method method = paintRunnable.getClass().getDeclaredMethod("run", Object.class, Event.class);
eventController.setEvent(event, widget, paintRunnable, this, method);
} catch (Exception e) {
LoggerManager.log(e);
}
} else {
RunableAction runnable = createRunnable(source);
try {
runnable.setEventTrigger(event);
} catch (Exception e) {
LoggerManager.log(e);
}
}
}
}
public void on(Object target) {
}
protected RunableAction createRunnable(Object target) {
return new RunableAction(target);
}
protected RunablePaintAction createPaintRunnable(Object target) {
return new RunablePaintAction(target);
}
class RunablePaintAction {
protected Object target;
public RunablePaintAction(Object target) {
this.target = target;
}
public void run(Object object, Event event) {
for(TriggerAction triggerAction : EventTrigger.this.getActions()) {
triggerAction.run(event, target, null);
}
}
}
class RunableAction implements Listener, Runnable {
protected Object target;
private int count = 0;
boolean started = false;
boolean transition = false;
private Event event;
private int eventType;
public RunableAction(Object target) {
this.target = target;
}
public void run() {
count--;
if(count == 0 && !event.widget.isDisposed()) {
final Display display = event.widget.getDisplay();
display.syncExec(new Runnable() {
public void run() {
if(transition) {
for(TriggerAction triggerAction : getActions()) {
triggerAction.initialize(target);
}
} else {
for(TriggerAction triggerAction : getActions()) {
triggerAction.endFinalize(target);
}
}
display.removeFilter(eventType, RunableAction.this);
if(!event.widget.isDisposed()) {
event.widget.notifyListeners(eventType, event);
display.addFilter(eventType, RunableAction.this);
}
started = false;
}
});
}
}
protected void setEventTrigger(IEvent event) {
Widget widget = UserData.getWidget(target);
String name = event.getName();
this.eventType = Controller.getEventTypeByName(name);
if(this.eventType != SWT.None) {
widget.getDisplay().addFilter(this.eventType, this);
transition = (this.eventType == XWTMaps.getEvent("swt.move") || this.eventType == XWTMaps.getEvent("swt.resize"));
}
}
public void handleEvent(Event event) {
Widget widget = UserData.getWidget(target);
if(event.widget != widget || widget.isDisposed()) {
return;
}
if(started) {
event.type = SWT.NONE;
return;
}
// execute the animation actions first and then normal events
count = EventTrigger.this.getActions().length;
started = true;
try {
this.event = Controller.copy(event);
if(!transition) {
for(TriggerAction triggerAction : getActions()) {
triggerAction.initialize(target);
}
}
for(TriggerAction triggerAction : EventTrigger.this.getActions()) {
triggerAction.run(event, target, this);
}
} catch (Exception e) {
started = false;
}
event.type = SWT.NONE;
}
}
}