/******************************************************************************* * Copyright (c) 2005, 2012 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.bpel.ui.properties; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.bpel.model.BPELFactory; import org.eclipse.bpel.model.Expression; import org.eclipse.bpel.ui.IBPELUIConstants; import org.eclipse.bpel.ui.commands.CompoundCommand; import org.eclipse.bpel.ui.commands.SetCommand; import org.eclipse.bpel.ui.editors.xpath.ColorManager; import org.eclipse.bpel.ui.editors.xpath.XPathSourceViewerConfiguration; import org.eclipse.bpel.ui.expressions.IEditorConstants; import org.eclipse.core.resources.IMarker; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.text.source.VerticalRuler; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; /** * Base class with some shared behavior for details panes that edit a XPath expression. * @author Michal Chmielewski (michal.chmielewski@oracle.com) * @author Vincent Zurczak - EBM WebSourcing (Merge this class with TextSection, simplify it by only using the XPath viewer) * FIXME: There are probably cases that are not handled correctly. To be fixed on the fly. * FIXME: Undo is not supported correctly. */ public abstract class ExpressionSection extends BPELPropertySection { protected Composite fEditorArea ; protected StyledText expressionText; protected Font boldFont; protected String title; protected Label titleLabel; protected EStructuralFeature fStructuralFeature; protected AtomicBoolean modelUpdate = new AtomicBoolean( false ); /* * (non-Javadoc) * @see org.eclipse.bpel.ui.properties.BPELPropertySection * #addAllAdapters() */ @Override protected void addAllAdapters() { super.addAllAdapters(); Expression e = getExprFromModel(); if( e != null && this.fAdapters.length > 0 ) this.fAdapters[0].addToObject(e); } /** * When this method is called, the section has already been created. * * The widgets are available to be configured, however, the section may not be shown yet. * * The concept here is that we are reflecting the input selected in the UI. So the path that is taken * by this code must not create any re-doable commands, just set the widgets to what they are supposed to * be based on the model. */ @Override protected void basicSetInput( EObject newInput ) { this.modelUpdate.set( true ); super.basicSetInput(newInput); /** Figure out based in the input, what EMF structural feature we are setting */ this.fStructuralFeature = getStructuralFeature( newInput ); Expression exp = getExprFromModel(); Object o = exp != null ? exp.getBody() : null; String content = o == null ? "" : String.valueOf( o ); this.expressionText.setText( content ); this.expressionText.setSelection( content.length()); this.expressionText.setFocus(); this.modelUpdate.set( false ); } /** * The expression target is the target object on which we can execute * the SetCommand(target,object,structural-feature). * * In most cases, it is just the input of the section. But in some cases * the input if the section does not match the target, so sub-classes * may override this method. * * @return */ protected EObject getExpressionTarget() { return getInput(); } /** * @return */ protected String getExpressionType() { return IEditorConstants.ET_ANY ; } /** * Return the previously computed structural feature of the input object. * @return */ protected EStructuralFeature getStructuralFeature() { return this.fStructuralFeature; } /** * @param object * @return the structural feature to update on the model object */ protected abstract EStructuralFeature getStructuralFeature( EObject object ); /** * @return */ protected Expression getExprFromModel() { Expression result = null; EObject target = getExpressionTarget(); if( target != null ) { Object o = target.eGet( getStructuralFeature()); if( o instanceof Expression ) result = (Expression) o; } return result; } /** * @param expression * @return */ protected Expression getExpression4Target( Expression expression ) { return expression; } /** * Determines whether a notification affects this section. * @param n a notification * @return true if it affects this section, false otherwise */ protected boolean isBodyAffected( Notification n ) { return n.getOldValue() instanceof Expression || n.getNewValue() instanceof Expression || n.getNotifier() instanceof Expression || n.getFeature() == getStructuralFeature(); } /* * (non-Javadoc) * @see org.eclipse.bpel.ui.properties.BPELPropertySection * #isValidMarker(org.eclipse.core.resources.IMarker) */ @Override public final boolean isValidMarker( IMarker marker ) { // FIXME: the implementation may not be valid for all the sub-classes boolean result = false; try { String context = (String) marker.getAttribute( "href.context" ); result = "name".equals ( context ); } catch( Exception ex ) { // nothing } return result; } protected String getCommandLabel() { return IBPELUIConstants.CMD_EDIT_EXPRESSION; } /* * (non-Javadoc) * @see org.eclipse.bpel.ui.properties.BPELPropertySection * #createClient(org.eclipse.swt.widgets.Composite) */ @Override protected void createClient( Composite parent ) { // The top this.fEditorArea = getWidgetFactory().createComposite( parent ); this.fEditorArea.setLayout( new GridLayout()); if( this.title != null ) { // The font FontData[] fontData = parent.getDisplay().getSystemFont().getFontData(); fontData[ 0 ].setStyle( SWT.BOLD ); this.boldFont = new Font( parent.getDisplay(), fontData[ 0 ]); // The title this.titleLabel = this.fWidgetFactory.createLabel( this.fEditorArea, this.title); this.titleLabel.setFont(this.boldFont); } // The expression editor getWidgetFactory().createLabel( this.fEditorArea, "Edit the associated XPath Expression." ); Composite editor = getWidgetFactory().createComposite( this.fEditorArea, SWT.BORDER ); editor.setLayout( new FillLayout ()); GridData layoutData = new GridData( GridData.FILL_BOTH ); editor.setLayoutData( layoutData ); int style = SWT.V_SCROLL | SWT.MULTI | SWT.BORDER; final ISourceViewer viewer = new SourceViewer( editor, new VerticalRuler( 0 ), style ); ColorManager cManager = new ColorManager (); viewer.configure( new XPathSourceViewerConfiguration( cManager )); viewer.getTextWidget().setLayoutData( new GridData( GridData.FILL_BOTH )); IDocument document = new Document( "" ); viewer.setDocument( document ); this.expressionText = viewer.getTextWidget(); this.expressionText.addModifyListener( new ModifyListener() { @Override public void modifyText( ModifyEvent e ) { saveExpressionToModel(); } }); } /** * Saves the expression to the model. */ protected void saveExpressionToModel() { if( this.modelUpdate.get()) return; CompoundCommand result = new CompoundCommand(); Expression exp = BPELFactory.eINSTANCE.createCondition(); exp.setBody( this.expressionText != null ? this.expressionText.getText().trim() : "" ); result.add( new SetCommand( getExpressionTarget(), getExpression4Target( exp ) , getStructuralFeature())); getCommandFramework().execute( result ); } /* * (non-Javadoc) * @see org.eclipse.bpel.ui.properties.TextSection * #dispose() */ @Override public void dispose() { if( this.boldFont != null && ! this.boldFont.isDisposed()) this.boldFont.dispose(); super.dispose(); } }