blob: 44a7778187622c8e0bc10e68b46f85b57d05346b [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2012 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:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
*****************************************************************************/
package org.eclipse.efm.papyrus.view.property.concretesyntax.sheet;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.efm.formalml.xtext.ui.internal.XtextActivator;
import org.eclipse.efm.papyrus.view.property.concretesyntax.ActivatorXLIAProperties;
import org.eclipse.efm.papyrus.view.property.concretesyntax.internal.command.UpdateOperationCommand;
import org.eclipse.efm.papyrus.view.property.concretesyntax.internal.command.UpdateTransitionCommand;
import org.eclipse.efm.papyrus.view.property.concretesyntax.internal.job.ExecuteCommandJob;
import org.eclipse.efm.papyrus.view.property.concretesyntax.sheet.tooling.StyledTextWithUndoRedo;
import org.eclipse.efm.papyrus.view.property.concretesyntax.sheet.tooling.UndoStyledTextManager;
import org.eclipse.efm.papyrus.view.property.concretesyntax.sheet.tooling.listeners.EditorFocusListener;
import org.eclipse.efm.ui.resources.UIfmlResources;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.diagram.ui.properties.sections.AbstractModelerPropertySection;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.uml.xtext.integration.StyledTextXtextAdapter;
import org.eclipse.papyrus.uml.xtext.integration.core.ContextElementAdapter;
import org.eclipse.papyrus.uml.xtext.integration.core.ContextElementAdapter.IContextElementProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.SubActionBars;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Transition;
import org.eclipse.xtext.resource.XtextResource;
import com.google.inject.Injector;
/**
* Property view contribution for the ALF editor
*/
public class EditingPropertySection extends
AbstractModelerPropertySection implements IContextElementProvider {
private FormToolkit toolkit;
private Form form;
String fRefreshEditedTextBakup;
private StyledTextWithUndoRedo fStyledText;
UndoStyledTextManager fUndoManager;
SubActionBars fSubActionBars;
Action fRevertAction;
Action fCommitAction;
public final String COMMIT_ACTION_DEFAULT_TEXT = "Commit";
public final String COMMIT_ACTION_DEFAULT_DESCRIPTION = "Commit and Push to Model";
// private Button commitButton;
private StyledTextXtextAdapter styledTextAdapter;
final private ContextElementAdapter contextElementAdapter = new ContextElementAdapter(this);
protected boolean isUndo;
protected boolean isRedo;
private Injector xliaToolingInjector;
private EObject previousEObject;
private EditingPropertyCodeGenerator fCodeGenerator;
public EditingPropertySection() {
this.previousEObject = null;
this.xliaToolingInjector = XtextActivator.getInstance().getInjector(
XtextActivator.ORG_ECLIPSE_EFM_FORMALML_XTEXT_FORMALML);
this.fCodeGenerator = new EditingPropertyCodeGenerator();
}
public StyledText getEditor() {
return this.fStyledText;
}
protected boolean isEditableElement(EObject eObject) {
return( (this.eObject instanceof Transition) ||
(this.eObject instanceof Operation ) );
}
@Override
public void refresh() {
/* 1. Compute edit string */
fRefreshEditedTextBakup = "/*Error: serialization could not be computed*/";
if( this.eObject != null ) {
this.fCodeGenerator.reset();
fRefreshEditedTextBakup =
this.fCodeGenerator.performTransform( this.eObject );
}
/* 2. Update adapters placed over the xtext resource */
if( this.previousEObject != this.eObject ) {
this.updateXtextAdapters(this.fStyledText);
this.previousEObject = this.eObject;
if( isEditableElement(this.eObject) ){
// aboutToBeShown();
String commitText = COMMIT_ACTION_DEFAULT_TEXT;
String commitDescription = COMMIT_ACTION_DEFAULT_DESCRIPTION;
if( this.eObject instanceof Transition ) {
commitText ="Commit Transition";
commitDescription ="Commit Transition(guard, tguard, effect)";
}
else if( this.eObject instanceof Operation ) {
commitText = "Commit Operation";
commitDescription = "Commit Operation Opaque xLIA behavior method";
}
fCommitAction.setText(commitText);
fCommitAction.setToolTipText(commitDescription);
fCommitAction.setEnabled(true);
fRevertAction.setEnabled(true);
}
else {
// aboutToBeHidden();
fCommitAction.setText(COMMIT_ACTION_DEFAULT_TEXT);
fCommitAction.setToolTipText(COMMIT_ACTION_DEFAULT_DESCRIPTION);
fCommitAction.setEnabled(false);
fRevertAction.setEnabled(false);
}
fSubActionBars.updateActionBars();
}
/* 3. Set up editor content (fStyledText) */
this.fStyledText.setText(fRefreshEditedTextBakup);
if (this.fStyledText != null) {
this.fStyledText.setEditable(! isReadOnly());
}
}
/**
* Provide the object that will be edited through the editor.
* The particular case is for an edited that is an operation.
* In this situation we return the implementation
* (i.e. an activity) of this operation.
* This way it is transparent for the user that when editing an
* operation it can modify both the signature and its implementation.
*
* @param edited
* the object that is currently edited
*
* @return the real object that will be edited
*/
private Element getEditableObject(EObject edited){
if( edited instanceof Transition ) {
return (Transition)edited;
}
else if( edited instanceof Operation ) {
// return ((Operation)edited).getMethods().get(0);
return (Operation)edited;
}
return (Element)edited;
}
/**
* Provide the namespace of the element that is given as parameter
*
* @param element
* the element currently edited
*
* @return a namespace
*/
// private Namespace getNamespace(Element element){
// if(element!=null && element instanceof NamedElement){
// Element edited = this.getEditableObject(element);
// return ((NamedElement)edited).getNamespace();
// }
// return null;
// }
/**
* Associate a context in which the xtext resource containing an ALF model will be validated
*
* @param element
* the element currently edited
*/
private void installValidationContextFor(Element element) {
if (this.styledTextAdapter != null) {
XtextResource resource = this.styledTextAdapter.
getFakeResourceContext().getFakeResource();
if (resource != null) {
// ModelNamespaceFacade.getInstance().createValidationContext(
// resource, this.getNamespace(element));
}
}
}
@Override
public void aboutToBeHidden() {
super.aboutToBeHidden();
if (styledTextAdapter != null) {
styledTextAdapter.getFakeResourceContext().getFakeResource().eAdapters()
.remove(contextElementAdapter);
}
fSubActionBars.deactivate();
fSubActionBars.updateActionBars();
}
@Override
public void aboutToBeShown() {
super.aboutToBeShown();
fSubActionBars.activate();
fSubActionBars.updateActionBars();
}
@Override
public void dispose() {
super.dispose();
if (toolkit != null) {
toolkit.dispose();
}
}
@Override
public final void createControls(Composite parent,
TabbedPropertySheetPage aTabbedPropertySheetPage) {
toolkit = new FormToolkit(parent.getDisplay());
toolkit.setBorderStyle(SWT.BORDER);
super.createControls(parent, aTabbedPropertySheetPage);
GridDataFactory.fillDefaults().grab(true, true).applyTo(parent);
parent.setLayout(new GridLayout(1, true));
form = toolkit.createForm(parent);
toolkit.decorateFormHeading(form);
GridDataFactory.fillDefaults().grab(true, true).applyTo(form);
form.getBody().setLayout(new GridLayout(1, false));
createTextControl(form.getBody());
createSubActionBars(parent, aTabbedPropertySheetPage);
}
protected void createSubActionBars(final Composite parent,
TabbedPropertySheetPage aTabbedPropertySheetPage) {
fSubActionBars = new SubActionBars(
aTabbedPropertySheetPage.getSite().getActionBars() );
createCommitAction(parent, aTabbedPropertySheetPage);
createRevertAction(parent, aTabbedPropertySheetPage);
}
protected void createRevertAction(final Composite parent,
TabbedPropertySheetPage aTabbedPropertySheetPage) {
fRevertAction = new Action("Revert") {
@Override
public void run() {
super.run();
revertFromModel();
}
};
fRevertAction.setToolTipText("Reset edited element text");
fRevertAction.setImageDescriptor(UIfmlResources.getImageDescriptor(UIfmlResources.IMAGE__REVERT_ICON));
ActionContributionItem aci = new ActionContributionItem(fRevertAction);
aci.setMode(ActionContributionItem.MODE_FORCE_TEXT);
fSubActionBars.getToolBarManager().add( aci );
fSubActionBars.getMenuManager().add( fRevertAction );
}
protected void revertFromModel() {
refresh();
}
protected void createCommitAction(final Composite parent,
TabbedPropertySheetPage aTabbedPropertySheetPage) {
fCommitAction = new Action( COMMIT_ACTION_DEFAULT_TEXT ) {
@Override
public void run() {
super.run();
commitAndPushToModel();
}
};
fCommitAction.setToolTipText(COMMIT_ACTION_DEFAULT_DESCRIPTION);
fCommitAction.setImageDescriptor(UIfmlResources.getImageDescriptor(UIfmlResources.IMAGE__PUSH_ICON));
ActionContributionItem aci = new ActionContributionItem(fCommitAction);
aci.setMode(ActionContributionItem.MODE_FORCE_TEXT);
fSubActionBars.getToolBarManager().add( aci );
fSubActionBars.getMenuManager().add( fCommitAction );
}
protected void commitAndPushToModel() {
if( isEditableElement(this.eObject) ) {
if( this.eObject instanceof Transition ) {
commitAndPushTransitionToModel((Transition) this.eObject);
}
if( this.eObject instanceof Operation ) {
commitAndPushOperationToModel((Operation) this.eObject);
}
else if( this.eObject instanceof NamedElement ) {
System.out.println("TODO:> Commit and Push to Model: element " +
((NamedElement) this.eObject).getName());
}
else {
System.out.println("Unknown Commit and Push to Model ?");
}
}
}
public TransactionalEditingDomain getTransactionalEditingDomain() {
return getEditingDomain();
}
protected void commitAndPushTransitionToModel(Transition transitionContext) {
System.out.println("Commit and Push to Model: transition " +
transitionContext.getName());
final String editedtext = getEditor().getText();
if( (editedtext != null) && (! editedtext.equals(fRefreshEditedTextBakup)) ) {
UpdateTransitionCommand command = new UpdateTransitionCommand(
transitionContext, editedtext, fRefreshEditedTextBakup);
Job job = new ExecuteCommandJob(this, command);
// job.addJobChangeListener(new JobChangeAdapter() {
// @Override
// public void done(IJobChangeEvent event) {
// this.after();
// }
// });
job.setPriority(Job.SHORT);
job.schedule();
}
else {
System.out.println("End Commit Transition without change !!!");
}
}
protected void commitAndPushOperationToModel(Operation operationContext) {
System.out.println("Commit and Push to Model: operation " +
operationContext.getName());
final String editedtext = getEditor().getText();
if( (editedtext != null) && (! editedtext.equals(fRefreshEditedTextBakup)) ) {
UpdateOperationCommand command = new UpdateOperationCommand(
operationContext, editedtext, fRefreshEditedTextBakup);
Job job = new ExecuteCommandJob(this, command);
// job.addJobChangeListener(new JobChangeAdapter() {
// @Override
// public void done(IJobChangeEvent event) {
// this.after();
// }
// });
job.setPriority(Job.SHORT);
job.schedule();
}
else {
System.out.println("End Commit Operation without change !!!");
}
}
protected void createTextControl(final Composite parent) {
fStyledText = new StyledTextWithUndoRedo(parent,
SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.WRAP);
fStyledText.setAlwaysShowScrollBars(false);
GridDataFactory.fillDefaults().grab(true, true).hint(parent.getSize())
.applyTo(fStyledText);
fUndoManager = new UndoStyledTextManager(fStyledText);
fStyledText.addFocusListener(new EditorFocusListener(this));
}
protected void updateXtextAdapters(Control styledText) {
if (styledTextAdapter != null) {
styledTextAdapter.getFakeResourceContext().
getFakeResource().eAdapters().remove(contextElementAdapter);
}
styledTextAdapter = new StyledTextXtextAdapter(this.xliaToolingInjector);
styledTextAdapter.getFakeResourceContext().
getFakeResource().eAdapters().add(contextElementAdapter);
this.installValidationContextFor((Element)this.eObject);
styledTextAdapter.adapt((StyledText) styledText);
}
public EObject getContextObject() {
return this.getEditableObject(this.eObject);
}
@Override
protected boolean isReadOnly() {
EObject context = getContextObject();
return (context == null) || EMFHelper.isReadOnly(context) ||
super.isReadOnly() || (! isEditableElement(this.eObject));
}
}