/******************************************************************************* * Copyright (c) 2008 Olivier Moises * * 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: * Olivier Moises- initial API and implementation *******************************************************************************/ package org.eclipse.wazaabi.ide.ui.propertysheets.eventhandlers; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EPackage; import org.eclipse.wazaabi.engine.edp.adapters.BindingAdapter; import org.eclipse.wazaabi.mm.core.widgets.CoreWidgetsPackage; import org.eclipse.wazaabi.mm.core.widgets.Widget; import org.eclipse.wazaabi.mm.edp.events.EDPEventsFactory; import org.eclipse.wazaabi.mm.edp.events.EDPEventsPackage; import org.eclipse.wazaabi.mm.edp.events.Event; import org.eclipse.wazaabi.mm.edp.events.PropertyChangedEvent; import org.eclipse.wazaabi.mm.edp.handlers.Binding; import org.eclipse.wazaabi.mm.edp.handlers.EDPHandlersFactory; import org.eclipse.wazaabi.mm.edp.handlers.EventHandler; import org.eclipse.wazaabi.mm.edp.handlers.Parameter; import org.eclipse.wazaabi.mm.edp.handlers.StringParameter; public abstract class AbstractBindingAction extends AbstractAction { public static final String TARGET_EPACKAGE_PARAMETER_NAME = "targetEPackage"; //$NON-NLS-1$ public static final String TARGET_ECLASS_PARAMETER_NAME = "targetEClass"; //$NON-NLS-1$ public static enum BindingDirection { WIDGET_TO_DOMAIN, DOMAIN_TO_WIDGET }; protected EClass getTargetWidgetEClass(EventHandler eventHandler) { String targetEpackage = getStringParameterValue(eventHandler, TARGET_EPACKAGE_PARAMETER_NAME); String targetEClass = getStringParameterValue(eventHandler, TARGET_ECLASS_PARAMETER_NAME); EPackage ePackage = EPackage.Registry.INSTANCE .getEPackage(targetEpackage); if (ePackage != null) { EClassifier eClassifier = ePackage.getEClassifier(targetEClass); if (eClassifier instanceof EClass) return (EClass) eClassifier; } return null; } protected String getEventDispatcherDefaultPropertyBoundFor(EClass eClass, BindingDirection bindingDirection) { if (eClass == CoreWidgetsPackage.Literals.TEXT_COMPONENT) { return "@text"; } else if (eClass == CoreWidgetsPackage.Literals.CHECK_BOX) { return "@selected"; } return null; } /** * Returns the list of events a eventDispatcher's binding is supposed to be * triggered by. If the bound property is not given but required, the method * returns null. * * @param eClass * The EventDispatcher eClass * @param boundProperty * the bound property when required (could be null). * @param bindingDirection * @return A list which could be empty. Null if the boundProperty was * required but not given. */ protected List<Event> getDefaultTriggeringEventsFor(EClass eClass, String boundProperty, BindingDirection bindingDirection) { List<Event> events = Collections.emptyList(); if (eClass == CoreWidgetsPackage.Literals.TEXT_COMPONENT) { if ("@text".equals(getEventDispatcherDefaultPropertyBoundFor( eClass, bindingDirection))) { events = new ArrayList<Event>(); if (bindingDirection == BindingDirection.WIDGET_TO_DOMAIN) { Event event1 = EDPEventsFactory.eINSTANCE.createEvent(); event1.setId("core:ui:focus:out"); Event event2 = EDPEventsFactory.eINSTANCE.createEvent(); event2.setId("core:ui:default:selection"); events.add(event1); events.add(event2); } else { if (boundProperty == null) return null; PropertyChangedEvent event1 = EDPEventsFactory.eINSTANCE .createPropertyChangedEvent(); event1.setPath(boundProperty); Event event2 = EDPEventsFactory.eINSTANCE.createEvent(); event2.setId("core:ui:refresh"); events.add(event1); events.add(event2); } } } else if (eClass == CoreWidgetsPackage.Literals.CHECK_BOX) { if ("@selected".equals(getEventDispatcherDefaultPropertyBoundFor( eClass, bindingDirection))) { events = new ArrayList<Event>(); if (bindingDirection == BindingDirection.WIDGET_TO_DOMAIN) { if (boundProperty == null) return null; PropertyChangedEvent event = EDPEventsFactory.eINSTANCE .createPropertyChangedEvent(); event.setPath(boundProperty); events.add(event); } else { if (boundProperty == null) return null; PropertyChangedEvent event1 = EDPEventsFactory.eINSTANCE .createPropertyChangedEvent(); event1.setPath(boundProperty); Event event2 = EDPEventsFactory.eINSTANCE.createEvent(); event2.setId("core:ui:refresh"); events.add(event1); events.add(event2); } } } return events; } protected String getCurrentContextKey() { return getDefaultContextKey(); } protected String getDefaultContextKey() { return "input"; } protected boolean areEquals(List<Event> events1, List<Event> events2) { // are both null or both not null ?? if (events1 == null) { if (events2 == null) return true; else return false; } else if (events2 == null) return false; // are both empty or both not empty ?? if (events1.isEmpty()) { if (events2.isEmpty()) return true; else return false; } else if (events2.isEmpty()) return false; if (events1.size() != events2.size()) return false; // Both lists have the same size, the comparison is easy for (Event event : events1) if (!contains(events2, event)) return true; return true; } /** * Returns true if events contains event. * * @param events * @param event * @return */ protected boolean contains(List<Event> events, Event event) { for (Event e : events) if (areEquals(e, event)) return true; return false; } /** * Returns true if the two events are equals. * * @param event1 * @param event2 * @return */ protected boolean areEquals(Event event1, Event event2) { if (event1 == null) { if (event2 == null) return true; else return false; } else if (event2 == null) return false; if (event1.eClass() == EDPEventsPackage.Literals.EVENT && event2.eClass() == EDPEventsPackage.Literals.EVENT) if (event1.getId() == null) return event2.getId() == null; else return event1.getId().equals(event2.getId()); if (event1.eClass() == EDPEventsPackage.Literals.PROPERTY_CHANGED_EVENT && event2.eClass() == EDPEventsPackage.Literals.PROPERTY_CHANGED_EVENT) if (((PropertyChangedEvent) event1).getPath() == null) return ((PropertyChangedEvent) event2).getPath() == null; else return ((PropertyChangedEvent) event1).getPath().equals( ((PropertyChangedEvent) event2).getPath()); return false; } protected Binding createDefaultBindingFor(EClass eClass, String domainBoundProperty, BindingDirection bindingDirection) { Binding binding = null; String defaultDispatcherBoundProperty = getEventDispatcherDefaultPropertyBoundFor( eClass, bindingDirection); if (defaultDispatcherBoundProperty == null || "".equals(defaultDispatcherBoundProperty)) return null; List<Event> defaultEvents = getDefaultTriggeringEventsFor(eClass, domainBoundProperty, bindingDirection); if (defaultEvents == null) return null; if (CoreWidgetsPackage.Literals.TEXT_COMPONENT == eClass || CoreWidgetsPackage.Literals.CHECK_BOX == eClass) { binding = EDPHandlersFactory.eINSTANCE.createBinding(); if (bindingDirection == BindingDirection.DOMAIN_TO_WIDGET) { addStringParameter(binding, BindingAdapter.SOURCE_PARAMETER_NAME, domainBoundProperty); addStringParameter(binding, BindingAdapter.TARGET_PARAMETER_NAME, defaultDispatcherBoundProperty); } else { addStringParameter(binding, BindingAdapter.SOURCE_PARAMETER_NAME, defaultDispatcherBoundProperty); addStringParameter(binding, BindingAdapter.TARGET_PARAMETER_NAME, domainBoundProperty); } } if (binding != null) binding.getEvents().addAll(defaultEvents); return binding; } protected void updateDomainBoundPropertyInBindingFor(Binding binding, EClass eClass, String newDomainBoundProperty, BindingDirection bindingDirection) { if (CoreWidgetsPackage.Literals.TEXT_COMPONENT == eClass || CoreWidgetsPackage.Literals.CHECK_BOX == eClass) { if (bindingDirection == BindingDirection.DOMAIN_TO_WIDGET) { String existingDomainBoundProperty = getStringParameterValue( binding, BindingAdapter.SOURCE_PARAMETER_NAME); updateStringParameterValue(binding, BindingAdapter.SOURCE_PARAMETER_NAME, newDomainBoundProperty); if (existingDomainBoundProperty != null && !"".equals(existingDomainBoundProperty)) for (Event event : binding.getEvents()) if (event instanceof PropertyChangedEvent && existingDomainBoundProperty .equals(((PropertyChangedEvent) event) .getPath())) { ((PropertyChangedEvent) event) .setPath(newDomainBoundProperty); return; } } else { updateStringParameterValue(binding, BindingAdapter.TARGET_PARAMETER_NAME, newDomainBoundProperty); } } } protected Parameter addStringParameter(Binding binding, String name, String value) { StringParameter parameter = EDPHandlersFactory.eINSTANCE .createStringParameter(); parameter.setName(name); parameter.setValue(value); binding.getParameters().add(parameter); return parameter; } protected String getBindingDomainBoundProperty(Binding binding, BindingDirection bindingDirection) { if (bindingDirection == BindingDirection.DOMAIN_TO_WIDGET) return getStringParameterValue(binding, BindingAdapter.SOURCE_PARAMETER_NAME); else return getStringParameterValue(binding, BindingAdapter.TARGET_PARAMETER_NAME); } protected String getBindingEventDispatcherBoundProperty(Binding binding, BindingDirection bindingDirection) { if (bindingDirection == BindingDirection.WIDGET_TO_DOMAIN) return getStringParameterValue(binding, BindingAdapter.SOURCE_PARAMETER_NAME); else return getStringParameterValue(binding, BindingAdapter.TARGET_PARAMETER_NAME); } /** * Finds an existing default binding in the given widget for this direction. * Returns null if no default binding has been found. * * @param widget * @param bindingDirection * @return */ protected Binding getExistingDefaultBinding(Widget widget, BindingDirection bindingDirection) { String widgetDefaultPropertyBound = getEventDispatcherDefaultPropertyBoundFor( widget.eClass(), bindingDirection); if (widgetDefaultPropertyBound == null || "".equals(widgetDefaultPropertyBound)) //$NON-NLS-1$ return null; for (EventHandler eventHandler : widget.getHandlers()) { if (eventHandler instanceof Binding) { Binding binding = (Binding) eventHandler; List<Event> expectedBindingTriggeringEvents = getDefaultTriggeringEventsFor( widget.eClass(), getBindingDomainBoundProperty(binding, bindingDirection), bindingDirection); if (expectedBindingTriggeringEvents == null) return null; if (!widgetDefaultPropertyBound .equals(getBindingEventDispatcherBoundProperty(binding, bindingDirection))) continue; if (areEquals(expectedBindingTriggeringEvents, binding.getEvents())) return binding; } } return null; } protected boolean isSameBinding(EClass eClass, String domainBoundProperty, String eventDispatcherBoundProperty, List<Object> converter, Binding binding, BindingDirection bindingDirection) { String bindingDomainBoundProperty = getBindingDomainBoundProperty( binding, bindingDirection); if (domainBoundProperty == null) { if (bindingDomainBoundProperty != null) return false; } else if (!domainBoundProperty.equals(bindingDomainBoundProperty)) return false; String bindingEventdispatcherBoundProperty = getBindingEventDispatcherBoundProperty( binding, bindingDirection); if (eventDispatcherBoundProperty == null) { if (bindingEventdispatcherBoundProperty != null) return false; } else if (!eventDispatcherBoundProperty .equals(bindingEventdispatcherBoundProperty)) return false; List<Event> expectedEvents = getDefaultTriggeringEventsFor(eClass, domainBoundProperty, bindingDirection); if (expectedEvents == null) return false; // We were not able to compute the list because // boundProperty is required but is null if (!areEquals(expectedEvents, binding.getEvents())) return false; // TODO : converters!! return true; } }