/***************************************************************************** * Copyright (c) 2011 CEA LIST. * * 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: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.uml.properties.widgets; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; import org.eclipse.papyrus.uml.properties.expression.ExpressionList; import org.eclipse.papyrus.uml.properties.expression.ExpressionList.Expression; import org.eclipse.papyrus.uml.properties.messages.Messages; import org.eclipse.papyrus.views.properties.modelelement.DataSource; import org.eclipse.papyrus.views.properties.widgets.AbstractPropertyEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; /** * A Property Editor for editing UML Expressions. * UML Expressions maintain two lists ; one for the languages, and another one * for the expression bodies. These lists should be coherent. This editor * ensures that operations on the language list will not break the coherence * with the bodies list. For example, when a language is deleted, the * associated body is deleted as well. * * @author Camille Letavernier * * @see ExpressionLanguageEditor */ //TODO : Check support for Ctrl+Z (Is there one single command executed ?) //TODO : Check listeners on observables (If there is an external modification, is the value correctly refreshed ?) public class ExpressionEditor extends AbstractPropertyEditor implements Listener, ISelectionChangedListener, ICommitListener { private final ExpressionLanguageEditor languageEditor; private final Composite bodyEditorContainer; private IObservableList bodies; private Expression currentExpression = null; private DynamicBodyEditor bodyEditor; /** * Constructor. * * @param parent * The composite in which the widget is created * @param style * The style for the {@link DynamicBodyEditor} */ public ExpressionEditor(Composite parent, int style) { languageEditor = new ExpressionLanguageEditor(parent, SWT.NONE); bodyEditorContainer = new Composite(parent, SWT.NONE); bodyEditorContainer.setLayout(new FillLayout()); bodyEditor = new DynamicBodyEditor(bodyEditorContainer, style); bodyEditor.setLabel(Messages.ExpressionEditor_BodyLabel); bodyEditor.addChangeListener(this); languageEditor.getViewer().addSelectionChangedListener(this); languageEditor.addCommitListener(this); setEditor(languageEditor); } @Override public void setInput(DataSource input) { bodies = (IObservableList)input.getObservable("UML:OpaqueExpression:body"); //$NON-NLS-1$ super.setInput(input); } @Override protected void doBinding() { super.doBinding(); languageEditor.addCommitListener((ExpressionList)observableList); bodyEditor.setContext(input.getModelElement(propertyPath)); if(languageEditor.getViewer().getTree().getItemCount() > 0) { Object firstItem = languageEditor.getViewer().getTree().getItem(0).getData(); StructuredSelection selection = new StructuredSelection(firstItem); languageEditor.getViewer().setSelection(selection); } } /** * @return the IObservableList for this propertyEditor, or null if it is not * available */ @Override protected IObservableList getInputObservableList() { if(observableList == null) { observableList = new ExpressionList(super.getInputObservableList(), bodies); } return observableList; } public void handleEvent(Event event) { String newValue = bodyEditor.getValue(); if(newValue == null) { return; } currentExpression.setBody(newValue); ((ExpressionList)observableList).commit(bodyEditor); } public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if(selection.isEmpty()) { bodyEditor.display(null); } else if(selection instanceof IStructuredSelection) { IStructuredSelection sSelection = (IStructuredSelection)selection; currentExpression = (Expression)sSelection.getFirstElement(); bodyEditor.display(currentExpression); } //Force the layout of the widget after the new widget has been displayed bodyEditorContainer.getParent().layout(); } @Override protected void applyReadOnly(boolean readOnly) { languageEditor.setReadOnly(readOnly); bodyEditor.setReadOnly(readOnly); } public void commit(AbstractEditor editor) { //If the viewer has no selection, or if there is only one element, //automatically set the selection to the first element if(editor == languageEditor && observableList != null) { if(observableList.size() == 0) { languageEditor.getViewer().setSelection(StructuredSelection.EMPTY); } else if(observableList.size() == 1 || languageEditor.getViewer().getSelection().isEmpty()) { languageEditor.getViewer().setSelection(new StructuredSelection(observableList.get(0))); } } } }