/******************************************************************************* * Copyright (c) 2006-2013 The RCP Company and others. * 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: * The RCP Company - initial API and implementation *******************************************************************************/ package com.rcpcompany.uibindings.internal.utils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbenchPart; import com.rcpcompany.uibindings.utils.IAutoFormCreator; import com.rcpcompany.uibindings.utils.IBindingContextSelectionProvider; import com.rcpcompany.uibindings.utils.IDnDSupport; import com.rcpcompany.uibindings.utils.IFormCreator; /** * Implementation of {@link IAutoFormCreator}. * * @author Tonny Madsen, The RCP Company */ public class AutoFormCreator implements IAutoFormCreator { /** * The form used to create fields. */ private final IFormCreator myForm; /** * The base {@link EClass} of the form. */ private final EClass myEClass; /** * The value of the form. */ private final IObservableValue myValue; private final IValueChangeListener myValueChangeListener = new IValueChangeListener() { @Override public void handleValueChange(ValueChangeEvent event) { updateFields(); } }; /** * Section used for identification fields. */ private final IFormCreator myIdentificationSection; /** * Section used for identification fields. */ private final IFormCreator myBaseSection; /** * Section used for identification fields. */ private final IFormCreator myOptionalSection; /** * Constructs and returns a new auto form. * * @param value the value currently shown * @param title title used for the form * @param parent the parent composite * @param part the view part */ public AutoFormCreator(IObservableValue value, String title, Composite parent, IWorkbenchPart part) { myValue = value; final Object valueType = value.getValueType(); if (!(valueType instanceof EClass)) { myForm = null; myEClass = null; myIdentificationSection = null; myBaseSection = null; myOptionalSection = null; final Label label = new Label(parent, SWT.NONE); label.setText("Value type of IAutoFormCreator not subclass of EClass: " + valueType); // TODO: button for details return; } myEClass = (EClass) valueType; myForm = IFormCreator.Factory.createScrolledForm(value, parent, title); myIdentificationSection = myForm.addSection("Identification"); myBaseSection = myForm.addSection("Base Information"); myOptionalSection = myForm.addSection("Optional"); final IBindingContextSelectionProvider selectionProvider = IBindingContextSelectionProvider.Factory.adapt( myForm.getContext(), part.getSite(), true); selectionProvider.addControl(myForm.getContext().getTop(), myForm.getObservableValue()); IDnDSupport.Factory.installOn(myForm.getContext()); myValue.addValueChangeListener(myValueChangeListener); if (myValue.getValue() != null) { updateFields(); } } @Override public void dispose() { myValue.removeValueChangeListener(myValueChangeListener); myForm.dispose(); } @Override public IFormCreator getForm() { return myForm; } /** * Updates the fields of the form. */ protected void updateFields() { final Object value = myValue.getValue(); getFields(myEClass); } /** * Returns the fields for the specified class. * * @param eclass the class to find * @return the fields of the class */ public static ClassFieldData getFields(EClass eclass) { ClassFieldData d = FIELDS.get(eclass); if (d == null) { d = new ClassFieldData(eclass); FIELDS.put(eclass, d); } return d; } /** * Map with all the field data on a per class basis. */ public static final Map<EClass, ClassFieldData> FIELDS = new HashMap<EClass, ClassFieldData>(); /** * Data structure used to save information about fields in a specific class. */ public static class ClassFieldData { /** * Constructs and returns a new data object for the specified class. * * @param eclass the class of the object */ public ClassFieldData(EClass eclass) { myEClass = eclass; for (final EStructuralFeature sf : myEClass.getEAllStructuralFeatures()) { boolean required = false; if (sf.isRequired()) { required = true; } if (!required && sf instanceof EReference) { final EReference ref = (EReference) sf; if (ref.isContainer()) { required = true; } } if (required) { myRequiredFeatures.add(sf); } else { myOptionalFeatures.add(sf); } } } /** * @return the class */ public EClass getEClass() { return myEClass; } /** * List of all required features. */ private final List<EStructuralFeature> myRequiredFeatures = new ArrayList<EStructuralFeature>(); /** * List of all optional features. */ private final List<EStructuralFeature> myOptionalFeatures = new ArrayList<EStructuralFeature>(); private final EClass myEClass; } }