| /***************************************************************************** |
| * Copyright (c) 2021 CEA LIST and others. |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Asma Smaoui (CEA LIST) asma.smaoui@cea.fr - Initial API and implementation |
| * |
| *****************************************************************************/ |
| package org.eclipse.papyrus.aas.ui.widgets; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| |
| import org.eclipse.core.internal.runtime.InternalPlatform; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.emf.common.command.Command; |
| import org.eclipse.emf.common.command.CompoundCommand; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EModelElement; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.xmi.XMLResource; |
| import org.eclipse.emf.edit.command.AddCommand; |
| import org.eclipse.emf.edit.command.SetCommand; |
| import org.eclipse.emf.edit.domain.EditingDomain; |
| import org.eclipse.emf.transaction.RecordingCommand; |
| import org.eclipse.emf.transaction.RollbackException; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.editparts.AbstractEditPart; |
| import org.eclipse.gmf.runtime.common.core.command.ICommand; |
| import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry; |
| import org.eclipse.gmf.runtime.emf.type.core.IElementType; |
| import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; |
| import org.eclipse.gmf.runtime.notation.View; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.nebula.widgets.nattable.NatTable; |
| import org.eclipse.papyrus.aas.ConceptDescription; |
| import org.eclipse.papyrus.aas.HasSemantics; |
| import org.eclipse.papyrus.aas.Reference; |
| import org.eclipse.papyrus.aas.profile.ui.Activator; |
| import org.eclipse.papyrus.aas.ui.utils.IAASElementTypes; |
| import org.eclipse.papyrus.infra.core.resource.EditingDomainServiceFactory; |
| import org.eclipse.papyrus.infra.core.resource.ModelSet; |
| import org.eclipse.papyrus.infra.core.services.ServiceDescriptor; |
| import org.eclipse.papyrus.infra.core.services.ServiceDescriptor.ServiceTypeKind; |
| import org.eclipse.papyrus.infra.core.services.ServiceException; |
| import org.eclipse.papyrus.infra.core.services.ServiceMultiException; |
| import org.eclipse.papyrus.infra.core.services.ServiceStartKind; |
| import org.eclipse.papyrus.infra.core.services.ServicesRegistry; |
| import org.eclipse.papyrus.infra.emf.gmf.command.GMFtoEMFCommandWrapper; |
| import org.eclipse.papyrus.infra.emf.gmf.util.GMFUnsafe; |
| import org.eclipse.papyrus.infra.emf.nattable.selection.EObjectSelectionExtractor; |
| import org.eclipse.papyrus.infra.emf.utils.EMFHelper; |
| import org.eclipse.papyrus.infra.nattable.manager.table.INattableModelManager; |
| import org.eclipse.papyrus.infra.nattable.manager.table.NattableModelManager; |
| import org.eclipse.papyrus.infra.nattable.manager.table.TreeNattableModelManager; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.NattableFactory; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.NattablePackage; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.Table; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxis.IAxis; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxisconfiguration.AxisManagerRepresentation; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxisconfiguration.EStructuralFeatureValueFillingConfiguration; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxisconfiguration.IAxisConfiguration; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxisconfiguration.TableHeaderAxisConfiguration; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxisprovider.AbstractAxisProvider; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxisprovider.NattableaxisproviderFactory; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableaxisprovider.NattableaxisproviderPackage; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattableconfiguration.TableConfiguration; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattablestyle.BooleanValueStyle; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattablestyle.NattablestyleFactory; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattablestyle.NattablestylePackage; |
| import org.eclipse.papyrus.infra.nattable.model.nattable.nattablestyle.Style; |
| import org.eclipse.papyrus.infra.nattable.resource.TableResourceHelper; |
| import org.eclipse.papyrus.infra.nattable.tree.ITreeItemAxisHelper; |
| import org.eclipse.papyrus.infra.nattable.utils.HeaderAxisConfigurationManagementUtils; |
| import org.eclipse.papyrus.infra.nattable.utils.NamedStyleConstants; |
| import org.eclipse.papyrus.infra.nattable.utils.NattableModelManagerFactory; |
| import org.eclipse.papyrus.infra.nattable.utils.TableHelper; |
| import org.eclipse.papyrus.infra.nattable.utils.TableResourceConstants; |
| import org.eclipse.papyrus.infra.properties.contexts.Property; |
| import org.eclipse.papyrus.infra.properties.ui.modelelement.CompositeModelElement; |
| import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource; |
| import org.eclipse.papyrus.infra.properties.ui.modelelement.DataSourceChangedEvent; |
| import org.eclipse.papyrus.infra.properties.ui.modelelement.EMFModelElement; |
| import org.eclipse.papyrus.infra.properties.ui.modelelement.IDataSourceListener; |
| import org.eclipse.papyrus.infra.properties.ui.modelelement.ModelElement; |
| import org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor; |
| import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; |
| import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; |
| import org.eclipse.papyrus.infra.widgets.creation.IAtomicOperationExecutor; |
| import org.eclipse.papyrus.uml.properties.modelelement.UMLNotationModelElement; |
| import org.eclipse.papyrus.uml.properties.widgets.TreeNattablePropertyEditor; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.CLabel; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite; |
| import org.eclipse.uml2.uml.Element; |
| import org.eclipse.uml2.uml.util.UMLUtil; |
| |
| /** |
| * The property editor for the nattable widget. |
| */ |
| @SuppressWarnings("restriction") |
| public class AASNattablePropertyEditor extends AbstractPropertyEditor { |
| |
| /** |
| * The save options to use. |
| * |
| * @deprecated since 3.0. Use TableResourceFactory. |
| */ |
| @Deprecated |
| private static final Map<Object, Object> saveOptions = new HashMap<>(); |
| |
| static { |
| saveOptions.put(Resource.OPTION_SAVE_ONLY_IF_CHANGED, Resource.OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER); |
| saveOptions.put(Resource.OPTION_LINE_DELIMITER, Resource.OPTION_LINE_DELIMITER_UNSPECIFIED); |
| saveOptions.put(XMLResource.OPTION_SAVE_TYPE_INFORMATION, true); |
| } |
| |
| /** |
| * The folders in which we will save the table configured by the user. |
| */ |
| private static final String TABLES_PREFERENCES_FOLDER_NAME = "tables";//$NON-NLS-1$ |
| |
| /** |
| * The file in which the table will be saved. |
| * |
| * It doesn't work using .notation as extension file. In this case, the commands are not executed, because it is read-only, but why ? |
| * |
| * @deprecated since 3.0. Use TableResourceConstants.TABLE_FILE_EXTENSION. |
| */ |
| @Deprecated |
| @SuppressWarnings("unused") |
| private static final String FILE_EXTENSION = "table";//$NON-NLS-1$ |
| |
| /** |
| * The composite. |
| */ |
| protected Group self = null;; |
| |
| /** |
| * The table configuration URI. |
| */ |
| private URI tableConfigURI = null; |
| |
| /** |
| * The nattable widget. |
| */ |
| protected NatTable natTableWidget = null; |
| |
| /** |
| * The nattable manager. |
| */ |
| protected INattableModelManager nattableManager = null; |
| |
| /** |
| * The dispose listener. |
| */ |
| private DisposeListener nattableDisposeListener = null; |
| |
| /** |
| * The data source listener. |
| */ |
| private IDataSourceListener dataSourceListener; |
| |
| /** |
| * The service registry used to manipulate the table |
| */ |
| private ServicesRegistry serviceRegistry = null; |
| |
| /** |
| * the resource where the table will be saved |
| */ |
| private Resource resource = null; |
| |
| /** |
| * the edited Papyrus table |
| */ |
| private Table table = null; |
| |
| /** |
| * the table configuration |
| */ |
| private TableConfiguration tableConfiguration = null; |
| |
| /** |
| * if <code>true</code> we register table configuration by eClass and not only by table type |
| */ |
| private boolean registerTableConfigurationByEClass = false; |
| |
| /** |
| * Constructor. |
| * |
| * @param parent |
| * The parent composite. |
| * @param style |
| * The style of the composite. |
| */ |
| public AASNattablePropertyEditor(final Composite parent, final int style) { |
| self = new Group(parent, SWT.NONE); |
| FillLayout fillLayout = new FillLayout(); |
| fillLayout.marginHeight = 10; |
| fillLayout.marginWidth = 10; |
| self.setLayout(fillLayout); |
| } |
| |
| /** |
| * |
| * @param newValue |
| * if <code>true</code> we register the table configuration by type AND by the ECLass of the selected element |
| * @since 2.0 |
| */ |
| public final void setRegisterTableConfigurationByEClass(final boolean newValue) { |
| this.registerTableConfigurationByEClass = newValue; |
| } |
| |
| /** |
| * Set the table URI. |
| * |
| * @param uri |
| * The URI of the table (as String). |
| * @since 2.0 |
| */ |
| public void setTableConfigurationURI(final String uri) { |
| tableConfigURI = URI.createURI(uri); |
| checkInput(); |
| } |
| |
| /** |
| * Get the table configuration URI. |
| * |
| * @return The table configuration URI. |
| * @since 2.0 |
| * |
| */ |
| public String getTableConfigurationURI() { |
| return tableConfigURI == null ? null : tableConfigURI.toString(); |
| } |
| |
| /** |
| * Set the table URI. |
| * |
| * @param uri |
| * The URI of the table (as String). |
| * |
| * @deprecated since 2.0, use setTableConfigurationURI instead |
| */ |
| @Deprecated |
| public void setTableURI(final String uri) { |
| setTableConfigurationURI(uri); |
| } |
| |
| /** |
| * Get the table configuration URI. |
| * |
| * @return The table configuration URI. |
| * @deprecated since 2.0, use getTableConfigurationUri instead |
| */ |
| @Deprecated |
| public String getTableURI() { |
| return getTableConfigurationURI(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor#checkInput() |
| */ |
| @Override |
| protected void checkInput() { |
| if (tableConfigURI != null) { |
| super.checkInput(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor#doBinding() |
| */ |
| @Override |
| protected void doBinding() { |
| super.doBinding(); |
| |
| // final ModelElement modelElement = input.getModelElement(propertyPath); |
| ModelElement modelElement = null; |
| final ModelElement modelElementHassemantic = input.getModelElement("AAS:HasSemantics:semanticId"); |
| final ModelElement modelElementConceptDescription = input.getModelElement("AAS:ConceptDescription:isCaseOf"); |
| // final ModelElement modelElementdataSpecification = input.getModelElement("AAS:HasDataSpecification:dataSpecification"); |
| // final ModelElement modelElementMultiLanguageProp = input.getModelElement("AAS:MultiLanguageProperty:valueId"); |
| final List<ModelElement> modelElements = new ArrayList(Arrays.asList(modelElementHassemantic, modelElementConceptDescription)); |
| // final List<ModelElement> modelElements = new ArrayList(Arrays.asList(modelElementHassemantic, modelElementConceptDescription, modelElementdataSpecification, modelElementMultiLanguageProp)); |
| if (modelElements.stream().filter(Objects::nonNull).findAny().isPresent()) { |
| modelElement = modelElements.stream().filter(Objects::nonNull).findAny().get(); |
| } |
| // The data needed to create the table |
| final List<Object> rows = new ArrayList<>(); |
| EObject sourceElement = null; |
| EStructuralFeature feature = null; |
| |
| // Manage the data needed for the table creation |
| if (modelElement instanceof CompositeModelElement) { |
| if (!((CompositeModelElement) modelElement).getSubElements().isEmpty()) { |
| if (((CompositeModelElement) modelElement).getSubElements().get(0) instanceof UMLNotationModelElement) { |
| final EModelElement eModelElement = ((UMLNotationModelElement) ((CompositeModelElement) modelElement).getSubElements().get(0)).getEModelElement(); |
| // Fill the list of views to determinate the axis to display (cannot be created without the table editing domain) |
| for (ModelElement subModelElement : ((CompositeModelElement) modelElement).getSubElements()) { |
| if (subModelElement instanceof UMLNotationModelElement) { |
| rows.add(((UMLNotationModelElement) subModelElement).getEModelElement()); |
| } |
| } |
| sourceElement = eModelElement; |
| } else if (((CompositeModelElement) modelElement).getSubElements().get(0) instanceof EMFModelElement) { |
| final EMFModelElement emfModelElement = (EMFModelElement) ((CompositeModelElement) modelElement).getSubElements().get(0); |
| sourceElement = emfModelElement.getSource(); |
| feature = emfModelElement.getFeature(getLocalPropertyPath()); |
| } |
| } |
| } else if (modelElement instanceof UMLNotationModelElement) { |
| final EModelElement eModelElement = ((UMLNotationModelElement) modelElement).getEModelElement(); |
| // Fill the list of views to determinate the axis to display (cannot be created without the table editing domain) |
| rows.add(eModelElement); |
| sourceElement = eModelElement; |
| } else if (modelElement instanceof EMFModelElement) { |
| final EMFModelElement emfModelElement = (EMFModelElement) modelElement; |
| EObject source = emfModelElement.getSource(); |
| |
| // case of hasSemantic |
| if (source != null && source instanceof HasSemantics) { |
| if (((HasSemantics) source).getSemanticId() != null) { |
| source = ((HasSemantics) source).getSemanticId(); |
| } else { |
| |
| |
| Element element = UMLUtil.getBaseElement(source); |
| HasSemantics has = (HasSemantics) source; |
| getOperationExecutor(element).execute(new Runnable() { |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void run() { |
| |
| if (element instanceof Element) { |
| |
| Element container = element.getModel(); |
| EditingDomain domain = EMFHelper.resolveEditingDomain(container); |
| IElementType referenceElementType = ElementTypeRegistry.getInstance().getType(IAASElementTypes.REFERENCE_ID); |
| CreateElementRequest request = null; |
| |
| request = new CreateElementRequest((TransactionalEditingDomain) domain, container, referenceElementType); |
| |
| IElementEditService provider = ElementEditServiceUtils.getCommandProvider(container); |
| ICommand createReference = provider.getEditCommand(request); |
| if (createReference.canExecute()) { |
| domain.getCommandStack().execute(new GMFtoEMFCommandWrapper(createReference)); |
| Object result = createReference.getCommandResult().getReturnValue(); |
| Reference reference = getReference(result); |
| has.setSemanticId(reference); |
| } else { |
| System.out.println("can not execute command"); |
| } |
| } |
| |
| } |
| }, "message"); |
| // Create the Reference if the sourceElement is a HasSemantic |
| source = ((HasSemantics) source).getSemanticId(); |
| } |
| |
| } // case of ConceptDescription |
| |
| else if (source != null && source instanceof ConceptDescription) { |
| if (((ConceptDescription) source).getIsCaseOf() != null && !((ConceptDescription) source).getIsCaseOf().isEmpty()) { |
| source = ((ConceptDescription) source).getIsCaseOf().get(0); |
| } else { |
| |
| |
| Element element = UMLUtil.getBaseElement(source); |
| ConceptDescription cons = (ConceptDescription) source; |
| getOperationExecutor(element).execute(new Runnable() { |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void run() { |
| |
| if (element instanceof Element) { |
| |
| Element container = element.getModel(); |
| EditingDomain domain = EMFHelper.resolveEditingDomain(container); |
| IElementType referenceElementType = ElementTypeRegistry.getInstance().getType(IAASElementTypes.REFERENCE_ID); |
| CreateElementRequest request = null; |
| |
| request = new CreateElementRequest((TransactionalEditingDomain) domain, container, referenceElementType); |
| |
| IElementEditService provider = ElementEditServiceUtils.getCommandProvider(container); |
| ICommand createReference = provider.getEditCommand(request); |
| if (createReference.canExecute()) { |
| domain.getCommandStack().execute(new GMFtoEMFCommandWrapper(createReference)); |
| Object result = createReference.getCommandResult().getReturnValue(); |
| Reference reference = getReference(result); |
| cons.getIsCaseOf().add(reference); |
| } else { |
| System.out.println("can not execute command"); |
| } |
| } |
| |
| } |
| }, "message"); |
| // Create the Reference if the sourceElement is a HasSemantic |
| source = ((ConceptDescription) source).getIsCaseOf().get(0); |
| } |
| } |
| |
| if (!(source instanceof Element)) { |
| final Element baseElement = UMLUtil.getBaseElement(source); |
| if (baseElement != null) {// in other case we will get an exeption somewhere |
| source = baseElement; |
| } |
| } |
| sourceElement = source; |
| if (emfModelElement.getSource() instanceof HasSemantics) { |
| feature = emfModelElement.getFeature("semanticId"); |
| } else if (emfModelElement.getSource() instanceof ConceptDescription) { |
| feature = emfModelElement.getFeature("isCaseOf"); |
| } |
| // rows.add(emfModelElement); |
| } else { |
| displayError("Invalid table context"); //$NON-NLS-1$ |
| return; |
| } |
| |
| // Create the widgets |
| createWidgets(sourceElement, feature, rows); |
| } |
| |
| /** |
| * This allow to create the widgets. |
| * |
| * @param sourceElement |
| * The source Element. |
| * @param feature |
| * The feature. |
| * @param rows |
| * The rows of the table. |
| * @since 2.0 |
| */ |
| protected void createWidgets(final EObject sourceElement, final EStructuralFeature feature, final Collection<?> rows) { |
| createPreviousWidgets(sourceElement, feature); |
| createTableWidget(sourceElement, feature, rows); |
| createFollowingWidgets(sourceElement, feature); |
| |
| // Configure the layout and the layout data |
| configureLayout(sourceElement); |
| self.layout(); |
| } |
| |
| /** |
| * This allow to create the widgets displayed before the table widget. |
| * |
| * @param sourceElement |
| * The source Element. |
| * @param feature |
| * The feature. |
| * @since 2.0 |
| */ |
| protected void createPreviousWidgets(final EObject sourceElement, final EStructuralFeature feature) { |
| // To implement if some widgets are needed before the table widget |
| } |
| |
| /** |
| * This allow to create the table widget or to reuse a table previously used in the property view |
| * |
| * @param sourceElement |
| * The source Element. |
| * @param feature |
| * The parent structural feature. |
| * @param rows |
| * The rows of the table. |
| * |
| * @since 2.0 |
| */ |
| protected void createTableWidget(final EObject sourceElement, final EStructuralFeature feature, final Collection<?> rows) { |
| // 1. we initialize a service registry |
| if (this.serviceRegistry == null) { |
| try { |
| this.serviceRegistry = createServiceRegistry(sourceElement); |
| } catch (Exception e) { |
| // Activator.log.error(e); |
| } |
| } |
| |
| if (this.serviceRegistry == null) { |
| displayError("Cannot initialize the service registry"); //$NON-NLS-1$ |
| return; |
| } |
| |
| // 2. get the editing domain |
| TransactionalEditingDomain domain = getTableEditingDomain(); |
| if (domain == null) { |
| displayError("Cannot found the editing domain"); //$NON-NLS-1$ |
| return; |
| } |
| |
| // 3. Create the table or get an existing one |
| this.table = getOrCreateTable(sourceElement, feature, rows); |
| |
| if (this.table == null) { |
| displayError("Cannot initialize the table"); //$NON-NLS-1$ |
| return; |
| } |
| |
| // 4. we configure the table |
| final CompoundCommand cc = new CompoundCommand("Configure table command");//$NON-NLS-1$ |
| |
| // 4.1 we register it into a resource if required |
| if (this.table.eResource() == null) { |
| cc.append(addTableToResource(domain, this.resource, this.table)); |
| } |
| |
| // 4.2 we configure the table |
| configureTable(domain, this.table, sourceElement, feature, rows, cc); |
| |
| if (!cc.canExecute()) { |
| displayError("The table can't be initialized");//$NON-NLS-1$ |
| return; |
| } |
| |
| final ResourceSet resourceSet = getResourceSet(); |
| // Bug 502160: Remove the resource from the resource set to execute the command without using the editing command stack |
| resourceSet.getResources().remove(this.resource); |
| try { |
| GMFUnsafe.write(domain, cc); |
| } catch (InterruptedException e) { |
| // Activator.log.error(e); |
| } catch (RollbackException e) { |
| // Activator.log.error(e); |
| } finally { |
| // Bug 502160: Re-add the removed resource before the command execute |
| resourceSet.getResources().add(this.resource); |
| } |
| |
| if (this.table.getContext() == null) { |
| displayError("The context of the table hasn't be set");//$NON-NLS-1$ |
| return; |
| } |
| // 5. Create the widget |
| this.nattableManager = NattableModelManagerFactory.INSTANCE.createNatTableModelManager(this.table, new EObjectSelectionExtractor()); |
| this.natTableWidget = createNatTableWidget(this.nattableManager, self, SWT.NONE, rows); |
| |
| self.addDisposeListener(getDisposeListener()); |
| // Configure the layout and the layout data |
| configureLayout(); |
| |
| ((NattableModelManager) nattableManager).refreshNatTable(); |
| } |
| |
| /** |
| * This allow to create the widgets displayed after the table widget. |
| * |
| * @param sourceElement |
| * The source Element. |
| * @param feature |
| * The feature. |
| * @since 2.0 |
| */ |
| protected void createFollowingWidgets(final EObject sourceElement, final EStructuralFeature feature) { |
| // To implement if some widgets are needed after the table widget |
| } |
| |
| /** |
| * |
| * @param parent |
| * the composite parent |
| * @param style |
| * the style to use to create the nattable widget |
| * @param rows |
| * the initial rows |
| * @return |
| * the created nattable widget |
| * @since 2.0 |
| */ |
| protected NatTable createNatTableWidget(final INattableModelManager manager, final Composite parent, final int style, Collection<?> rows) { |
| NatTable natTable = manager.createNattable(self, style, null); |
| natTable.setBackground(self.getBackground()); |
| return natTable; |
| } |
| |
| /** |
| * |
| * @param sourceElement |
| * the source element used to initiatiaze the table |
| * @return |
| * the service registry to use for the table displayed in property view |
| * @throws Exception |
| * |
| * Duplicated code from org.eclipse.papyrus.junit.utils.rules.ModelSetFixture |
| * @since 2.0 |
| */ |
| protected ServicesRegistry createServiceRegistry(EObject sourceElement) throws Exception { |
| ServicesRegistry result = new ServicesRegistry(); |
| |
| result.add(ModelSet.class, 10, new ModelSet()); |
| |
| ServiceDescriptor desc = new ServiceDescriptor(TransactionalEditingDomain.class, EditingDomainServiceFactory.class.getName(), ServiceStartKind.STARTUP, 10);// , Collections.singletonList(ResourceSet.class.getName())); |
| desc.setServiceTypeKind(ServiceTypeKind.serviceFactory); |
| desc.setClassBundleID(Activator.PLUGIN_ID); |
| result.add(desc); |
| |
| result.startRegistry(); |
| return result; |
| } |
| |
| |
| /** |
| * This allows to configure the tree table. |
| * |
| * @param nattableManager |
| * The nattable model manager. |
| * @param sourceElement |
| * The source Element. |
| * @param feature |
| * The feature. |
| * @param rows |
| * The rows of the table. |
| * @deprecated since 2.0, moved into {@link TreeNattablePropertyEditor} |
| */ |
| @Deprecated |
| protected void configureTreeTable(final TreeNattableModelManager nattableManager, final EObject sourceElement, final EStructuralFeature feature, final Collection<?> rows) { |
| // Do nothing |
| } |
| |
| /** |
| * This allows to configure the layout and the layout data. |
| * |
| * @deprecated since 2.0.0 |
| */ |
| @Deprecated |
| protected void configureLayout() { |
| // Adapt the group to the table preferred size |
| final GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| |
| // The preferred height of the nattable calculate it for each row (even if some are hidden) |
| // So to calculate the correct height for the composite : |
| // - Calculate the header height |
| // - Calculate the body height |
| // Add these values and add some extra to have correct displays |
| final int headerHeight = natTableWidget.getPreferredHeight() - nattableManager.getBodyLayerStack().getRowHideShowLayer().getPreferredHeight(); |
| final int bodyHeight = nattableManager.getBodyLayerStack().getRowHideShowLayer().getHeight(); |
| // 16px must be added because of the left area slider |
| final int extra = 20 + 16; |
| data.minimumHeight = headerHeight + bodyHeight + extra; |
| self.setLayoutData(data); |
| |
| self.layout(); |
| natTableWidget.layout(); |
| } |
| |
| /** |
| * This allows to configure the layout and the layout data. |
| * |
| * @param sourceElement |
| * The source element. |
| * @since 2.0 |
| */ |
| protected void configureLayout(final EObject sourceElement) { |
| // must be done first! |
| ((NattableModelManager) nattableManager).refreshNatTable(); |
| |
| // Configure the size of the parent container |
| configureSize(sourceElement); |
| |
| natTableWidget.layout(); |
| } |
| |
| /** |
| * This allows to configure the size of the parent container. |
| * |
| * @param sourceElement |
| * The source element. |
| * @since 2.0 |
| */ |
| protected void configureSize(final EObject sourceElement) { |
| // Adapt the group to the table preferred size |
| final GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| |
| // The preferred height of the nattable calculate it for each row (even if some are hidden) |
| // So to calculate the correct height for the composite : |
| // - Calculate the header height |
| // - Calculate the body height |
| // Add these values and add some extra to have correct displays |
| final int headerHeight = natTableWidget.getPreferredHeight() - nattableManager.getBodyLayerStack().getRowHideShowLayer().getPreferredHeight(); |
| final int bodyHeight = nattableManager.getBodyLayerStack().getRowHideShowLayer().getHeight(); |
| // 16px must be added because of the left area slider |
| final int extra = 20 + 16; |
| data.minimumHeight = headerHeight + bodyHeight + extra; |
| self.setLayoutData(data); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor#updateDescription(java.lang.String) |
| */ |
| @Override |
| protected void updateDescription(String description) { |
| self.setToolTipText(description); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor#updateLabel(java.lang.String) |
| */ |
| @Override |
| public void updateLabel(final String label) { |
| if (showLabel) { |
| self.setText(getLabel()); |
| } |
| } |
| |
| /** |
| * This allow to display the error. |
| * |
| * @param message |
| * The error message to display. |
| */ |
| protected void displayError(final String message) { |
| final CLabel label = new CLabel(self, SWT.NONE); |
| label.setText(message); |
| label.setImage(org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage("icons/error.gif")); //$NON-NLS-1$ |
| } |
| |
| /** |
| * |
| * @param sourceElement |
| * the source Element |
| * @param synchronizedFeature |
| * the synchronized feature |
| * @param rows |
| * @return |
| * the existing table or the new created one |
| * @since 2.0 |
| */ |
| protected Table getOrCreateTable(final EObject sourceElement, final EStructuralFeature synchronizedFeature, final Collection<?> rows) { |
| Table returnedTable = null; |
| final TableConfiguration tableConfiguration = getTableConfiguration(); |
| if (tableConfiguration == null) { |
| return null; |
| } |
| |
| if (this.serviceRegistry != null) { |
| URI tableURI = createTableURI(sourceElement, tableConfiguration); |
| final ResourceSet resourceSet = getResourceSet(); |
| // Install the table support to manage the table as a correct Resource |
| TableResourceHelper.installTableSupport(resourceSet); |
| ((ModelSet) resourceSet).createModels(tableURI); |
| boolean exists = resourceSet.getURIConverter().exists(tableURI, Collections.emptyMap()); |
| if (exists) { |
| this.resource = resourceSet.getResource(tableURI, true); |
| } else { |
| this.resource = resourceSet.createResource(tableURI); |
| } |
| |
| Iterator<EObject> iter = this.resource.getContents().iterator(); |
| while (iter.hasNext() && returnedTable == null) {// the resource should contains only 1 table and this one will get the good type |
| EObject object = iter.next(); |
| if (object instanceof Table) { |
| TableConfiguration configuration = ((Table) object).getTableConfiguration(); |
| if (configuration != null && configuration.getType() != null && configuration.getType().equals(getTableConfiguration().getType())) { |
| returnedTable = (Table) object; |
| } |
| } |
| } |
| |
| if (null == returnedTable) { |
| returnedTable = createTable(sourceElement, synchronizedFeature); |
| } |
| |
| } |
| |
| return returnedTable; |
| } |
| |
| /** |
| * |
| * @return |
| * the resource set to use to load/store emf files |
| * @since 2.0 |
| */ |
| protected ResourceSet getResourceSet() { |
| ResourceSet set = null; |
| if (this.serviceRegistry != null) { |
| try { |
| set = this.serviceRegistry.getService(ModelSet.class); |
| } catch (ServiceException e) { |
| // Activator.log.error(e); |
| } |
| } |
| return set; |
| } |
| |
| /** |
| * Create URI for the table configuration. |
| * |
| * @param sourceElement |
| * The source Element |
| * @param tableConfiguration |
| * The tableConfiguration |
| * @return The URI to use to save and load the table |
| * @since 2.0 |
| */ |
| protected URI createTableURI(final EObject sourceElement, final TableConfiguration tableConfiguration) { |
| // If the source element has an EClass, the table configuration file name |
| // will be suffixed by the name of its eClass |
| setRegisterTableConfigurationByEClass((sourceElement != null) && (sourceElement.eClass() != null)); |
| |
| IPath preferencePath = InternalPlatform.getDefault().getStateLocation(Activator.getContext().getBundle(), true); |
| // we create a folder to save the tables used by the property view and we start to create the name of the model owning the table |
| preferencePath = preferencePath.append(TABLES_PREFERENCES_FOLDER_NAME).append(tableConfiguration.getType()); |
| |
| // we continue to build the path, adding the good suffix to the name of the model |
| final StringBuilder b = new StringBuilder().append(preferencePath.toPortableString()); |
| if (this.registerTableConfigurationByEClass) { |
| ModelElement modelElement = input.getModelElement(propertyPath); |
| EClass eClass = null; |
| if (modelElement instanceof CompositeModelElement) { |
| CompositeModelElement compoModelElement = (CompositeModelElement) modelElement; |
| for (ModelElement next : compoModelElement.getSubElements()) { |
| if ((next instanceof UMLNotationModelElement) |
| || (next instanceof EMFModelElement)) { |
| modelElement = next; |
| break; |
| } |
| } |
| } |
| |
| if (modelElement instanceof UMLNotationModelElement) { |
| EditPart part = ((UMLNotationModelElement) modelElement).getEditPart(); |
| eClass = EMFHelper.getEObject(part).eClass(); |
| } else if (modelElement instanceof EMFModelElement) { |
| EObject source = ((EMFModelElement) modelElement).getSource(); |
| if (source != null) { |
| eClass = source.eClass(); |
| } |
| } |
| |
| if (eClass != null) { |
| b.append("_"); //$NON-NLS-1$ |
| b.append(eClass.getName()); |
| } |
| } |
| |
| URI newURI = URI.createFileURI(b.toString()).appendFileExtension(TableResourceConstants.TABLE_FILE_EXTENSION); |
| return newURI; |
| } |
| |
| |
| /** |
| * This allow to create the nattable. |
| * |
| * @param sourceElement |
| * The context element. |
| * @param synchronizedFeature |
| * The synchronized feature. |
| * @param rows |
| * The rows of the table. |
| * @return The created table. |
| * |
| * @since 2.0 |
| */ |
| protected Table createTable(final EObject sourceElement, final EStructuralFeature synchronizedFeature) { |
| final TableConfiguration tableConfiguration = getTableConfiguration(); |
| if (tableConfiguration == null) { |
| return null; |
| } |
| final Table table = NattableFactory.eINSTANCE.createTable(); |
| table.setTableConfiguration(tableConfiguration); |
| final Property property = getModelProperty(); |
| if (property != null) { |
| String description = property.getDescription(); |
| if (description != null) { |
| table.setDescription(description); |
| } |
| } |
| |
| table.setName(getLabel()); |
| // for table used in property view, the kindId was null, because it is given by the AF. So we propose to use the type for kindId |
| table.setTableKindId(table.getTableConfiguration().getType()); |
| |
| AbstractAxisProvider rowProvider = tableConfiguration.getDefaultRowAxisProvider(); |
| if (rowProvider == null) { |
| rowProvider = NattableaxisproviderFactory.eINSTANCE.createMasterObjectAxisProvider(); |
| } else { |
| rowProvider = EcoreUtil.copy(rowProvider); |
| } |
| |
| AbstractAxisProvider columnProvider = tableConfiguration.getDefaultColumnAxisProvider(); |
| if (columnProvider == null) { |
| columnProvider = NattableaxisproviderFactory.eINSTANCE.createSlaveObjectAxisProvider(); |
| } else { |
| columnProvider = EcoreUtil.copy(columnProvider); |
| } |
| |
| table.getColumnAxisProvidersHistory().add(columnProvider); |
| table.setCurrentColumnAxisProvider(columnProvider); |
| table.getRowAxisProvidersHistory().add(rowProvider); |
| table.setCurrentRowAxisProvider(rowProvider); |
| for (final Style style : tableConfiguration.getStyles()) { |
| table.getStyles().add(EcoreUtil.copy(style)); |
| } |
| |
| // for the table displayed in property view, we want to use all the available place, so we add a specific named style each time |
| // We manage it with percentage named style |
| BooleanValueStyle columnsWidthAsPercentage = (BooleanValueStyle) table.getNamedStyle(NattablestylePackage.eINSTANCE.getBooleanValueStyle(), NamedStyleConstants.COLUMNS_WIDTH_AS_PERCENTAGE); |
| // if the name style already exists we do nothing |
| if (null == columnsWidthAsPercentage) { |
| // for the table displayed in property view, we want to use all the available place, so we add a specific named style each time |
| BooleanValueStyle fillStyle = (BooleanValueStyle) table.getNamedStyle(NattablestylePackage.eINSTANCE.getBooleanValueStyle(), NamedStyleConstants.FILL_COLUMNS_SIZE); |
| // if the name style already exists we do nothing |
| if (null == fillStyle) { |
| columnsWidthAsPercentage = NattablestyleFactory.eINSTANCE.createBooleanValueStyle(); |
| columnsWidthAsPercentage.setName(NamedStyleConstants.COLUMNS_WIDTH_AS_PERCENTAGE); |
| columnsWidthAsPercentage.setBooleanValue(true); |
| table.getStyles().add(columnsWidthAsPercentage); |
| } |
| } |
| |
| // for the table displayed in property view, we expand all directly |
| BooleanValueStyle expandStyle = (BooleanValueStyle) table.getNamedStyle(NattablestylePackage.eINSTANCE.getBooleanValueStyle(), NamedStyleConstants.EXPAND_ALL); |
| // if the name style already exists we do nothing |
| if (null == expandStyle) { |
| expandStyle = NattablestyleFactory.eINSTANCE.createBooleanValueStyle(); |
| expandStyle.setName(NamedStyleConstants.EXPAND_ALL); |
| expandStyle.setBooleanValue(true); |
| table.getStyles().add(expandStyle); |
| } |
| return table; |
| } |
| |
| /** |
| * This allow to create the nattable. |
| * |
| * @param sourceElement |
| * The context element. |
| * @param synchronizedFeature |
| * The synchronized feature. |
| * @param rows |
| * The rows of the table. |
| * @return The created table. |
| * |
| * @deprecated since 2.0, use the same method without the collections of rows as arguments. Rows are set later in the new implementation |
| */ |
| @Deprecated |
| protected Table createTable(final EObject sourceElement, final EStructuralFeature synchronizedFeature, final Collection<?> rows) { |
| final TableConfiguration tableConfiguration = getTableConfiguration(); |
| if (tableConfiguration == null) { |
| return null; |
| } |
| final Table table = NattableFactory.eINSTANCE.createTable(); |
| table.setTableConfiguration(tableConfiguration); |
| final Property property = getModelProperty(); |
| if (property != null) { |
| String description = property.getDescription(); |
| if (description != null) { |
| table.setDescription(description); |
| } |
| } |
| |
| table.setName(getLabel()); |
| |
| AbstractAxisProvider rowProvider = tableConfiguration.getDefaultRowAxisProvider(); |
| if (rowProvider == null) { |
| rowProvider = NattableaxisproviderFactory.eINSTANCE.createMasterObjectAxisProvider(); |
| } else { |
| rowProvider = EcoreUtil.copy(rowProvider); |
| } |
| |
| AbstractAxisProvider columnProvider = tableConfiguration.getDefaultColumnAxisProvider(); |
| if (columnProvider == null) { |
| columnProvider = NattableaxisproviderFactory.eINSTANCE.createSlaveObjectAxisProvider(); |
| } else { |
| columnProvider = EcoreUtil.copy(columnProvider); |
| } |
| |
| if (null != synchronizedFeature) { |
| TableHeaderAxisConfiguration rowHeaderAxisconfig = tableConfiguration.getRowHeaderAxisConfiguration(); |
| for (IAxisConfiguration axisConfig : rowHeaderAxisconfig.getOwnedAxisConfigurations()) { |
| if (axisConfig instanceof EStructuralFeatureValueFillingConfiguration) { |
| ((EStructuralFeatureValueFillingConfiguration) axisConfig).setListenFeature(synchronizedFeature); |
| } |
| } |
| } |
| table.getColumnAxisProvidersHistory().add(columnProvider); |
| table.setCurrentColumnAxisProvider(columnProvider); |
| table.getRowAxisProvidersHistory().add(rowProvider); |
| table.setCurrentRowAxisProvider(rowProvider); |
| for (final Style style : tableConfiguration.getStyles()) { |
| table.getStyles().add(EcoreUtil.copy(style)); |
| } |
| |
| return table; |
| } |
| |
| /** |
| * |
| * @return |
| * the editing domain to use |
| * |
| * @since 2.0 |
| */ |
| protected TransactionalEditingDomain getTableEditingDomain() { |
| try { |
| return this.serviceRegistry.getService(TransactionalEditingDomain.class); |
| } catch (ServiceException e) { |
| Activator.log.error(e); |
| } |
| return null; |
| } |
| |
| /** |
| * Get the table configuration (from the table configuration URI). |
| * |
| * @return The table configuration. |
| */ |
| protected TableConfiguration getTableConfiguration() { |
| if (this.tableConfiguration == null) { |
| ResourceSet resourceSet = getResourceSet(); |
| if (resourceSet != null) { |
| try { |
| this.tableConfiguration = (TableConfiguration) EMFHelper.loadEMFModel(resourceSet, this.tableConfigURI); |
| } catch (Exception ex) { |
| Activator.log.error("Invalid table configuration", ex); //$NON-NLS-1$ |
| } |
| } |
| } |
| return this.tableConfiguration; |
| } |
| |
| /** |
| * This allow to create the dispose listener for the nattable table manager. |
| * |
| * @return The dispose nattable manager listener. |
| */ |
| protected DisposeListener getDisposeListener() { |
| if (null == this.nattableDisposeListener) { |
| this.nattableDisposeListener = new DisposeListener() { |
| |
| @Override |
| public void widgetDisposed(DisposeEvent e) { |
| disposeListener(); |
| } |
| }; |
| } |
| return nattableDisposeListener; |
| } |
| |
| /** |
| * This allows to dispose the listeners. |
| * |
| * @since 2.0 |
| */ |
| protected void disposeListener() { |
| if (AASNattablePropertyEditor.this.serviceRegistry != null) { |
| // we dispose it to avoid unecessary refresh |
| if (null != this.nattableManager) { |
| this.nattableManager.dispose(); |
| } |
| if (null != this.natTableWidget) { |
| this.natTableWidget.dispose(); |
| } |
| if (AASNattablePropertyEditor.this.resource != null) { |
| try { |
| AASNattablePropertyEditor.this.resource.save(null); |
| } catch (IOException e1) { |
| Activator.log.error(e1); |
| } |
| } |
| try { |
| AASNattablePropertyEditor.this.serviceRegistry.disposeRegistry(); |
| } catch (ServiceMultiException e1) { |
| Activator.log.error(e1); |
| } |
| AASNattablePropertyEditor.this.serviceRegistry = null; |
| AASNattablePropertyEditor.this.table = null; |
| |
| } |
| } |
| |
| /** |
| * |
| * @param domain |
| * the editing domain |
| * @param table |
| * the table to clean before dispose |
| * @return |
| * the command to use to clean the table before disposing it |
| * @since 2.0 |
| * @deprecated since 3.0 |
| */ |
| @Deprecated |
| protected CompoundCommand getDisposeTableCommand(final TransactionalEditingDomain domain, final Table table) { |
| CompoundCommand disposeCommand = new CompoundCommand("Command used to clean the table before disposing it"); //$NON-NLS-1$ |
| disposeCommand.append(SetCommand.create(domain, table, NattablePackage.eINSTANCE.getTable_Context(), null)); |
| disposeCommand.append(SetCommand.create(domain, table, NattablePackage.eINSTANCE.getTable_Owner(), null)); |
| // assuming the table is synchronized and not inverted : |
| disposeCommand.append(SetCommand.create(domain, table.getCurrentRowAxisProvider(), NattableaxisproviderPackage.eINSTANCE.getAxisProvider_Axis(), Collections.emptyList())); |
| |
| return disposeCommand; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor#unhookDataSourceListener(org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource) |
| */ |
| @Override |
| protected void unhookDataSourceListener(DataSource oldInput) { |
| oldInput.removeDataSourceListener(getDataSourceListener()); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.papyrus.infra.properties.ui.widgets.AbstractPropertyEditor#hookDataSourceListener(org.eclipse.papyrus.infra.properties.ui.modelelement.DataSource) |
| */ |
| @Override |
| protected void hookDataSourceListener(DataSource newInput) { |
| newInput.addDataSourceListener(getDataSourceListener()); |
| } |
| |
| public static Reference getReference(Object result) { |
| Reference ref = null; |
| if (result != null) { |
| ref = UMLUtil.getStereotypeApplication((Element) result, Reference.class); |
| } |
| return ref; |
| |
| } |
| |
| public static ConceptDescription getConceptDescription(EObject sourceElement) { |
| ConceptDescription conceptDescription = null; |
| if (sourceElement != null && sourceElement instanceof Element) { |
| conceptDescription = UMLUtil.getStereotypeApplication((Element) sourceElement, ConceptDescription.class); |
| } |
| return conceptDescription; |
| |
| } |
| |
| |
| public static HasSemantics gethasSemantic(EObject sourceElement) { |
| HasSemantics HasSem = null; |
| if (sourceElement != null && sourceElement instanceof Element) { |
| HasSem = UMLUtil.getStereotypeApplication((Element) sourceElement, HasSemantics.class); |
| } |
| return HasSem; |
| |
| } |
| |
| /** |
| * This allow to create the data source listener. |
| * |
| * @return The created data source listener. |
| */ |
| private IDataSourceListener getDataSourceListener() { |
| if (dataSourceListener == null) { |
| dataSourceListener = new IDataSourceListener() { |
| |
| @Override |
| public void dataSourceChanged(final DataSourceChangedEvent event) { |
| // bug 494537 - The diagram selection changed, but the property view has not been disposed |
| disposeListener(); |
| // Bug 492560: The self children control was not all disposed correclty |
| if (null != self) { |
| if (self.getChildren().length > 0) { |
| for (Control control : self.getChildren()) { |
| control.dispose(); |
| } |
| } |
| self.removeDisposeListener(getDisposeListener()); |
| nattableDisposeListener = null; |
| self.layout(); |
| } |
| // Get the datasource |
| final DataSource dataSource = event.getDataSource(); |
| final StructuredSelection selection = (StructuredSelection) dataSource.getSelection(); |
| |
| // Manage the context selection |
| final List<Object> contexts = new ArrayList<>(selection.size()); |
| EObject sourceElement = null; |
| final Iterator<?> selectionIterator = selection.iterator(); |
| while (selectionIterator.hasNext()) { |
| Object selectedObject = selectionIterator.next(); |
| if (selectedObject instanceof AbstractEditPart) { |
| // contexts.add(((AbstractEditPart) selectedObject).getModel()); |
| } else { |
| // contexts.add(selectedObject); |
| } |
| |
| if (sourceElement == null) { |
| // An edit-part in GMF can resolve its semantic element |
| // to something different to the element referenced by |
| // its notation view, so don't rely on the notation |
| sourceElement = EMFHelper.getEObject(selectedObject); |
| } |
| } |
| |
| // Get the model element |
| if (sourceElement != null) { |
| ModelElement modelElement = null; |
| if (gethasSemantic(sourceElement) != null) { |
| modelElement = dataSource.getModelElement("AAS:HasSemantics:semanticId"); |
| } else if (getConceptDescription(sourceElement) != null) { |
| modelElement = dataSource.getModelElement("AAS:ConceptDescription:isCaseOf"); |
| } |
| sourceElement = getEObjectAsTableContext(sourceElement); // Convert to table context |
| EStructuralFeature feature = null; |
| if (modelElement instanceof CompositeModelElement) { |
| if (!((CompositeModelElement) modelElement).getSubElements().isEmpty()) { |
| if (((CompositeModelElement) modelElement).getSubElements().get(0) instanceof EMFModelElement) { |
| final EMFModelElement emfModelElement = (EMFModelElement) ((CompositeModelElement) modelElement).getSubElements().get(0); |
| if (emfModelElement instanceof HasSemantics) { |
| feature = emfModelElement.getFeature("semanticId"); |
| } else if (emfModelElement instanceof ConceptDescription) { |
| feature = emfModelElement.getFeature("isCaseOf"); |
| } |
| |
| } |
| } |
| } else if (modelElement instanceof EMFModelElement) { |
| final EMFModelElement emfModelElement = (EMFModelElement) modelElement; |
| if (sourceElement != null && gethasSemantic(sourceElement) != null) { |
| if (gethasSemantic(sourceElement).getSemanticId() != null) { |
| sourceElement = gethasSemantic(sourceElement).getSemanticId(); |
| } |
| } else if (sourceElement != null && getConceptDescription(sourceElement) != null) { |
| if (getConceptDescription(sourceElement).getIsCaseOf() != null && getConceptDescription(sourceElement).getIsCaseOf().isEmpty()) { |
| sourceElement = getConceptDescription(sourceElement).getIsCaseOf().get(0); |
| } |
| } |
| if (!(sourceElement instanceof Element)) { |
| final Element baseElement = UMLUtil.getBaseElement(sourceElement); |
| if (baseElement != null) {// in other case we will get an exeption somewhere |
| sourceElement = baseElement; |
| } |
| } |
| |
| if (gethasSemantic(sourceElement) != null || getConceptDescription(sourceElement) != null) { |
| |
| |
| HasSemantics has = gethasSemantic(sourceElement); |
| ConceptDescription cons = getConceptDescription(sourceElement); |
| |
| if (has != null && has.getSemanticId() == null) { |
| Element element = (Element) sourceElement; |
| getOperationExecutor(element).execute(new Runnable() { |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void run() { |
| |
| if (element instanceof Element) { |
| |
| Element container = element.getModel(); |
| EditingDomain domain = EMFHelper.resolveEditingDomain(container); |
| IElementType referenceElementType = ElementTypeRegistry.getInstance().getType(IAASElementTypes.REFERENCE_ID); |
| CreateElementRequest request = null; |
| |
| request = new CreateElementRequest((TransactionalEditingDomain) domain, container, referenceElementType); |
| |
| IElementEditService provider = ElementEditServiceUtils.getCommandProvider(container); |
| ICommand createReference = provider.getEditCommand(request); |
| if (createReference.canExecute()) { |
| domain.getCommandStack().execute(new GMFtoEMFCommandWrapper(createReference)); |
| Object result = createReference.getCommandResult().getReturnValue(); |
| Reference reference = getReference(result); |
| has.setSemanticId(reference); |
| } else { |
| System.out.println("can not execute command"); |
| } |
| } |
| |
| } |
| }, "message"); |
| // Create the Reference if the sourceElement is a HasSemantic |
| |
| |
| } else if (cons != null && (cons.getIsCaseOf() == null || cons.getIsCaseOf().isEmpty())) { |
| Element element = (Element) sourceElement; |
| getOperationExecutor(element).execute(new Runnable() { |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public void run() { |
| |
| if (element instanceof Element) { |
| |
| Element container = element.getModel(); |
| EditingDomain domain = EMFHelper.resolveEditingDomain(container); |
| IElementType referenceElementType = ElementTypeRegistry.getInstance().getType(IAASElementTypes.REFERENCE_ID); |
| CreateElementRequest request = null; |
| |
| request = new CreateElementRequest((TransactionalEditingDomain) domain, container, referenceElementType); |
| |
| IElementEditService provider = ElementEditServiceUtils.getCommandProvider(container); |
| ICommand createReference = provider.getEditCommand(request); |
| if (createReference.canExecute()) { |
| domain.getCommandStack().execute(new GMFtoEMFCommandWrapper(createReference)); |
| Object result = createReference.getCommandResult().getReturnValue(); |
| Reference reference = getReference(result); |
| cons.getIsCaseOf().add(reference); |
| } else { |
| System.out.println("can not execute command"); |
| } |
| } |
| |
| } |
| }, "message"); |
| // Create the Reference if the sourceElement is a HasSemantic |
| |
| |
| } |
| if (has != null) { |
| sourceElement = UMLUtil.getBaseElement(has.getSemanticId()); |
| feature = emfModelElement.getFeature("semanticId"); |
| } else if (cons != null) { |
| sourceElement = UMLUtil.getBaseElement(cons.getIsCaseOf().get(0)); |
| feature = emfModelElement.getFeature("isCaseOf"); |
| } |
| } |
| |
| |
| // Recreate the table widget, its adjuncts, and their layout |
| createWidgets(sourceElement, feature, contexts); |
| |
| // We need to refresh the parent composite to get the needed space |
| Composite parent = self.getParent(); |
| boolean found = false; |
| while (null != parent && !found) { |
| if (parent instanceof TabbedPropertyComposite) { |
| found = true; |
| } else { |
| parent.layout(true, true); |
| parent.redraw(); |
| parent.update(); |
| } |
| parent = parent.getParent(); |
| } |
| } |
| } |
| } |
| }; |
| } |
| |
| return dataSourceListener; |
| } |
| |
| /** |
| * This allows to get the table context as EObject (and avoid View). |
| * |
| * @param element |
| * The initial source element. |
| * @return The source element defining Table context. |
| * @since 2.1 |
| */ |
| protected EObject getEObjectAsTableContext(final EObject element) { |
| EObject result = element; |
| if (result instanceof View) { |
| result = ((View) result).getElement(); |
| } |
| return result; |
| } |
| |
| /** |
| * |
| * @param domain |
| * the editing domain to use |
| * @param resource |
| * the resource where the table must be saved |
| * @param table |
| * the table to add to the resource |
| * @return |
| * the command to add the table to the resource |
| */ |
| private static final Command addTableToResource(final TransactionalEditingDomain domain, final Resource resource, final Table table) { |
| return new RecordingCommand(domain) { |
| |
| @Override |
| protected void doExecute() { |
| resource.getContents().add(table); |
| } |
| }; |
| } |
| |
| /** |
| * @see org.eclipse.papyrus.uml.properties.widgets.NattablePropertyEditor#configureTable(org.eclipse.emf.transaction.TransactionalEditingDomain, org.eclipse.papyrus.infra.nattable.model.nattable.Table, org.eclipse.emf.ecore.EObject, |
| * org.eclipse.emf.ecore.EStructuralFeature, java.util.Collection, org.eclipse.emf.common.command.CompoundCommand) |
| * |
| * @param domain |
| * @param table |
| * @param sourceElement |
| * @param synchronizedFeature |
| * @param rows |
| * @param command |
| */ |
| |
| protected void configureTable(TransactionalEditingDomain domain, Table table, EObject sourceElement, EStructuralFeature synchronizedFeature, Collection<?> rows, CompoundCommand command) { |
| Assert.isNotNull(domain); |
| // 1. we register the context of the table |
| |
| Command setContextCommand = SetCommand.create(domain, table, NattablePackage.eINSTANCE.getTable_Context(), sourceElement); |
| command.append(setContextCommand); |
| if (TableHelper.isTreeTable(table) && null != rows && !rows.isEmpty()) {// add test on TreeTable to fix bug 476623 |
| final AbstractAxisProvider axisProvider = table.getCurrentRowAxisProvider(); |
| TableHeaderAxisConfiguration conf = (TableHeaderAxisConfiguration) HeaderAxisConfigurationManagementUtils.getRowAbstractHeaderAxisInTableConfiguration(table); |
| AxisManagerRepresentation rep = conf.getAxisManagers().get(0); |
| for (Object context : rows) { |
| addTreeItemAxis(domain, axisProvider, rep, context, command); |
| } |
| } |
| } |
| |
| /** |
| * This allow to add the tree item axis. |
| * |
| * @param axisProvider |
| * The axis provider. |
| * @param rep |
| * The axis manager representation. |
| * @param object |
| * The object to add. |
| */ |
| protected void addTreeItemAxis(final TransactionalEditingDomain domain, final AbstractAxisProvider axisProvider, final AxisManagerRepresentation rep, final Object object, final CompoundCommand command) { |
| final IAxis axis = ITreeItemAxisHelper.createITreeItemAxis(null, null, object, rep); |
| Command addCommand = AddCommand.create(getTableEditingDomain(), axisProvider, NattableaxisproviderPackage.eINSTANCE.getAxisProvider_Axis(), Collections.singleton(axis)); |
| command.append(addCommand); |
| } |
| |
| public IAtomicOperationExecutor getOperationExecutor(Object context) { |
| IAtomicOperationExecutor result; |
| if (context instanceof IAdaptable) { |
| result = ((IAdaptable) context).getAdapter(IAtomicOperationExecutor.class); |
| } else if (context != null) { |
| result = Platform.getAdapterManager().getAdapter(context, IAtomicOperationExecutor.class); |
| } else { |
| // We can't adapt null, of course, so we will have to settle for the default executor |
| result = null; |
| } |
| |
| if (result == null) { |
| result = IAtomicOperationExecutor.DEFAULT; |
| } |
| |
| return result; |
| } |
| } |