/**************************************************************************
* ERA - Eclipse Requirements Analysis
* ==============================================
* Copyright (C) 2009-2013 by Georg Blaschke, Christoph P. Neumann
* and Bernd Haberstumpf (http://era.origo.ethz.ch)
**************************************************************************
* Licensed under the Eclipse Public License - v 1.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.eclipse.org/org/documents/epl-v10.html
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**************************************************************************
*/
package era.foss.typeeditor.datatype;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.emf.databinding.IEMFListProperty;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.command.ReplaceCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ViewerProperties;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ComboBoxViewerCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorPart;
import era.foss.erf.AttributeDefinition;
import era.foss.erf.DatatypeDefinition;
import era.foss.erf.ErfPackage;
import era.foss.erf.impl.ErfFactoryImpl;
import era.foss.typeeditor.common.AbstractErfTypesForm;
import era.foss.typeeditor.common.AddDeleteTableViewer;
import era.foss.typeeditor.common.Ui;
/**
* A form for editing {@link DatatypeDefinition}s.
* <p>
* Presents the list of {@link DatatypeDefinition}s in form of an {@link AddDeleteTableViewer}. Each
* {@link DatatypeDefinition} is presented as row which consists of a user-defined long name and its model-based class
* name. On row selection the description property of a {@link DatatypeDefinition} can be edited.
* <p>
* A properties viewer for any additional {@link DatatypeDefinition} attributes is instantiated.
* <p>
* The inner class {@link .DatatypeDefinitionContentProvider} is registered to the {@link AddDeleteTableViewer} and
* extracts all {@link DatatypeDefinition} elements from the ERF model -- by the model reference named "dataTypes".
* <p>
* The inner class {@link .DatatypeDefinitionLabelProvider} is registered to the {@link AddDeleteTableViewer} and
* provides the cell values from the {@link DatatypeDefinition} element.
*
*
* @see DatatypeDefinition
*/
final public class DatatypeDefinitionsForm extends AbstractErfTypesForm {
/** Table viewer containing the datatype definitions. */
private AddDeleteTableViewer tableViewer;
/**
* Instantiates a new datatype definitions form.
*
* @param parent the parent
* @param editor the editor
*/
public DatatypeDefinitionsForm( Composite parent, IEditorPart editor ) {
super( parent, editor, SWT.NONE );
// set-up layout
GridLayout gridLayout = new GridLayout( 2, true );
this.setLayout( gridLayout );
createTableViewer();
// setup Data type properties viewer
DataTypeDefinitionDetailViewer dataTypeDefinitionDetail = new DataTypeDefinitionDetailViewer(
this,
SWT.NONE,
editingDomain,
ViewerProperties.singleSelection().observe( tableViewer ) );
dataTypeDefinitionDetail.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
}
/**
* The Class DatatypeDefinitionEditingSupport.
*/
private class DatatypeDefinitionTypeEditingSupport extends EditingSupport {
/** The cell editor. */
private CellEditor cellEditor;
/**
* Instantiates a new datatype definition editing support.
*
* @param viewer the viewer
* @param column the column
*/
public DatatypeDefinitionTypeEditingSupport( ColumnViewer viewer ) {
super( viewer );
ComboBoxViewerCellEditor comboCellEditor = new ComboBoxViewerCellEditor(
((TableViewer)viewer).getTable(),
SWT.READ_ONLY );
comboCellEditor.setContentProvider( new TypesForDatatypeDefinitionComboContentProvider(
adapterFactory,
comboCellEditor.getViewer() ) );
comboCellEditor.setLabelProvider( new TypesForDatatypeDefinitionComboLabelProvider() );
comboCellEditor.setInput( editingDomain.getResourceSet() );
this.cellEditor = comboCellEditor;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object)
*/
@Override
protected boolean canEdit( Object element ) {
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.EditingSupport#getCellEditor(java.lang.Object)
*/
@Override
protected CellEditor getCellEditor( Object element ) {
return this.cellEditor;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object)
*/
@Override
protected Object getValue( Object element ) {
assert (element instanceof DatatypeDefinition);
DatatypeDefinition dataType = (DatatypeDefinition)element;
return dataType.eClass();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object, java.lang.Object)
*/
@Override
protected void setValue( Object element, Object value ) {
assert (element instanceof DatatypeDefinition);
DatatypeDefinition dataTypeDefinition = (DatatypeDefinition)element;
// the value must always be valid (ensured with ComboBox and SWT.READ_ONLY for the cells)
assert (value instanceof EClass);
if( ((EClass)value).getClassifierID() == dataTypeDefinition.eClass().getClassifierID() ) {
// the current data type is the same data type selected in the ComboBox
// therefore: DO NOTHING
return;
}
// List holding all AttributeDefinitions having this the DatatypeDefinition as type
List<AttributeDefinition> attributeDefintions = new ArrayList<AttributeDefinition>(
dataTypeDefinition.getAttributeDefinitions() );
// clear all adapters of the attribute definition, as these might belong to observables
// trying to access the elements of the wrong AttributeDefinition
for( AttributeDefinition attributeDefinition : attributeDefintions ) {
attributeDefinition.eAdapters().clear();
}
// create new a datatypeDefinition based on the value
DatatypeDefinition newDataTypeDefinition = (DatatypeDefinition)ErfFactoryImpl.eINSTANCE.create( (EClass)value );
// copy all properties common for all subclasses of DataTypeDefinition
for( EStructuralFeature datatypeDefinitionEStructuralFeature : ErfPackage.Literals.DATATYPE_DEFINITION.getEAllStructuralFeatures() ) {
if( datatypeDefinitionEStructuralFeature.isChangeable() == true ) {
Command setCommand = new SetCommand(
editingDomain,
newDataTypeDefinition,
datatypeDefinitionEStructuralFeature,
dataTypeDefinition.eGet( datatypeDefinitionEStructuralFeature ) );
editingDomain.getCommandStack().execute( setCommand );
}
}
// perform the REPLACE
// remark: the ReplaceCommand issues an REMOVE and ADD notification
Command replaceCommand = ReplaceCommand.create( editingDomain,
erfModel.getCoreContent(),
ErfPackage.Literals.CONTENT__DATA_TYPES,
dataTypeDefinition,
Collections.singleton( newDataTypeDefinition ) );
editingDomain.getCommandStack().execute( replaceCommand );
// adapt all AttributeDefintions refering to this DatatypeDefinition
for( AttributeDefinition attributeDefinition : attributeDefintions ) {
if( attributeDefinition == null ) {
attributeDefintions.remove( attributeDefinition );
} else {
Command setCommand = new SetCommand(
editingDomain,
attributeDefinition,
ErfPackage.Literals.ATTRIBUTE_DEFINITION__TYPE,
newDataTypeDefinition );
editingDomain.getCommandStack().execute( setCommand );
adaptAttributeDefintion( attributeDefinition );
}
}
// reset the cellEditor (remember: there is only one object, which handles all cell in its row)
// because the selected value must not propagate if another row is selected
((ComboBoxViewerCellEditor)this.cellEditor).setValue( null );
((CCombo)((ComboBoxViewerCellEditor)this.cellEditor).getControl()).clearSelection();
// set the selection of the viewer to the newly created datatype defintion object
super.getViewer().setSelection( new StructuredSelection( newDataTypeDefinition ) );
// refresh the tableViewer
super.getViewer().refresh();
}
}
/**
* Label Provider for the Type of the Datatype definition
*/
public class DatatypeDefinitionTypeLabelProvider extends CellLabelProvider {
@Override
public void update( ViewerCell cell ) {
assert (cell.getElement() instanceof DatatypeDefinition);
DatatypeDefinition dataType = (DatatypeDefinition)cell.getElement();
cell.setText( Ui.getUiName( dataType.eClass() ) );
}
}
/**
* Content provider for the combo box.
*/
public class TypesForDatatypeDefinitionComboContentProvider extends AdapterFactoryContentProvider {
/**
* Instantiates a new types for datatype definition combo content provider.
*
* @param adapterFactory the adapter factory
* @param viewer the viewer
*/
public TypesForDatatypeDefinitionComboContentProvider( AdapterFactory adapterFactory, Viewer viewer ) {
super( adapterFactory );
this.viewer = viewer;
}
/**
* Get list of typenames for the allowed DatatypeDefinition elements which have to be show in the combobox.
*
* @param object the object
* @return EClass[] of form (DatatypeDefinition x).eClass()
* @see org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements( Object object ) {
EClass supportedDatatypes[] = {
ErfPackage.Literals.DATATYPE_DEFINITION_INTEGER,
ErfPackage.Literals.DATATYPE_DEFINITION_STRING,
ErfPackage.Literals.DATATYPE_DEFINITION_BOOLEAN,
ErfPackage.Literals.DATATYPE_DEFINITION_ENUMERATION};
return supportedDatatypes;
}
}
/**
* Label provider for the Combo box.
*/
public class TypesForDatatypeDefinitionComboLabelProvider extends LabelProvider implements IBaseLabelProvider {
@Override
public String getText( Object element ) {
assert (element instanceof EClass);
return Ui.getUiName( (EClass)element );
}
}
/**
* Creates the table viewer.
*/
private void createTableViewer() {
tableViewer = new AddDeleteTableViewer( this, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION );
tableViewer.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
tableViewer.setEditingDomain( editingDomain );
tableViewer.setElementInformation( erfModel.getCoreContent(),
ErfPackage.Literals.CONTENT__DATA_TYPES,
ErfPackage.Literals.DATATYPE_DEFINITION_INTEGER );
ObservableListContentProvider cp = new ObservableListContentProvider();
tableViewer.setContentProvider( cp );
TableColumnLayout columnLayout = (TableColumnLayout)tableViewer.getTable().getParent().getLayout();
// create column with name of the datatype
TableViewerColumn nameColumn = new TableViewerColumn( tableViewer, SWT.NONE );
columnLayout.setColumnData( nameColumn.getColumn(), new ColumnWeightData( 100, 70 ) );
nameColumn.getColumn().setResizable( true );
nameColumn.getColumn().setMoveable( false );
nameColumn.getColumn().setText( Ui.getUiName( ErfPackage.Literals.IDENTIFIABLE__LONG_NAME ) );
EStructuralFeature[] structuralFeature = {ErfPackage.Literals.IDENTIFIABLE__LONG_NAME};
ui.bindColumn( nameColumn, structuralFeature );
// create column with type of the datatype
TableViewerColumn typeColumn = new TableViewerColumn( tableViewer, SWT.NONE );
columnLayout.setColumnData( typeColumn.getColumn(), new ColumnWeightData( 70, 30 ) );
typeColumn.getColumn().setResizable( false );
typeColumn.getColumn().setMoveable( false );
typeColumn.setEditingSupport( new DatatypeDefinitionTypeEditingSupport( tableViewer ) );
typeColumn.setLabelProvider( new DatatypeDefinitionTypeLabelProvider() );
typeColumn.getColumn().setText( typeEditorActivator.getString( "_UI_DataTypeDefinitionType_label" ) );
// provide input for the table
IEMFListProperty dataTypeProperty = EMFProperties.list( ErfPackage.Literals.CONTENT__DATA_TYPES );
tableViewer.setInput( dataTypeProperty.observe( erfModel.getCoreContent() ) );
}
}