/************************************************************************** * 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.view; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.observable.map.IObservableMap; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.emf.databinding.EMFProperties; import org.eclipse.emf.databinding.FeaturePath; import org.eclipse.emf.databinding.IEMFListProperty; import org.eclipse.emf.databinding.edit.EMFEditProperties; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.jface.databinding.viewers.IViewerObservableValue; import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; import org.eclipse.jface.databinding.viewers.ObservableMapCellLabelProvider; import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider; import org.eclipse.jface.databinding.viewers.ObservableValueEditingSupport; import org.eclipse.jface.databinding.viewers.ViewerProperties; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ComboBoxViewerCellEditor; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.IEditorPart; import era.foss.erf.AttributeDefinition; import era.foss.erf.EraToolExtension; import era.foss.erf.ErfPackage; import era.foss.erf.SpecType; import era.foss.erf.ToolExtension; import era.foss.erf.View; import era.foss.erf.ViewElement; import era.foss.objecteditor.EraCommandStack; import era.foss.typeeditor.Activator; import era.foss.typeeditor.common.AbstractErfTypesForm; import era.foss.typeeditor.common.AddDeleteTableViewer; import era.foss.typeeditor.common.BindingCheckBox; import era.foss.typeeditor.common.Ui; import era.foss.typeeditor.view.layoutviewer.ViewLayoutViewer; import era.foss.ui.contrib.CheckingSelectionChangedListener; import era.foss.ui.contrib.ComboBoxViewerCellEditorSp; /** * The topmost UI class of the typeeditor plug-in: representing the overall dialog. * <p> * Structured by a tab folder for which it instantiates forms for DatatypeDefinitions and SpecificationTypes. * <p> * Instantiates the {@link EraCommandStack} for handling the OK and Cancel buttons. * */ public class ViewForm extends AbstractErfTypesForm { /** * Era Tool extension model object */ private EraToolExtension toolExtension; /** The databinding context for binding model elements to widgets show in this dialog */ DataBindingContext dataBindContext; /** Master object for observing the selected {@link View}s */ private IViewerObservableValue viewMaster; /** Master object for observing the selected {@link SpecType} */ private IViewerObservableValue specTypeMaster; /** Master object for observing the selected {@link ViewElement}s */ private IViewerObservableValue viewElementMaster; /** table viewer showing holding view elements */ private AddDeleteTableViewer viewElementTableViewer; /** gef viewer showing layout of view elements in a view */ ViewLayoutViewer viewLayoutViewer; /** * Checks if the {@link AttributeDefinition} refers to the same {@link SpecType} as is selected in * {@link specTypeMaster} */ class SpecTypeFilter extends ViewerFilter { @Override public boolean select( Viewer viewer, Object parentElement, Object element ) { assert (element instanceof ViewElement); ViewElement viewElement = (ViewElement)element; if( (ViewForm.this.specTypeMaster.getValue() != null) && ((viewElement.getAttributeDefinition() == null) || (viewElement.getAttributeDefinition() .getSpecType().equals( ViewForm.this.specTypeMaster.getValue() ))) ) { return true; } return false; } } /** * Creates a editor for {@link View} elements. * * @param parent the parent * @param editor the editor */ public ViewForm( Composite parent, IEditorPart editor ) { super( parent, editor, SWT.NONE ); // find Era specific tool extensions for( ToolExtension toolExtension : this.erfModel.getToolExtensions() ) { if( toolExtension.eClass().getClassifierID() == ErfPackage.ERA_TOOL_EXTENSION ) { this.toolExtension = (EraToolExtension)toolExtension; } } // The existence of the EraToolExtension object as part of the model is currently // guaranteed by the EraModelWizard that creates it explicitly assert (this.toolExtension != null); dataBindContext = new DataBindingContext(); this.setLayout( new GridLayout( 4, true ) ); createViewTableViewer( this ); createViewElementComposite( this ); createViewLayoutViewer( this ); createDetails( this ); } /** * Creates the table viewer for {@link View}s */ private void createViewTableViewer( Composite parent ) { AddDeleteTableViewer viewTableViewer = new AddDeleteTableViewer( parent, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION ); viewTableViewer.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true, 1, 2 ) ); viewTableViewer.setEditingDomain( editingDomain ); viewTableViewer.setElementInformation( toolExtension, ErfPackage.Literals.ERA_TOOL_EXTENSION__VIEWS, ErfPackage.Literals.VIEW ); ObservableListContentProvider cp = new ObservableListContentProvider(); viewTableViewer.setContentProvider( cp ); TableColumnLayout columnLayout = (TableColumnLayout)viewTableViewer.getTable().getParent().getLayout(); // create column with name of the view TableViewerColumn nameColumn = new TableViewerColumn( viewTableViewer, SWT.NONE ); columnLayout.setColumnData( nameColumn.getColumn(), new ColumnWeightData( 100, 70 ) ); nameColumn.getColumn().setResizable( false ); nameColumn.getColumn().setMoveable( false ); nameColumn.getColumn().setText( Ui.getUiName( ErfPackage.Literals.IDENTIFIABLE__LONG_NAME ) ); ui.bindColumn( nameColumn, new EStructuralFeature[]{ErfPackage.Literals.IDENTIFIABLE__LONG_NAME} ); // provide input for the table IEMFListProperty viewsProperty = EMFProperties.list( ErfPackage.Literals.ERA_TOOL_EXTENSION__VIEWS ); viewTableViewer.setInput( viewsProperty.observe( toolExtension ) ); viewTableViewer.getTable().select( 0 ); this.viewMaster = ViewerProperties.singleSelection().observe( viewTableViewer ); } /** * Creates the composite holding the selection of the {@link SpecType} and the table of the {@link ViewElement} */ private void createViewElementComposite( Composite parent ) { // composite holding the selection of the specType and the table of the viewElements Composite viewElementComposite = new Composite( parent, SWT.NONE ); viewElementComposite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true, 1, 2 ) ); viewElementComposite.setLayout( new GridLayout() ); Label specTypeLabel = new Label( viewElementComposite, SWT.NONE ); specTypeLabel.setText( Ui.getUiName( ErfPackage.Literals.SPEC_TYPE ) ); specTypeLabel.setLayoutData( new GridData( SWT.LEFT, SWT.BOTTOM, true, false ) ); createSpecTypeComboViewer( viewElementComposite ); Label viewElementsLabel = new Label( viewElementComposite, SWT.NONE ); viewElementsLabel.setText( Ui.getUiName( ErfPackage.Literals.VIEW__VIEW_ELEMENTS ) ); viewElementsLabel.setLayoutData( new GridData( SWT.LEFT, SWT.BOTTOM, true, false ) ); createViewElementTableViewer( viewElementComposite ); } /** * Create a Combo box for selecting the {@link SpecType} of the respective view * * @param parent parent composite */ private void createSpecTypeComboViewer( Composite parent ) { final ComboViewer specTypeComboViewer = new ComboViewer( parent, SWT.READ_ONLY ) { @Override protected void doUpdateItem( Widget data, Object element, boolean fullMap ) { // memorize the selection before updating the item, as the // update routine removes the selection... ISelection currentSelection = this.getSelection(); super.doUpdateItem( data, element, fullMap ); // set the selection to the previous value this.setSelection( currentSelection ); } }; ObservableListContentProvider contentProvider = new ObservableListContentProvider(); specTypeComboViewer.getControl().setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, false ) ); // set content provider specTypeComboViewer.setContentProvider( contentProvider ); // set label provider specTypeComboViewer.setLabelProvider( new ObservableMapLabelProvider( EMFProperties.value( ErfPackage.Literals.IDENTIFIABLE__LONG_NAME ) .observeDetail( contentProvider.getKnownElements() ) ) ); // set input IEMFListProperty specTypeProperty = EMFProperties.list( ErfPackage.Literals.CONTENT__SPEC_TYPES ); specTypeComboViewer.setInput( specTypeProperty.observe( this.erfModel.getCoreContent() ) ); specTypeMaster = ViewerProperties.singleSelection().observe( specTypeComboViewer ); if( erfModel.getCoreContent().getSpecTypes().size() > 0 ) { specTypeComboViewer.setSelection( new StructuredSelection( erfModel.getCoreContent() .getSpecTypes() .get( 0 ) ) ); } specTypeMaster.addValueChangeListener( new IValueChangeListener() { @Override public void handleValueChange( ValueChangeEvent event ) { viewElementTableViewer.refresh(); viewLayoutViewer.refresh(); } } ); } /** * Creates the table viewer for {@link ViewElements} * * @param parent parent composite */ private void createViewElementTableViewer( Composite parent ) { this.viewElementTableViewer = new AddDeleteTableViewer( parent, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION | AddDeleteTableViewer.NO_DESCRIPTION ) { @Override public void addElement() { this.elementOwner = (EObject)viewMaster.getValue(); super.addElement(); // is_a ViewElement ViewElement addedViewElement = (ViewElement)super.getElementAt( super.doGetItemCount() - 1 ); // default placement of views' elements addedViewElement.setEditorRowPosition( getCurrentMaxRowIdx() + 1 ); addedViewElement.setEditorColumnPosition( 0 ); addedViewElement.setEditorColumnSpan( 2 ); addedViewElement.setEditorRowSpan( 1 ); } /** * Calculates maximum row index of existing view elements * * @return maximum row index */ private int getCurrentMaxRowIdx() { int maxRowIdx = 0; for( int i = 0; i < super.doGetItemCount(); ++i ) { ViewElement iterViewElement = (ViewElement)super.getElementAt( i ); maxRowIdx = Math.max( maxRowIdx, iterViewElement.getEditorRowPosition() + (iterViewElement.getEditorRowSpan() - 1) ); } return maxRowIdx; } @Override protected void createButtonBar() { super.createButtonBar(); // FIXME @cpn create "add all" button } }; // the owner is null as it is set in the overridden addElement() method viewElementTableViewer.setElementInformation( (EObject)viewMaster.getValue(), ErfPackage.Literals.VIEW__VIEW_ELEMENTS, ErfPackage.Literals.VIEW_ELEMENT ); viewElementTableViewer.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true, 1, 2 ) ); viewElementTableViewer.setEditingDomain( editingDomain ); ObservableListContentProvider tableViewerContentProvider = new ObservableListContentProvider(); viewElementTableViewer.setContentProvider( tableViewerContentProvider ); TableColumnLayout columnLayout = (TableColumnLayout)viewElementTableViewer.getTable().getParent().getLayout(); // create column showing the Attribute Definition TableViewerColumn attributeDefinitionColumn = new TableViewerColumn( viewElementTableViewer, SWT.NONE ); columnLayout.setColumnData( attributeDefinitionColumn.getColumn(), new ColumnWeightData( 100, 70 ) ); attributeDefinitionColumn.getColumn().setResizable( false ); attributeDefinitionColumn.getColumn().setMoveable( false ); attributeDefinitionColumn.getColumn() .setText( Ui.getUiName( ErfPackage.Literals.VIEW_ELEMENT__ATTRIBUTE_DEFINITION ) ); // label provider for column showing the AttributeDefintion IValueProperty elementProperty = EMFEditProperties.value( editingDomain, FeaturePath.fromList( new EStructuralFeature[]{ ErfPackage.Literals.VIEW_ELEMENT__ATTRIBUTE_DEFINITION, ErfPackage.Literals.IDENTIFIABLE__LONG_NAME} ) ); IObservableMap attributeMap = elementProperty.observeDetail( tableViewerContentProvider.getKnownElements() ); attributeDefinitionColumn.setLabelProvider( new ObservableMapCellLabelProvider( attributeMap ) ); // editing support column showing the AttributeDefintion // Combo box: Create combo box to select choices for the reference ComboBoxViewerCellEditor combo = new ComboBoxViewerCellEditorSp( (Composite)viewElementTableViewer.getControl(), SWT.DROP_DOWN | SWT.READ_ONLY ); // Combo box: Set Content Provider; ObservableListContentProvider comboBoxContentProvider = new ObservableListContentProvider(); combo.setContentProvider( comboBoxContentProvider ); // Combo box: Set Label Provider combo.setLabelProvider( new ObservableMapLabelProvider( EMFProperties.value( ErfPackage.Literals.IDENTIFIABLE__LONG_NAME ) .observeDetail( comboBoxContentProvider.getKnownElements() ) ) ); // Combo box: set input from selected specType IEMFListProperty specAttributesProperty = EMFProperties.list( ErfPackage.Literals.SPEC_TYPE__SPEC_ATTRIBUTES ); combo.setInput( specAttributesProperty.observeDetail( specTypeMaster ) ); // Set editing support of table cell IValueProperty editorElementProperty = EMFEditProperties.value( editingDomain, ErfPackage.Literals.VIEW_ELEMENT__ATTRIBUTE_DEFINITION ); IValueProperty cellEditorProperty = ViewerProperties.singleSelection(); attributeDefinitionColumn.setEditingSupport( ObservableValueEditingSupport.create( viewElementTableViewer, dataBindContext, combo, cellEditorProperty, editorElementProperty ) ); // provide input for the table IEMFListProperty viewsProperty = EMFProperties.list( ErfPackage.Literals.VIEW__VIEW_ELEMENTS ); viewElementTableViewer.addFilter( new SpecTypeFilter() ); viewElementTableViewer.setInput( viewsProperty.observeDetail( viewMaster ) ); viewElementMaster = ViewerProperties.singleSelection().observe( viewElementTableViewer ); viewElementTableViewer.getTable().select( 0 ); } /** * Create graphical representation of the layout of the specType in the respective {@link View} * * @param parent parent composite */ private void createViewLayoutViewer( Composite parent ) { // composite holding the label and the composite with the widgets Composite layoutComposite = new Composite( parent, SWT.NONE ); layoutComposite.setLayout( new GridLayout( 1, true ) ); layoutComposite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true, 2, 1 ) ); // create label for detail viewer Label label = new Label( layoutComposite, SWT.NONE ); label.setLayoutData( new GridData( SWT.LEFT, SWT.TOP, true, false ) ); label.setText( Activator.INSTANCE.getString( "_UI_View_Layout_label" ) + ":" ); // create layout viewer this.viewLayoutViewer = new ViewLayoutViewer( editingDomain, layoutComposite ); viewLayoutViewer.getControl().setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) ); viewLayoutViewer.addFilter( new SpecTypeFilter() ); viewLayoutViewer.setContents( viewMaster ); viewLayoutViewer.setSelection( viewElementTableViewer.getSelection() ); // add listeners so that the selections get updated in each viewer viewLayoutViewer.addSelectionChangedListener( new CheckingSelectionChangedListener( viewElementTableViewer ) ); viewElementTableViewer.addSelectionChangedListener( new CheckingSelectionChangedListener( viewLayoutViewer ) ); } /** * Creates detailed view for settings of the selected {@link ViewElement} * * @param parent parent composite */ private void createDetails( Composite parent ) { // composite holding the label and the composite with the widgets Composite detailsComposite = new Composite( parent, SWT.NONE ); detailsComposite.setLayout( new GridLayout( 1, true ) ); detailsComposite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true, 2, 1 ) ); // create label for detail viewer Label label = new Label( detailsComposite, SWT.NONE ); label.setLayoutData( new GridData( SWT.LEFT, SWT.TOP, true, false ) ); label.setText( Activator.INSTANCE.getString( "_UI_Details_label" ) + ":" ); // Create composite holding the UI elements of the final Composite widgetComposite = new Composite( detailsComposite, SWT.BORDER ); widgetComposite.setLayout( new GridLayout( 4, true ) ); widgetComposite.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) ); if( viewElementMaster.getValue() != null ) { createDetailWidgets( widgetComposite ); } viewElementMaster.addValueChangeListener( new IValueChangeListener() { /** * Redraw the composite with the widgets */ @Override public void handleValueChange( ValueChangeEvent event ) { if( event.diff.getNewValue() == null ) { for( Control control : widgetComposite.getChildren() ) { control.dispose(); } } if( event.diff.getNewValue() != null && event.diff.getOldValue() == null ) { createDetailWidgets( widgetComposite ); } // we need this so that the modified content will be drawn widgetComposite.layout(); widgetComposite.redraw(); widgetComposite.update(); widgetComposite.getParent().layout(); widgetComposite.getParent().redraw(); widgetComposite.getParent().update(); } } ); } /** * Create widgets in the composite showing the details of an {@link ViewElement} * * @param parent parent composite */ private void createDetailWidgets( Composite parent ) { // create checkbox for editoShowLabel property createCheckbox( parent, ErfPackage.Literals.VIEW_ELEMENT__EDITOR_SHOW_LABEL ); } /** * Create a checkbox of a structural feature of the selected {@link ViewElement} * * @param parent parent composite * @param eStructuralFeature the */ private void createCheckbox( Composite parent, EStructuralFeature eStructuralFeature ) { // create label Label showLabelLabel = new Label( parent, SWT.NONE ); showLabelLabel.setText( Ui.getUiName( eStructuralFeature ) ); showLabelLabel.setLayoutData( new GridData( SWT.LEFT, SWT.CENTER, true, false ) ); // create checkbox BindingCheckBox showLabelCheckbox = new BindingCheckBox( parent, SWT.NONE ); showLabelCheckbox.bind( editingDomain, eStructuralFeature, viewElementMaster ); showLabelCheckbox.setLayoutData( new GridData( SWT.LEFT, SWT.DEFAULT, true, false ) ); } /* * private void createTextField( Composite parent, EStructuralFeature eStructuralFeature ) { // label for * editorRowNumber property Label defaultValueLabel = new Label( parent, SWT.NONE ); defaultValueLabel.setText( * Ui.getUiName( eStructuralFeature ) ); defaultValueLabel.setLayoutData( new GridData( SWT.LEFT, SWT.CENTER, true, * false ) ); * * // text field for editorRowNumber property BindingText defaultValueTextfield = new BindingText( parent, * SWT.BORDER ); defaultValueTextfield.bind( editingDomain, eStructuralFeature, viewElementMaster ); * defaultValueTextfield.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, false ) ); * * } */ }