/****************************************************************************** * Copyright (c) 2011-2013, Linagora * * 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: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.services.su.editor.su; import java.util.ArrayList; import java.util.List; import javax.xml.namespace.QName; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.databinding.edit.EMFEditObservables; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.forms.widgets.FormToolkit; import com.ebmwebsourcing.petals.common.internal.provisional.databinding.LocalQNameToStringConverter; import com.ebmwebsourcing.petals.common.internal.provisional.databinding.NamespaceQNameToStringConverter; import com.ebmwebsourcing.petals.common.internal.provisional.emf.EObjectUIHelper; import com.ebmwebsourcing.petals.common.internal.provisional.formeditor.ISharedEdition; import com.ebmwebsourcing.petals.common.internal.provisional.utils.CommonUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.StringUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.SwtFactory; import com.sun.java.xml.ns.jbi.AbstractEndpoint; import com.sun.java.xml.ns.jbi.JbiPackage; import com.sun.java.xml.ns.jbi.Provides; /** * @author Mickael Istria - EBM WebSourcing */ public final class JBIEndpointUIHelpers { /** * Private constructor for utility class. */ private JBIEndpointUIHelpers() { // nothing } /** * A simple bean. */ public static class CommonUIBean { public Text itfNameText, itfNamespaceText, srvNameText, srvNamespaceText, edptText; public Label edptLabel; } /** * Creates the common widgets for the main tab in the JBI editor. * @param endpoint * @param toolkit * @param generalDetails * @param ise */ public static CommonUIBean createCommonEndpointUI( final AbstractEndpoint endpoint, FormToolkit toolkit, final Composite container, final ISharedEdition ise ) { // Controls String end = endpoint instanceof Provides ? " *:" : ":"; Color blueFont = container.getDisplay().getSystemColor( SWT.COLOR_DARK_BLUE ); SwtFactory.createLabel( container, "Interface Namespace *:", "The qualified name of the service contract" ).setForeground( blueFont ); final Text itfNamespaceText = SwtFactory.createSimpleTextField( container, true ); SwtFactory.createLabel( container, "Interface Name *:", "The qualified name of the service contract" ).setForeground( blueFont ); final Text itfNameText = SwtFactory.createSimpleTextField( container, true ); SwtFactory.createLabel( container, "Service Namespace" + end, "The qualified name of the service implementation" ).setForeground( blueFont ); final Text srvNamespaceText = SwtFactory.createSimpleTextField( container, true ); SwtFactory.createLabel( container, "Service Name" + end, "The qualified name of the service implementation" ).setForeground( blueFont ); final Text srvNameText = SwtFactory.createSimpleTextField( container, true ); Label edptLabel = SwtFactory.createLabel( container, "End-point Name" + end, "The name of the service deployment point" ); edptLabel.setForeground( blueFont ); Text edptText = SwtFactory.createSimpleTextField( container, true ); // Data-binding ise.getDataBindingContext().bindValue( SWTObservables.observeText( itfNameText ), EMFEditObservables.observeValue( ise.getEditingDomain(), endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__INTERFACE_NAME ), null, new UpdateValueStrategy().setConverter( new LocalQNameToStringConverter())); ise.getDataBindingContext().bindValue( SWTObservables.observeText( itfNamespaceText ), EMFEditObservables.observeValue(ise.getEditingDomain(), endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__INTERFACE_NAME), null, new UpdateValueStrategy().setConverter( new NamespaceQNameToStringConverter())); ise.getDataBindingContext().bindValue( SWTObservables.observeText( srvNameText ), EMFEditObservables.observeValue( ise.getEditingDomain(), endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__SERVICE_NAME ), null, new UpdateValueStrategy().setConverter( new LocalQNameToStringConverter())); ise.getDataBindingContext().bindValue( SWTObservables.observeText( srvNamespaceText ), EMFEditObservables.observeValue( ise.getEditingDomain(), endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__SERVICE_NAME ), null, new UpdateValueStrategy().setConverter( new NamespaceQNameToStringConverter())); ise.getDataBindingContext().bindValue( SWTObservables.observeDelayedValue( 200, SWTObservables.observeText( edptText, SWT.Modify )), EMFEditObservables.observeValue( ise.getEditingDomain(), endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__ENDPOINT_NAME )); // The data-binding handles the "model to target (widget)" parts. But not ALL the "widget to model" parts. // For QNames, in fact, the data-binding cannot be applied in this sense. We have to use a modify listener for this. createModifyListenerForQname( ise.getEditingDomain(), endpoint, itfNamespaceText, itfNameText, JbiPackage.Literals.ABSTRACT_ENDPOINT__INTERFACE_NAME, false ); createModifyListenerForQname( ise.getEditingDomain(), endpoint, srvNamespaceText, srvNameText, JbiPackage.Literals.ABSTRACT_ENDPOINT__SERVICE_NAME, false ); // PETALSSTUD-268: Wrong handling of empty end-point name // Do not set an empty end-point name in the model edptText.addModifyListener( new ModifyListener() { @Override public void modifyText( ModifyEvent e ) { String value = ((Text) e.widget).getText().trim(); if( value.length() > 0 ) return; Command cmd = EObjectUIHelper.createCustomSetCommand( ise.getEditingDomain(), endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__ENDPOINT_NAME, null ); ise.getEditingDomain().getCommandStack().execute( cmd ); } }); // PETALSSTUD-268 // Complete the UI effects final ModifyListener sameNsModifyListener = new ModifyListener() { @Override public void modifyText( ModifyEvent e ) { String serviceNs = srvNamespaceText.getText(); String interfaceNs = itfNamespaceText.getText(); Color fgColor; if( serviceNs.trim().length() > 0 && serviceNs.equals( interfaceNs )) fgColor = container.getDisplay().getSystemColor( SWT.COLOR_DARK_GREEN ); else fgColor = container.getDisplay().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND ); srvNamespaceText.setForeground( fgColor ); itfNamespaceText.setForeground( fgColor ); } }; FocusListener nsFocusListener = new FocusAdapter() { @Override public void focusGained( FocusEvent e ) { ((Text) e.widget).addModifyListener( sameNsModifyListener ); ((Text) e.widget).notifyListeners( SWT.Modify, new Event()); } @Override public void focusLost( FocusEvent e ) { ((Text) e.widget).removeModifyListener( sameNsModifyListener ); Color fgColor = container.getDisplay().getSystemColor( SWT.COLOR_WIDGET_FOREGROUND ); srvNamespaceText.setForeground( fgColor ); itfNamespaceText.setForeground( fgColor ); } }; itfNamespaceText.addFocusListener( nsFocusListener ); srvNamespaceText.addFocusListener( nsFocusListener ); // Prepare the result CommonUIBean result = new CommonUIBean(); result.edptText = edptText; result.itfNameText = itfNameText; result.itfNamespaceText = itfNamespaceText; result.srvNameText = srvNameText; result.srvNamespaceText = srvNamespaceText; result.edptLabel = edptLabel; return result; } /** * Creates a modify listener for QName widgets. * <p> * The data-binding handles the "model to target (widget)" parts. But not ALL the "widget to model" parts. * For QNames, in fact, the data-binding cannot be applied in this sense. We have to use a modify listener for this. * </p> * * @param domain * @param owner * @param namespaceText * @param nameText * @param attribute * @param useCustomSetCommand true to use a custom Set command, false for the usual SetCommand * TODO: replace this method by EMFEditObservables as soon as EMF 2.8.0 or 2.7.2 is out * @See EObjectUIHelper.createCustomSetCommand */ public static ActivableListener createModifyListenerForQname( final EditingDomain domain, final EObject owner, final Text namespaceText, final Text nameText, final EAttribute attribute, final boolean useCustomSetCommand ) { ActivableListener listener = new ActivableListener() { @Override public void handleEvent( Event e ) { // Not enabled, do nothing if( ! isEnabled()) return; // Save the caret position // Otherwise, the caret goes back to the position 0 Text focusedText = null; if( namespaceText.isFocusControl()) focusedText = namespaceText; else if( nameText.isFocusControl()) focusedText = nameText; int caretPosition = focusedText == null ? -1 : focusedText.getCaretPosition(); // Update the model? String ns = namespaceText.getText().trim(); String name = nameText.getText().trim(); Object o = owner.eGet( attribute ); boolean needsUpdate = false; if( o instanceof QName ) { String currentNs = ((QName) o).getNamespaceURI(); String currentName = ((QName) o).getLocalPart(); needsUpdate = ! CommonUtils.areEqual( ns, currentNs ) || ! CommonUtils.areEqual( name, currentName ); } if( needsUpdate ) { QName result; if( StringUtils.isEmpty( ns )) result = StringUtils.isEmpty( name ) ? null : new QName( name ); else result = new QName( ns, name ); Command cmd; if( useCustomSetCommand ) cmd = EObjectUIHelper.createCustomSetCommand( domain, owner, attribute, result ); else cmd = SetCommand.create( domain, owner, attribute, result ); domain.getCommandStack().execute( cmd ); } // Restore the caret position if( caretPosition != -1 ) focusedText.setSelection( caretPosition ); } }; namespaceText.addListener( SWT.Modify, listener ); nameText.addListener( SWT.Modify, listener ); return listener; } /** * Creates widgets automatically by introspecting EMF classes. * @param endpoint * @param toolkit * @param advancedDetails * @param ise * @param extensionClasses */ public static void createDefaultWidgetsByEIntrospection( AbstractEndpoint endpoint, FormToolkit toolkit, Composite advancedDetails, ISharedEdition ise, EClass... extensionClasses) { List<EStructuralFeature> toProcessFeaturesList = new ArrayList<EStructuralFeature>(); for (EClass extensionClass : extensionClasses) { for (EStructuralFeature feature : extensionClass.getEAllStructuralFeatures()) { if (isInPackage(feature, extensionClass) && feature instanceof EAttribute && !feature.getEType().equals(EcorePackage.Literals.EFEATURE_MAP_ENTRY)) toProcessFeaturesList.add( feature ); } } EStructuralFeature[] toProcessFeatures = toProcessFeaturesList.toArray(new EStructuralFeature[toProcessFeaturesList.size()] ); EObjectUIHelper.generateWidgets(endpoint, toolkit, advancedDetails, ise.getEditingDomain(), ise.getDataBindingContext(), true, toProcessFeatures); } /** * @param feature * @param extensionClass * @return */ private static boolean isInPackage(EStructuralFeature feature, EClass extensionClass) { return feature.eContainer() instanceof EClass && ((EClass)feature.eContainer()).getEPackage().equals(extensionClass.getEPackage()); } }